1

中间人攻击(Man-in-the-Middle (MITM) attack)

中间人攻击是一种常见的攻击手段,攻击者与通信双方分别建立连接,将双方想要交换的数据进行记录、篡改甚至丢弃。由于Http是明文传输,因此很容易遭受到中间人攻击。

一个通俗的例子

  • 假设 Tom 想和 Jerry 交换一些秘密信息,然而 Tom 又不想跑到 Jerry 家里,于是 Tom 叫来了邮递员,给了邮递员一封信。信的内容是希望 Jerry 给 Tom 一个盒子(这个盒子有两把钥匙)和其中一把钥匙(另一把在 Jerry 手里)。
  • 邮递员在拿到 Tom 给的信件以后,把 Tom 的信拆开看了一遍,了解到 Tom 希望 Jerry 给 Tom 一个有锁的盒子,又用另一个信封装了回去,并交给了 Jerry。
  • Jerry 在收到 Tom 的信(实际已经被邮递员拆阅过了)之后,给了邮递员一个有锁的盒子和其中一把钥匙。
  • 邮递员想知道他们的通信内容,于是他把 Jerry 给 Tom 的盒子换成了他自己的盒子,并附上了自己盒子中的一把钥匙,并在之后将自己的盒子交给了 Tom。
  • Tom 在收到盒子之后,以为这个盒子是 Jerry 给他的,于是就把秘密的信件放进了盒子里,并把钥匙留下了,之后又交给了邮递员。
  • 邮递员在拿到盒子之后,用自己的另一把钥匙打开盒子,看了里面的信件。之后将信件调换之后放进了 Jerry 给的盒子,交给了 Jerry。
  • Jerry 在拿到邮递员给他的盒子之后,并不知道这个盒子里的信件其实已经被邮递员调换过了,所以 Jerry 认为盒子里的信件是来自 Tom 且未被修改过的。之后 Jerry 把回信放进了盒子里,又交给了邮递员。
  • 邮递员再次调换盒子里的信件,交给了 Tom。

这是一个典型的中间人攻击的过程,在Http中,Tom是客户端,Jerry是服务端,而邮递员就是客户端跟服务端之间的实体(包括代理服务器,路由器、反向代理服务器等),两把钥匙分别是公钥和私钥。通信双方并不知道且很难发觉自己其实在和中间人攻击而非对方。在通信过程中,Tom和Jerry并没有验证对方的身份,这就导致了邮递员可以任意查看、修改或者丢弃双方的通信内容。

Http如何防范中间人攻击

非对称加密

用私钥对某个文件/某段消息的散列值进行签名就像一个人亲手在信件最后签上自己的名字一样,证明这份文件/这段消息确实来自自己的拥有者(因为公钥是公开的,私钥只有拥有者知道,所以如果能用其公开的公钥解开数字签名,那就证明这条消息确实来自于私钥的拥有者),这就可以确保消息是来自他所声称的那个实体。

不过有个问题,如果中间人在会话建立阶段把双方交换的真实公钥替换成自己的公钥,那么中间人还是可以篡改消息的内容而双方不知情。为了解决这个问题,需要找一个第三方来为双方确认身份。即数字证书跟CA(数字证书认证机构)。

数字证书就是申请人将一些必要的信息(包括公钥、姓名、电子邮件、有效期)等提供给CA,CA在通过各种手段确认申请人确实是他所声称的人之后,用自己的私钥对申请人所提供信息计算散列值进行加密,形成数字签名,附在证书最后,再将数字证书颁发给申请人,申请人就可以使用CA的证书想别人证明自己的身份了。对方收到数字证书之后,只需要用CA的公钥解密证书最后的签名得到加密之前的散列值,同计算数字证书中的信息的散列值,将两者进行对比,只要散列值一致,就证明这张数字证书是有效切且未被篡改。

通信过程中的安全性自下而上就是这样保证的:

  • 双方通信的内容的安全性是靠私钥加密,公钥解密来保证的,这一安全性由非对称加密的特性,即由私钥加密的信息只能使用对应的公钥才能解开来保证。由于私钥不会传递,只由拥有者知道,所以安全性就由公钥的正确性来保证。
  • 公钥由双方在通信初始化提供,但这时很容易被中间人替换掉,为了保证公钥的正确性,所以在发送公钥的时候也会提供对应的数字证书,用于验证这个公钥是对方的而不是中间人的。那么安全性就是由数字证书的正确性来保证了。
  • 数字证书是由上级CA签发给个人/组织的,上级CA用自己的私钥给个人证书进行签名,保证证书中的公钥不被篡改,而接受者需要用上级CA证书中的公钥来解密个人数字证书中的数字签名来验证证书中的公钥是否正确。那么安全性就是由上级CA证书的正确性保证了。
  • 但是上级CA证书也是由其上级CA签发的,这种信任关系一直到根证书。根证书没有上级CA为其签名,而是自签名,也就是他自身为自身签名,保证正确性。所以跟证书就是这个信任练最关键的部分。如果根证书泄露的话,其签名的所有证书及使用其签名的证书索签名的证书的安全性将不复存在。现在,安全性就是靠系统根证书的私钥不被泄露或者其公钥不被篡改来保证的。
  • 根证书不应该通过网络分发,因为通过网路分发的话,可能被中间人攻击。一般根证书都通过操作系统或浏览器分发,在操作系统中会内置很多根证书,但是最初的操作系统也不能通过网络分发,因为中间人可以修改系统中的根证书。所以要确保安全只能靠最原始的方法,当面交流。硬件厂商会和证书签发机构合作,在电脑、手机等设备出厂的时候在其操作系统中内置签发机构的根证书,再将这些设备分发出去,这样,这些设备的用户就可以安全地进行信息交换了。所以,安全性就依赖于这些设备在分发到消费者手中之前不会被恶意修改来保证了。

SSLTrip和HSTS

HTTP协议最初的时候是明文的,因为安全问题所以现在很多网站都在逐渐过渡到HTTPS,然而对于大部分使用者来说,他们并不知道HTTP和HTTPS的之前的区别,在浏览器输入地址的时候都是直接输入www.example.com而非https://www.example.com,在大部分情况下,如果一个网站使用了HTTPS,服务器会将这个请求使用301或者302状态码以及一个Location头部键将请求从80端口重定向至使用HTTPS的443端口,但是,如果中间人劫持了使用者的网络请求,那么中间人可以阻止客户端与服务器建立HTTPS连接,而是一直使用不安全的HTTP连接,而中间人和服务器建立正常的HTTP连接,让客户端以为自己和真实服务器通信。这种攻击手法称作SSLTrip

为了而解决这个问题,IETF(互联网工程任务小组)引入了一个策略,叫做HSTS(HTTP Strict Transport Security,HTTP严格传输安全)。HSTS的作用是强制客户端与服务端建立安全的HTTPS连接,而非不安全的HTTP连接。如果一个站点启用了HSTS策略,那么客户端在第一次与该站点建立连接之后,在为来一段时间内(由一个HTTP头部控制,这个头部为:Strict-Transport-Security),客户端与该站点的所有连接都会直接使用HTTPS,即使客户端访问的是HTTP,也会直接在客户端重定向到HTTPS连接。

如果站点没有启用HSTS,用户可以忽略证书无效(域名对不上、自签名、不在有效期)的警告,继续建立连接,而如果站点启用了 HSTS,那么用户即使想冒风险,浏览器也不会继续访问。

HSTS 可以很大程度上防止 SSLTrip 攻击,不过这样还是有个问题,那就是要启用 HSTS,浏览器至少要和服务器建立一次 HTTPS 连接,如果中间人一直阻止浏览器与服务器建立 HTTPS 连接,那么 HSTS 就失效了。解决这个问题有个办法,那就是将 HSTS 站点列表内置到浏览器中,这样只要浏览器离线判断该站点启用了 HSTS,就会跳过原先的 HTTP 重定向,直接发起 HTTPS 请求。

本内容摘自:
HTTPS中间人攻击及其防范

拒绝服务攻击(DDoS)

DDoS的攻击方式有很多种,最基本的DDoS攻击就是利用合理的服务请求来占用过多的服务资源,从而使合法用户无法得到服务的响应。

被DDoS攻击时的现象

  • 被攻击主机有大量等待的TCP连接
  • 网络中充斥着大量的无用的数据包,源地址为假
  • 制造高流量无用数据,造成网络拥塞,是受害主机无法正常和外界通讯
  • 利用受害主机提供的服务或传输协议上的缺陷,反复高速的发出特定的服务请求,是受害主机无法及时处理所有正常请求
  • 严重时会造成系统死机

clipboard.png

DDoS攻击实例--SYN Flood攻击

SYN-Flood是目前最流行的攻击手段。

SYN-Flood利用TCP/IP协议的固有漏洞。面向连接的TCP三次握手是SYN-Flood存在的基础。
clipboard.png

如上图图,在第一步中,客户端向服务端提出连接请求。这时TCP SYN标志置位。客户端告诉服务端序列号区域合法,需要检查。客户端在TCP报头的序列号区中插入自己的ISN。服务端收到该TCP分段后,在第二步以自己的ISN回应(SYN标志置位),同时确认收到客户端的第一个TCP分段(ACK标志置位)。在第三步中,客户端确认收到服务端的ISN(ACK标志置位)。到此为止建立完整的TCP连接,开始全双工模式的数据传输过程。

clipboard.png

假设一个用户向服务器发送了SYN报文后突然死机或掉线,那么服务器在发出SYN+ACK应答报文后是无法收到客户端的ACK报文的(第三次握手无法完成),这种情况下服务器端一般会重试(再次发送SYN+ACK给客户端)并等待一段时间后丢弃这个未完成的连接,这段时间的长度我们称为SYN Timeout,一般来说这个时间是分钟的数量级(大约为30秒-2分钟);一个用户出现异常导致服务器的一个线程等待1分钟并不是什么很大的问题,但如果有一个恶意的攻击者大量模拟这种情况,服务器端将为了维护一个非常大的半连接列表而消耗非常多的资源—-数以万计的半连接,即使是简单的保存并遍历也会消耗非常多的CPU时间和内存,何况还要不断对这个列表中的IP进行SYN+ACK的重试。实际上如果服务器的TCP/IP栈不够强大,最后的结果往往是堆栈溢出崩溃—即使服务器端的系统足够强大,服务器端也将忙于处理攻击者伪造的TCP连接请求而无暇理睬客户的正常请求(毕竟客户端的正常请求比率非常之小),此时从正常客户的角度看来,服务器失去响应,这种情况我们称做:服务器端受到了SYN Flood攻击(SYN洪水攻击)。

DDoS的防范

主机上的设置
几乎所有的主机平台都有抵御DDoS的设置,基本的有几种:

  • 关闭不必要的服务
  • 限制同时打开的SYN半连接数目
  • 缩短SYN半连接的time out时间
  • 及时更新系统补丁

网络设备上的设置

  • 防火墙

    • 禁止对主机的非开放服务的访问
    • 限制同时打开的SYN最大连接数
    • 限制特定IP地址的访问
    • 启用防火墙的防DDoS属性
    • 严格限制对外开放的服务器的向外访问

本内容摘自:
分布式拒绝服务攻击(DDoS)原理及防范

XSS攻击

SQL注入攻击

SQL注入是一种危害极大的攻击形势,虽然危害很大,但是防御却远没有XSS那么难。

原因

SQL注入的漏洞存在,就是拼接SQL参数,也就是将用于输入的查询参数,直接拼接在SQL语句中,导致了SQL注入漏洞。

例子

String sql = "SELECT id,no FROM user WHERE id = " + id;

其中id是用户输入的参数,那么如果用户输入2,那么上面查到的是一条数据,如果用户输入的是"2 or 1 = 1"进行SQL注入攻击,那么即将user表的所有记录都查找出来了。

SQL注入的防御

采用预编译和绑定变量
    String sql = "SELECT id,no FROM user WHERE id = ?";
    PreparedStatement ps = conn.preparedStatement(sql);
    ps.setInt(1,id);
    ps.executuQuery();

原因:采用了PrepareStatement,就会将sql语句:"SELECT id,no FROM user WHERE id = ?"`预先编译好,也就是SQL引擎预先进行语法分析,产生语法书,声称执行计划,也就是说,后面你输入的参数,无论输入什么,都不会影响该SQL语句的语法结构,后面输入的参数,绝不会被作为sql命令来执行,只会被当做字符串面值参数。

在实际项目中,一般都是采用各种框架,比如ibatis,hibernate,mybatis等,他们一般默认就是sql预编译。对于ibatis/mybatis,如果使用#{name}形式的,那么就是SQL预编译,使用${name},就不是SQL预编译。

mybatis中的#跟$:
#{}:解析为一个JDBC预编译语句的参数标识符,一个#{}被解析为一个参数标识符。
${}:仅仅作为一个纯粹的String替换,在动态SQL解析阶段进行变量替换。

eg:

    -- id = 123
    SELECT id,no FROM user WHERE id = #{id} -- > '123'
    SELECT id,no FROM user WHERE id = ${id} -- >  123

本内容参考:
sql注入防御方法总结
Mybatis 中$与#的区别


dack
98 声望18 粉丝

一直在路上


« 上一篇
算法-剑指offer
下一篇 »
Java基础