web开发常见的几大安全问题

一、SQL注入

SQL注入是一种常见的Web安全漏洞,攻击者利用这个漏洞,可以访问或修改数据,或者利用潜在的数据库漏洞进行攻击。SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。

1.SQL注入的原理

我们先举一个万能钥匙的例子来说明其原理:

<form action="/login" method="POST">
    <p>Username: <input type="text" name="username" /></p>
    <p>Password: <input type="password" name="password" /></p>
    <p><input type="submit" value="登陆" /></p>
</form>

后端的 SQL 语句可能是如下这样的:

let querySQL = `
    SELECT *
    FROM user
    WHERE username='${username}'
    AND psw='${password}'
`;
// 接下来就是执行 sql 语句...

这是我们经常见到的登录页面,但如果有一个恶意攻击者输入的用户名是 admin' --,密码随意输入,就可以直接登入系统了。why! ----这就是SQL注入

我们之前预想的SQL 语句是:

SELECT * FROM user WHERE username='admin' AND psw='password'

但是恶意攻击者用奇怪用户名将你的 SQL 语句变成了如下形式:

SELECT * FROM user WHERE username='admin' --' AND psw='xxxx'

在 SQL 中,' --是闭合和注释的意思,-- 是注释后面的内容的意思,所以查询语句就变成了:

SELECT * FROM user WHERE username='admin'

所谓的万能密码,本质上就是SQL注入的一种利用方式。

一次SQL注入的过程包括以下几个过程:

  • 获取用户请求参数
  • 拼接到代码当中
  • SQL语句按照我们构造参数的语义执行成功

SQL注入的必备条件:
1.可以控制输入的数据
2.服务器要执行的代码拼接了控制的数据

我们会发现SQL注入流程中与正常请求服务器类似,只是黑客控制了数据,构造了SQL查询,而正常的请求不会SQL查询这一步,SQL注入的本质:数据和代码未分离,即数据当做了代码来执行。

2.危害

  • 获取数据库信息
    • 管理员后台用户名和密码
    • 获取其他数据库敏感信息:用户名、密码、手机号码、身份证、银行卡信息……
    • 整个数据库:脱裤
  • 获取服务器权限
  • 植入Webshell,获取服务器后门
  • 读取服务器敏感文件

3.如何防御

  • 严格限制Web应用的数据库的操作权限,给此用户提供仅仅能够满足其工作的最低权限,从而最大限度的减少注入攻击对数据库的危害
  • 后端代码检查输入的数据是否符合预期,严格限制变量的类型,例如使用正则表达式进行一些匹配处理。
  • 字符串长度验证,仅接受指定长度范围内的变量值。sql注入脚本必然会大大增加输入变量的长度,通过长度限制,比如用户名长度为 8 到 20 个字符之间,超过就判定为无效值。
  • 对进入数据库的特殊字符(',",,<,>,&,*,; 等)进行转义处理,或编码转换。基本上所有的后端语言都有对字符串进行转义处理的方法,比如 lodash 的 lodash._escapehtmlchar 库。
  • 所有的查询语句建议使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到 SQL 语句中,即不要直接拼接 SQL 语句。例如 Node.js 中的 mysqljs 库的 query 方法中的 ? 占位参数。
  • 框架防御: mybatis

    ① # 符号作用为 将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。

    如:where user_id= #{id}

    如果传入的值是111,那么解析成sql时的值为 where id ="111"

    如果传入的值是 1’=or ’1’=‘1’ ,则解析成的sql为 whereid “1’=or ’1’=‘1’ “

    ② $ 符号则是将传入的数据直接生成在sql中。

    如:where user_id= ‘${id}’

    如果传入的值是111,那么解析成sql时的值为 where id =‘111’

    如果传入的值是 1’=or ’1’=‘1’,则解析成的sql为 where _id =‘1’or ’1’=1’

    结论:# 符号能够防止SQL注入, $符号无法防止SQL注入,$ 符号一般用于传入数据库对象,例如传入表名

 

二、XSS

XSS (Cross-Site Scripting),跨站脚本攻击,因为缩写和 CSS重叠,所以只能叫 XSS。跨站脚本攻击是指通过存在安全漏洞的Web网站注册用户的浏览器内运行非法的HTML标签或JavaScript进行的一种攻击。

跨站脚本攻击有可能造成以下影响:

  • 利用虚假输入表单骗取用户个人信息。
  • 利用脚本窃取用户的Cookie值,被害者在不知情的情况下,帮助攻击者发送恶意请求。
  • 显示伪造的文章或图片。

XSS 的原理是恶意攻击者往 Web 页面里插入恶意可执行网页脚本代码,当用户浏览该页之时,嵌入其中 Web 里面的脚本代码会被执行,从而可以达到攻击者盗取用户信息或其他侵犯用户安全隐私的目的

XSS 的攻击方式千变万化,但还是可以大致细分为几种类型。

1.非持久型 XSS(反射型 XSS )

非持久型 XSS 漏洞,一般是通过给别人发送带有恶意脚本代码参数的 URL,当 URL 地址被打开时,特有的恶意代码参数被 HTML 解析、执行。

举一个例子,比如页面中包含有以下代码:

<select>
    <script>
        document.write(''
            + '<option value=1>'
            +     location.href.substring(location.href.indexOf('default=') + 8)
            + '</option>'
        );
        document.write('<option value=2>English</option>');
    </script>
</select>

攻击者可以直接通过 URL (类似:https://xxx.com/xxx?default=<script>alert(document.cookie)</script>) 注入可执行的脚本代码。不过一些浏览器如Chrome其内置了一些XSS过滤器,可以防止大部分反射型XSS攻击。

非持久型 XSS 漏洞攻击有以下几点特征:

  • 即时性,不经过服务器存储,直接通过 HTTP 的 GET 和 POST 请求就能完成一次攻击,拿到用户隐私数据。
  • 攻击者需要诱骗点击,必须要通过用户点击链接才能发起
  • 反馈率低,所以较难发现和响应修复
  • 盗取用户敏感保密信息

为了防止出现非持久型 XSS 漏洞,需要确保这么几件事情:

  • Web 页面渲染的所有内容或者渲染的数据都必须来自于服务端。
  • 尽量不要从 URLdocument.referrerdocument.forms 等这种 DOM API 中获取数据直接渲染。
  • 尽量不要使用 evalnew Function()document.write()document.writeln()window.setInterval()window.setTimeout()innerHTMLdocument.createElement() 等可执行字符串的方法。
  • 如果做不到以上几点,也必须对涉及 DOM 渲染的方法传入的字符串参数做 escape 转义。
  • 前端渲染的时候对任何的字段都需要做 escape 转义编码。

2.持久型 XSS(存储型 XSS)

持久型 XSS 漏洞,一般存在于 Form 表单提交等交互功能,如文章留言,提交文本信息等,黑客利用的 XSS 漏洞,将内容经正常功能提交进入数据库持久保存,当前端页面获得后端从数据库中读出的注入代码时,恰好将其渲染执行。

举个例子,对于评论功能来说,就得防范持久型 XSS 攻击,因为我可以在评论中输入以下内容

主要注入页面方式和非持久型 XSS 漏洞类似,只不过持久型的不是来源于 URL,referer,forms 等,而是来源于后端从数据库中读出来的数据 。持久型 XSS 攻击不需要诱骗点击,黑客只需要在提交表单的地方完成注入即可,但是这种 XSS 攻击的成本相对还是很高。

攻击成功需要同时满足以下几个条件:

  • POST 请求提交表单后端没做转义直接入库。
  • 后端从数据库中取出数据没做转义直接输出给前端。
  • 前端拿到后端数据没做转义直接渲染成 DOM。

持久型 XSS 有以下几个特点:

  • 持久性,植入在数据库中
  • 盗取用户敏感私密信息
  • 危害面广

3.如何防御

对于 XSS 攻击来说,通常有两种方式可以用来防御。

1) CSP

CSP 本质上就是建立白名单,开发者明确告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则,如何拦截是由浏览器自己实现的。我们可以通过这种方式来尽量减少 XSS 攻击。

通常可以通过两种方式来开启 CSP:

  • 设置 HTTP Header 中的 Content-Security-Policy
  • 设置 meta 标签的方式

这里以设置 HTTP Header 来举例:

  • 只允许加载本站资源
Content-Security-Policy: default-src 'self'
  • 只允许加载 HTTPS 协议图片
Content-Security-Policy: img-src https://*
  • 允许加载任何来源框架
Content-Security-Policy: child-src 'none'

如需了解更多属性,请查看Content-Security-Policy文档

对于这种方式来说,只要开发者配置了正确的规则,那么即使网站存在漏洞,攻击者也不能执行它的攻击代码,并且 CSP 的兼容性也不错。

2) 转义字符

用户的输入永远不可信任的,最普遍的做法就是转义输入输出的内容,对于引号、尖括号、斜杠进行转义

function escape(str) {
  str = str.replace(/&/g, '&amp;')
  str = str.replace(/</g, '&lt;')
  str = str.replace(/>/g, '&gt;')
  str = str.replace(/"/g, '&quto;')
  str = str.replace(/'/g, '&#39;')
  str = str.replace(/`/g, '&#96;')
  str = str.replace(/\//g, '&#x2F;')
  return str
}

但是对于显示富文本来说,显然不能通过上面的办法来转义所有字符,因为这样会把需要的格式也过滤掉。对于这种情况,通常采用白名单过滤的办法,当然也可以通过黑名单过滤,但是考虑到需要过滤的标签和标签属性实在太多,更加推荐使用白名单的方式。

const xss = require('xss')
let html = xss('<h1 id="title">XSS Demo</h1><script>alert("xss");</script>')
// -> <h1>XSS Demo</h1>&lt;script&gt;alert("xss");&lt;/script&gt;
console.log(html)

以上示例使用了 js-xss 来实现,可以看到在输出中保留了 h1 标签且过滤了 script 标签。

3) HttpOnly Cookie。

这是预防XSS攻击窃取用户cookie最有效的防御手段。Web应用程序在设置cookie时,将其属性设为HttpOnly,就可以避免该网页的cookie被客户端恶意JavaScript窃取,保护用户cookie信息。

 

三、CSRF

 

CSRF(Cross Site Request Forgery),即跨站请求伪造,是一种常见的Web攻击,它利用用户已登录的身份,在用户毫不知情的情况下,以用户的名义完成非法操作。

 

1. CSRF攻击的原理

 

下面先介绍一下CSRF攻击的原理:

 

 

完成 CSRF 攻击必须要有三个条件:

 

  • 用户已经登录了站点 A,并在本地记录了 cookie
  • 在用户没有登出站点 A 的情况下(也就是 cookie 生效的情况下),访问了恶意攻击者提供的引诱危险站点 B (B 站点要求访问站点A)。
  • 站点 A 没有做任何 CSRF 防御

 

我们来看一个例子: 当我们登入转账页面后,突然眼前一亮惊现"XXX隐私照片,不看后悔一辈子"的链接,耐不住内心躁动,立马点击了该危险的网站(页面代码如下图所示),但当这页面一加载,便会执行submitForm这个方法来提交转账请求,从而将10块转给黑客。

 

 

2.如何防御

 

防范 CSRF 攻击可以遵循以下几种规则:

 

  • Get 请求不对数据进行修改
  • 不让第三方网站访问到用户 Cookie
  • 阻止第三方网站请求接口
  • 请求时附带验证信息,比如验证码或者 Token

 

1) SameSite

 

可以对 Cookie 设置 SameSite 属性。该属性表示 Cookie 不随着跨域请求发送,可以很大程度减少 CSRF 的攻击,但是该属性目前并不是所有浏览器都兼容。

 

2) Referer Check

 

HTTP Referer是header的一部分,当浏览器向web服务器发送请求时,一般会带上Referer信息告诉服务器是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理。可以通过检查请求的来源来防御CSRF攻击。正常请求的referer具有一定规律,如在提交表单的referer必定是在该页面发起的请求。所以通过检查http包头referer的值是不是这个页面,来判断是不是CSRF攻击

 

但在某些情况下如从https跳转到http,浏览器处于安全考虑,不会发送referer,服务器就无法进行check了。若与该网站同域的其他网站有XSS漏洞,那么攻击者可以在其他网站注入恶意脚本,受害者进入了此类同域的网址,也会遭受攻击。出于以上原因,无法完全依赖Referer Check作为防御CSRF的主要手段。但是可以通过Referer Check来监控CSRF攻击的发生。

 

3) Anti CSRF Token

 

目前比较完善的解决方案是加入Anti-CSRF-Token。即发送请求时在HTTP 请求中以参数的形式加入一个随机产生的token,并在服务器建立一个拦截器来验证这个token。服务器读取浏览器当前域cookie中这个token值,会进行校验该请求当中的token和cookie当中的token值是否都存在且相等,才认为这是合法的请求。否则认为这次请求是违法的,拒绝该次服务。

 

这种方法相比Referer检查要安全很多,token可以在用户登陆后产生并放于session或cookie中,然后在每次请求时服务器把token从session或cookie中拿出,与本次请求中的token 进行比对。由于token的存在,攻击者无法再构造出一个完整的URL实施CSRF攻击。但在处理多个页面共存问题时,当某个页面消耗掉token后,其他页面的表单保存的还是被消耗掉的那个token,其他页面的表单提交时会出现token错误。

 

4) 验证码

 

应用程序和用户进行交互过程中,特别是账户交易这种核心步骤,强制用户输入验证码,才能完成最终请求。在通常情况下,验证码够很好地遏制CSRF攻击。但增加验证码降低了用户的体验,网站不能给所有的操作都加上验证码。所以只能将验证码作为一种辅助手段,在关键业务点设置验证码。

 

四、点击劫持

 

点击劫持是一种视觉欺骗的攻击手段。攻击者将需要攻击的网站通过 iframe 嵌套的方式嵌入自己的网页中,并将 iframe 设置为透明,在页面中透出一个按钮诱导用户点击。

 

1. 特点

 

  • 隐蔽性较高,骗取用户操作
  • "UI-覆盖攻击"
  • 利用iframe或者其它标签的属性

 

2. 点击劫持的原理

 

用户在登陆 A 网站的系统后,被攻击者诱惑打开第三方网站,而第三方网站通过 iframe 引入了 A 网站的页面内容,用户在第三方网站中点击某个按钮(被装饰的按钮),实际上是点击了 A 网站的按钮。
接下来我们举个例子:我在优酷发布了很多视频,想让更多的人关注它,就可以通过点击劫持来实现

 

iframe {
width: 1440px;
height: 900px;
position: absolute;
top: -0px;
left: -0px;
z-index: 2;
-moz-opacity: 0;
opacity: 0;
filter: alpha(opacity=0);
}
button {
position: absolute;
top: 270px;
left: 1150px;
z-index: 1;
width: 90px;
height:40px;
}
</style>
......
<button>点击脱衣</button>
<img src="http://pic1.win4000.com/wallpaper/2018-03-19/5aaf2bf0122d2.jpg">
<iframe src="http://i.youku.com/u/UMjA0NTg4Njcy" scrolling="no"></iframe>

 

 

从上图可知,攻击者通过图片作为页面背景,隐藏了用户操作的真实界面,当你按耐不住好奇点击按钮以后,真正的点击的其实是隐藏的那个页面的订阅按钮,然后就会在你不知情的情况下订阅了。

 

 

3. 如何防御

 

1)X-FRAME-OPTIONS

 

X-FRAME-OPTIONS是一个 HTTP 响应头,在现代浏览器有一个很好的支持。这个 HTTP 响应头 就是为了防御用 iframe 嵌套的点击劫持攻击。

 

该响应头有三个值可选,分别是

 

  • DENY,表示页面不允许通过 iframe 的方式展示
  • SAMEORIGIN,表示页面可以在相同域名下通过 iframe 的方式展示
  • ALLOW-FROM,表示页面可以在指定来源的 iframe 中展示

 

2)JavaScript 防御

 

对于某些远古浏览器来说,并不能支持上面的这种方式,那我们只有通过 JS 的方式来防御点击劫持了,Frame Busting :这种方式是通过写JavaScript来禁止iframe嵌套,但是可以轻易饶过。

 

<head>
  <style id="click-jack">
    html {
      display: none !important;
    }
  </style>
</head>
<body>
  <script>
    if (self == top) {
      var style = document.getElementById('click-jack')
      document.body.removeChild(style)
    } else {
      top.location = self.location
    }
  </script>
</body>

 

以上代码的作用就是当通过 iframe 的方式加载页面时,攻击者的网页直接不显示所有内容了。

 

给大家推荐一个好用的BUG监控工具Fundebug,欢迎免费试用!

 

五、URL跳转漏洞

 

定义:借助未验证的URL跳转,将应用程序引导到不安全的第三方区域,从而导致的安全问题。

 

1.URL跳转漏洞原理

 

黑客利用URL跳转漏洞来诱导安全意识低的用户点击,导致用户信息泄露或者资金的流失。其原理是黑客构建恶意链接(链接需要进行伪装,尽可能迷惑),发在QQ群或者是浏览量多的贴吧/论坛中。
安全意识低的用户点击后,经过服务器或者浏览器解析后,跳到恶意的网站中。

 

 

恶意链接需要进行伪装,经常的做法是熟悉的链接后面加上一个恶意的网址,这样才迷惑用户。

 

 

诸如伪装成像如下的网址,你是否能够识别出来是恶意网址呢?

 

http://gate.baidu.com/index?act=go&url=http://t.cn/RVTatrd
http://qt.qq.com/safecheck.html?flag=1&url=http://t.cn/RVTatrd
http://tieba.baidu.com/f/user/passport?jumpUrl=http://t.cn/RVTatrd

 

2.实现方式:

 

  • Header头跳转
  • Javascript跳转
  • META标签跳转

 

这里我们举个Header头跳转实现方式:

 

<?php
$url=$_GET['jumpto'];
header("Location: $url");
?>
http://www.wooyun.org/login.php?jumpto=http://www.evil.com

 

这里用户会认为www.wooyun.org都是可信的,但是点击上述链接将导致用户最终访问www.evil.com这个恶意网址。

 

3.如何防御

 

1)referer的限制

 

如果确定传递URL参数进入的来源,我们可以通过该方式实现安全限制,保证该URL的有效性,避免恶意用户自己生成跳转链接

 

2)加入有效性验证Token

 

我们保证所有生成的链接都是来自于我们可信域的,通过在生成的链接里加入用户不可控的Token对生成的链接进行校验,可以避免用户生成自己的恶意链接从而被利用,但是如果功能本身要求比较开放,可能导致有一定的限制。

 

 

六、OS命令注入攻击

OS命令注入和SQL注入差不多,只不过SQL注入是针对数据库的,而OS命令注入是针对操作系统的。OS命令注入攻击指通过Web应用,执行非法的操作系统命令达到攻击的目的。只要在能调用Shell函数的地方就有存在被攻击的风险。倘若调用Shell时存在疏漏,就可以执行插入的非法命令。

命令注入攻击可以向Shell发送命令,让Windows或Linux操作系统的命令行启动程序。也就是说,通过命令注入攻击可执行操作系统上安装着的各种程序。

1.原理

黑客构造命令提交给web应用程序,web应用程序提取黑客构造的命令,拼接到被执行的命令中,因黑客注入的命令打破了原有命令结构,导致web应用执行了额外的命令,最后web应用程序将执行的结果输出到响应页面中。

我们通过一个例子来说明其原理,假如需要实现一个需求:用户提交一些内容到服务器,然后在服务器执行一些系统命令去返回一个结果给用户

// 以 Node.js 为例,假如在接口中需要从 github 下载用户指定的 repo
const exec = require('mz/child_process').exec;
let params = {/* 用户输入的参数 */};
exec(`git clone ${params.repo} /some/path`);

如果 params.repo 传入的是 https://github.com/admin/admin.github.io.git 确实能从指定的 git repo 上下载到想要的代码。
但是如果 params.repo 传入的是 https://github.com/xx/xx.git && rm -rf /* && 恰好你的服务是用 root 权限起的就糟糕了。

2.如何防御

    • 后端对前端提交内容进行规则限制(比如正则表达式)。
    • 在调用系统命令前对所有传入参数进行命令行参数转义过滤。
    • 不要直接拼接命令语句,借助一些工具做拼接、转义预处理,例如 Node.js 的 shell-escape npm

 

七、DOS攻击

1、概念的理解

 DoS:Denial of Service,拒绝服务,即无法及时接收并处理外界合法请求。

DoS攻击:指造成DoS的攻击行为,目的是使攻击目标计算机无法提供正常的服务。最常见的DoS攻击有计算机网络带宽攻击和连通性攻击。其中,带宽攻击是指以极大通信量冲击通往目标计算机的网络,使得所有可用网络资源都被消耗殆尽,导致合法的用户请求无法通过,无法到达目标计算机。而连通性攻击则是指用大量的连接请求攻击目标计算机,使得所有可用的操作系统资源都被消耗殆尽,导致目标计算机无法处理合法用户的请求。

DDoS攻击:DDoS即Distributed Denial of Service,DDoS攻击即是分布式DoS攻击。攻击者借助客户/服务器技术,控制并利用多个傀儡机(肉鸡),对一个或多个攻击目标发起DDoS攻击,从而成倍地提高DoS攻击的威力。

DRDoS攻击:DRDoS即Distributed Reflection Denial of Service,DRDoS攻击即是分布式反射DoS攻击。DRDoS攻击与DoS攻击、DDoS攻击不同,它不是直接对攻击目标发起请求,而是通过IP欺骗,发送大量源IP地址为攻击目标IP地址的数据包给攻击主机(第三方),然后攻击主机对IP地址源(即攻击目标)做出大量回应,从而形成DoS攻击。攻击者往往会选择那些响应包远大于请求包的第三方服务来利用,以达到放大反射攻击的效果,这样的服务包括DNS、NTP、SSDP、Chargen、Memcached等。

       今天最常见的DoS攻击有对计算机网络的带宽攻击和连通性攻击。带宽攻击指以极大的通信量冲击网络,使得所有可用网络资源都被消耗殆尽,最后导致合法的用户请求无法通过。连通性攻击指用大量的连接请求冲击计算机,使得所有可用的操作系统资源都被消耗殆尽,最终计算机无法再处理合法用户的请求。

       传统上,攻击者所面临的主要问题是网络带宽,由于较小的网络规模和较慢的网络速度的限制,攻击者无法发出过多的请求。虽然类似“the ping of death”的攻击类型只需要较少量的包就可以摧毁一个没有打过补丁的UNIX系统,但大多数的DoS攻击还是需要相当大的带宽的,而以个人为单位的黑客们很难使用高带宽的资源。为了克服这个缺点,DoS攻击者开发了分布式的攻击。攻击者简单利用工具集合许多的网络带宽来同时对同一个目标发动大量的攻击请求,这就是DDoS攻击。

无论是DoS攻击还是DDoS攻击,简单的看,都只是一种破坏网络服务的黑客方式,虽然具体的实现方式千变万化,但都有一个共同点,就是其根本目的是使受害主机或网络无法及时接收并处理外界请求,或无法及时回应外界请求。其具体表现方式有以下几种:

  (1) 制造大流量无用数据,造成通往被攻击主机网络拥塞,使被攻击主机无法正常和外界通信。

  (2) 利用被攻击主机提供服务或传输协议上处理重复连接的缺陷,反复高频的发出攻击性的重复服务请求,使被攻击主机无法及时处理其它正常的请求。

  (3)利用被攻击主机所提供服务程序传输协议的本身实现缺陷,反复发送畸形的攻击数据引发系统错误的分配大量系统资源,使主机处于挂起状态甚至死机。

 

2、攻击流程

 

 要理解dos攻击,首先要理解TCP连接的三次握手过程(Three-wayhandshake)。在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。

 

    1.第一次握手:建立连接时,客户端发送SYN包((SYN=i)到服务器,并进入SYN SEND状态,等待服务器确认;

 

    2.第二次握手:服务器收到SYN包,必须确认客户的SYN (ACK=i+1 ),同时自己也发送一个SYN包((SYN=j)}即SYN+ACK包,此时服务器进入SYN_RECV状态;

 

    3.第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ACK=j+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手,客户端与服务器开始传送数据。

 1. 半连接:收到SYN包而还未收到ACK包时的连接状态称为半连接,即尚未完全完成三次握手的TCP连接。

   2. 半连接队列:在三次握手协议中,服务器维护一个半连接队列,该队列为每个客户端的SYN包(SYN=i )开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于SYN_ RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。

   3. Backlog参数:表示半连接队列的最大容纳数目。

   4. SYN-ACK重传次数:服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间 仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息、从半连接队列中删除。注意,每次重传等待的时间不一定相同。

   5. 半连接存活时间:是指半连接队列的条目存活的最长时间,也即服务从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时也称半连接存活时间为Timeout时间、SYN_RECV存活时间。

 

上面三个参数对系统的TCP连接状况有很大影响。

    SYN洪水攻击属于DoS攻击的一种,它利用TCP协议缺陷,通过发送大量的半连接请求,耗费CPU和内存资源。 SYN攻击除了能影响主机外,还可以危害路由器、防火墙等网络系统,事实上SYN攻击并不管目标是什么系统,只要这些系统打开TCP服务就可以实施。从图 4-3可看到,服务器接收到连接请求(SYN=i )将此信息加入未连接队列,并发送请求包给客户端( SYN=j,ACK=i+1 ),此时进入SYN_RECV状态。当服务器未收到客户端的确认包时,重发请求包,一直到超时,才将此条目从未连接队列删除。配合IP欺骗,SYN攻击能 达到很好的效果,通常,客户端在短时间内伪造大量不存在的IP地址,向服务器不断地发送SYN包,服务器回复确认包,并等待客户的确认,由于源地址是不存 在的,服务器需要不断的重发直至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN 请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。过程如下:

 

       攻击主机C(地址伪装后为C)-----大量SYN包---->被攻击主机

       C<-------SYN/ACK包----被攻击主机

 

由于C地址不可达,被攻击主机等待SYN包超时。攻击主机通过发大量SYN包填满未连接队列,导致正常SYN包被拒绝服务。另外,SYN洪水攻击还可以通过发大量ACK包进行DoS攻击。

 

3、攻击手段

 

 拒绝服务攻击是一种对网络危害巨大的恶意攻击。今天,DoS具有代表性的攻击手段包括Ping of Death、TearDrop、UDPflood、SYNflood、LandAttack、IPSpoofingDoS等。看看它们又是怎么实现的。 

 

   (1) 死亡之ping (ping of death)

 

    ICMP(InternetControlMessageProtocol,Internet控制信息协议)在Internet上用于错误处理和传递控制信息。它的功能之一是与主机联系,通过发送一个“回音请求”(echorequest)信息包看看主机是否“活着”。最普通的ping程序就是这个功能。而在TCP/IP的RFC文档中对包的最大尺寸都有严格限制规定,许多操作系统TCP/IP协议栈都规定ICMP包大小为64KB,且在对包的标题头进行读取之后,要根据该标题头里包含的信息来为有效载荷生成缓冲区。"Ping of Death"就是故意产生畸形的测试Ping(PacketInternetGroper)包,声称自己的尺寸超过ICMP上限,也就是加载的尺寸超过64KB上限,使未采取保护措施的网络系统出现内存分配错误,导致TCP/IP协议栈崩溃,最终接收方宕机

 

   (2)泪滴 (tear drop)

 

   泪滴攻击利用在TCP/IP协议栈实现中信任IP碎片中的包的标题头所包含的信息来实现自己的攻击。IP分段含有指示该分段所包含的是原包的哪一段的信息,某些TCP/IP协议栈(例如NT在servicepack4以前)在收到含有重叠偏移的伪造分段时将崩溃。

 

   (3)UDP泛洪(UDP flood)

 

    UDPflood攻击:如今在Internet上UDP(用户数据包协议)的应用比较广泛,很多提供WWW和Mail等服务设备通常是使用Unix的服务器,它们默认打开一些被黑客恶意利用的UDP服务。如echo服务会显示接收到的每一个数据包,而原本作为测试功能的chargen服务会在收到每一个数据包时随机反馈一些字符。UDPflood假冒攻击就是利用这两个简单的TCP/IP服务的漏洞进行恶意攻击,通过伪造与某一主机的Chargen服务之间的一次的UDP连接,回复地址指向开着Echo服务的一台主机,通过将Chargen和Echo服务互指,来回传送毫无用处且占满带宽的垃圾数据,在两台主机之间生成足够多的无用数据流,这一拒绝服务攻击飞快地导致网络可用带宽耗尽。

 

   (4) SYN泛洪(SYNflood)

 

    SYNflood攻击:我们知道当用户进行一次标准的 TCP(TransmissionControlProtocol)连接时,会有一个3次握手过程。首先是请求服务方发送一个 SYN(SynchronizeSequenceNumber)消息,服务方收到SYN后,会向请求方回送一个SYN-ACK表示确认,当请求方收到 SYN-ACK后,再次向服务方发送一个ACK消息,这样一次TCP连接建立成功。“SYNFlooding”则专门针对TCP协议栈在两台主机间初始化连接握手的过程进行DoS攻击,其在实现过程中只进行前2个步骤:当服务方收到请求方的SYN-ACK确认消息后,请求方由于采用源地址欺骗等手段使得服务方收不到ACK回应,于是服务方会在一定时间处于等待接收请求方ACK消息的状态。而对于某台服务器来说,可用的TCP连接是有限的,因为他们只有有限的内存缓冲区用于创建连接,如果这一缓冲区充满了虚假连接的初始信息,该服务器就会对接下来的连接停止响应,直至缓冲区里的连接企图超时。如果恶意攻击方快速连续地发送此类连接请求,该服务器可用的TCP连接队列将很快被阻塞,系统可用资源急剧减少,网络可用带宽迅速缩小,长此下去,除了少数幸运用户的请求可以插在大量虚假请求间得到应答外,服务器将无法向用户提供正常的合法服务。

 

    (5)Land(LandAttack)攻击

 

    在Land攻击中,黑客利用一个特别打造的SYN包--它的原地址和目标地址都被设置成某一个服务器地址进行攻击。此举将导致接受服务器向它自己的地址发送SYN-ACK消息,结果这个地址又发回ACK消息并创建一个空连接,每一个这样的连接都将保留直到超时,在Land攻击下,许多UNIX将崩溃,NT变得极其缓慢(大约持续五分钟)。

 

     (6)IP欺骗dos攻击

 

     这种攻击利用TCP协议栈的RST位来实现,使用IP欺骗,迫使服务器把合法用户的连接复位,影响合法用户的连接。假设现在有一个合法用户(100.100.100.100)已经同服务器建立了正常的连接,攻击者构造攻击的TCP数据,伪装自己的IP为100.100.100.100,并向服务器发送一个带有RST位的TCP数据段服务器接收到这样的数据后,认为从100.100.100.100发送的连接有错误,就会清空缓冲区中已建立好的连接。这时,合法用户100.100.100.100再发送合法数据,服务器就已经没有这样的连接了,该用户就被拒绝服务而只能重新开始建立新的连接。

 

     (7)Smurf攻击

 

    Smurf是一种简单但有效的DDoS攻击技术,它利用了ICMP(Internet控制信息协议)。ICMP在Internet上用于错误处理和传递控制信息。它的功能之一是与主机联系,通过发送一个“回音请求”(echo request)信息包看看主机是否“活着”。最普通的ping程序就使用了这个功能。Smurf是用一个偷来的帐号安装到一个计算机上的,然后用一个伪造的源地址连续ping一个或多个计算机网络,这就导致所有计算机所响应的那个计算机并不是实际发送这个信息包的那个计算机。这个伪造的源地址,实际上就是攻击的目标,它将被极大数量的响应信息量所淹没。对这个伪造信息包做出响应的计算机网络就成为攻击的不知情的同谋

 

4、常见的dos攻击与防护

 

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

 

  (2)Smurf攻击:
       原理:
    发送伪装的ICMP数据包,目的地址设为某个网络的广播地址,源地址设为要攻击的目的主机,使所有收到此ICMP数据包的主机都将对目的主机发出一个回应,使被攻击主机在某一段时间内收到成千上万的数据包
       防范:
     在cisco路由器上配置如下可以防止将包传递到广播地址上:
         Router(config-if)# no ip directed-broadcast

 

    (3)Ping of Death
       原理:
     "ping of death"攻击就是我们常说的"死亡Ping"
这种攻击通过发送大于65536字节的ICMP包使操作系统崩溃;通常不可能发送大于65536个字节的ICMP包,但可以把报文分割成片段,然后在目标主机上重组;最终会导致被攻击目标缓冲区溢出,引起拒绝服务攻击。有些时候导致telnet和http服务停止,有些时候路由器重启。

 

    (4)泪滴攻击
       原理:
     对于一些大的IP数据包,往往需要对其进行拆分传送,这是为了迎合链路层的MTU(最大传输单元)的要求。比如,一个6000字节的IP包,在MTU为2000的链路上传输的时候,就需要分成3个IP 包。在IP报头中有一个偏移字段和一个拆分标志(MF)。如果MF标志设置为1,则表示这个IP包是一个大IP包的片段,其中偏移字段指出了这个片段在整 个IP包中的位置。例如,对一个6000字 节的IP包进行拆分(MTU为2 000),则3个片段中偏移字段的值依次为0,2000,4000。这样接收端在全部接收完IP数据包后,就可以根据这些信息重新组装这几个分次接收的拆分IP包。在这 里就有一个安全漏洞可以利用了,就是如果黑客们在截取IP数据包后,把偏移字段设置成不正确的值,这样接收端在收到这些分拆的数据包后,就不能按数据包中 的偏移字段值正确组合这些拆 分的数据包,但接收端会不断尝试,这样就可能致使目标计算机操作系统因资源耗尽而崩溃。

 

     (5) DRDOS
        原理:
    攻击时,攻击者巧妙的利用了反弹服务器群来将洪 水数据包反弹给目标主机 反弹服务是指某些服务器在收到一个请求数据报后就会产生一个回应数据报。所有的 Web 服务器、DNS 服务器及路 由器都是反弹服务器,他们会对 SYN 报文或其他 TCP 报文回应 SYNACKs 或 RST 报文, 以及对一些 IP 报文回应 ICMP 数据报超时或目的地不可达消息的数据 报。任何用于普通目的 TCP 连 接许可的网络服务器都可以用做数据包反射服务器

 

 

 

 

八、session劫持

       基于session的攻击有很多种方式。大部分的手段都是首先通过捕获合法用户的session, 然后冒充该用户来访问系统。也就是说,攻击者至少必须要获取到一个有效的session标识符,用于接下来的身份验证。 

      攻击者至少可以通过以下三种方式来获取一个有效的session标识符:

  1、预测:攻击者需要猜测出系统中使用的有效的session标识符(PHP中格式为PHPSESSID=1234),有点类似暴力破解。 php内部session的实现机制虽然不是很安全,但是关于生成session id的关节还是比较安全的,这个随机的session id往往是极其复杂的并且难于被预测出来,所以说,这种攻击方式基本上是不太可能成功的。

        2、捕获(劫持):会话劫持(Session hijacking),这是一种通过获取用户Session ID后,使用该Session ID登录目标账号的攻击方法,此时攻击者实际上是使用了目标账户的有效Session。会话劫持的第一步是取得一个合法的会话标识来伪装成合法用户,因此需要保证会话标识不被泄漏。

                    攻击步骤:

                    (1)目标用户需要先登录站点;

                    (2)登录成功后,该用户会得到站点提供的一个会话标识SessionID;

                    (3)攻击者通过某种攻击手段捕获Session ID;

                    (4)攻击者通过捕获到的Session ID访问站点即可获得目标用户合法会话。

                     Session劫持防御:

                    (1)更改Session名称。PHP中Session的默认名称是PHPSESSID,此变量会保存在Cookie中,如果攻击者不分析站点,就不能猜到Session名称,阻挡部分攻击。

                    (2)关闭透明化Session ID。透明化Session ID指当浏览器中的Http请求没有使用Cookie来存放Session ID时,Session ID则使用URL来传递。

                    (3)设置HttpOnly。通过设置Cookie的HttpOnly为true,可以防止客户端脚本访问这个Cookie,从而有效的防止XSS攻击。

                    (4)关闭所有phpinfo类dump request信息的页面。

                    (5) 验证HTTP头部信息,在http访问头文件:[Accept-Charset、Accept-Encoding、Accept-Language、User-Agent],浏览器一般发出的头部不会改

            (6)加入Token校验。同样是用于检测请求的一致性,给攻击者制造一些麻烦,使攻击者即使获取了Session ID,也无法进行破坏,能够减少对系统造成的损失。但Token需要存放在客户端,如果攻击者有办法获取到Session ID,那么也同样可以获取到Token。

        3、固定:会话固定(Session fixation)是一种诱骗受害者使用攻击者指定的会话标识(SessionID)的攻击手段。这是攻击者获取合法会话标识的最简单的方法。(让合法用户使用黑客预先设置的sessionID进行登录,从而是Web不再进行生成新的sessionID,从而导致黑客设置的sessionId变成了合法桥梁。)

会话固定也可以看成是会话劫持的一种类型,原因是会话固定的攻击的主要目的同样是获得目标用户的合法会话,不过会话固定还可以是强迫受害者使用攻击者设定的一个有效会话,以此来获得用户的敏感信息。

      攻击步骤: 

1、 攻击者通过某种手段重置目标用户的SessionID,然后监听用户会话状态;

2、 目标用户携带攻击者设定的Session ID登录站点;

3、 攻击者通过Session ID获得合法会话

 

参考:

https://www.cnblogs.com/fundebug/p/details-about-6-web-security.html

https://blog.csdn.net/TT_love9527/article/details/82150726

 

posted @ 2019-09-01 14:54  pretty.sunshine  Views(9918)  Comments(2Edit  收藏  举报