Web安全测试——常见的威胁攻防
-
SQL注入
部分程序员在编写代码的时候,没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患。用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据,这就是所谓的SQL Injection,即SQL注入
案例
HTTP://xxx.xxx.xxx/abc.asp?p=YY
①HTTP://xxx.xxx.xxx/abc.asp?p=YY’(附加一个单引号), abc.asp运行异常,表示没有对特殊字符进行转义或过滤
②HTTP://xxx.xxx.xxx/abc.asp?p=YY and 1=1, abc.asp运行正常,而且与HTTP://xxx.xxx.xxx/abc.asp?p=YY运行结果相同;
③HTTP://xxx.xxx.xxx/abc.asp?p=YY and 1=2, abc.asp运行异常;
如果以上三步全面满足,abc.asp中一定存在SQL注入漏洞。
攻击步骤
1、 发现SQL注入位置;
2、 判断后台数据库类型;
3、 确定XP_CMDSHELL可执行情况
4、 发现WEB虚拟目录
5、 上传木马;
6、 得到管理员权限;
具体见:http://www.cnblogs.com/tanshuicai/archive/2010/02/03/1664900.html
常见的不安全写法:
Statement s = connection.createStatement();
ResultSet rs = s.executeQuery("SELECT email FROM member WHERE name = " + formField);
安全写法
PreparedStatement ps = connection.prepareStatement(
"SELECT email FROM member WHERE name = ?");
ps.setString(1, formField);
ResultSet rs = ps.executeQuery();
如何防御?
转义?过滤?
避开过滤方法
1、大小写变种
若小写被过滤,则变成大写继续执行
http://bbs.ichunqiu.com/data/attachment/forum/201608/21/134905u36phck612j6kw3j.gif?_=5793686
2、URL编码
双url编码可以绕过过滤
http://bbs.ichunqiu.com/data/attachment/forum/201608/21/143646fnygion74g9c8idi.gif?_=5793686
3、SQL注释
很多开发人员认为,将输入限制为单个就可以限制SQL注入攻击,所以他们往往就只是阻止各种空白符,但是内联注释不使用空格就可以构造任意复杂的SQL语句。
http://bbs.ichunqiu.com/data/attachment/forum/201608/21/142321um0h0q5zefvhooqk.gif?_=5793686
防御
输入验证是指要验证所有应用程序接收到的输入是否合法。
有两中不同类型的输入验证方法:白名单和黑名单验证
白名单验证:比如id值,那么我们判断它是否为数字。
黑名单验证:使用正则表达式禁止使用某些字符和字符串
应该尽量使用白名单,对于无法使用白名单的,使用黑名单提供局部限制。
-
跨站脚本(XSS)
跨站脚本(cross site script)为了避免与样式css混淆,所以简称为XSS。
什么是XSS?
XSS是指攻击者利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点,进而添加一些代码,嵌入到web页面中去。使别的用户访问都会执行相应的嵌入代码。从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。
反射型xss攻击
一般会放在请求或者跳转的链接中,一次性造成攻击。,称之为反射性XSS攻击
例:页面搜索框输入"/><script>alert("这是一个反射型xss攻击")</script>后点击搜索,会提示提示框
存储式XSS攻击
一般是在提交表单式的请求中,注入XSS,存入服务器中,达到攻击打开的用户,影响所有看到的人。
例:新建用户,描述中输入"/><script>alert("这是一个存储型xss攻击")</script>
保存后,后面的用户打开用户管理页面,查看到刚添加的用户所在页,都会弹出提示框
防御
1. 前端在显示服务端数据时候,不仅是标签内容需要过滤、转义,属性值也可能需要。
1) 将重要的cookie标记为http only, 这样的话Javascript 中的document.cookie语句就不能获取到cookie了。
2) 表单数据规定值的类型,例如:年龄应为只能为int、name只能为字母数字组合。。。
3) 对数据进行Html Encode 处理
4) 过滤或移除特殊的Html标签,例如: <script>, <iframe> , < for <, > for >, " for
5) 过滤JavaScript 事件的标签。例如 "onclick=", "onfocus" 等等。
2. 后端接收请求时,验证请求是否为攻击请求,攻击则屏蔽。
【特别注意】
在有些应用中是允许html标签出现的,如输出需要html代码、javascript代码拼接、或者此表单直接允许使用等等,需要区别处理。
-
跨站请求伪造(CSRF)
CSRF(Cross-site request forgery), 就是攻击者盗用你的身份,以你的名义发送恶意请求。
攻击原理
如图所示,其中Web A为存在CSRF漏洞的网站,Web B为攻击者构建的恶意网站,User C为Web A网站的合法用户。
1、用户C打开浏览器,访问网站A,输入用户名和密码请求登录网站A;
2、在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
3、用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
4、网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问站点A;
5、浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的!
案例
银行网站A,它以GET请求来完成银行转账的操作,如:
http://www.mybank.com/Transfer.php?toBankId=11&money=1000
危险网站B,它里面有一段HTML的代码如下:
<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
首先,你登录了银行网站A,然后访问危险网站B,这时你会发现你的银行账户少了1000块......
为什么会这样呢?原因是银行网站A使用GET请求更新资源。在访问危险网站B的之前,你已经登录了银行网站A,而B中的<img>以GET的方式请求第三方资源(这里的第三方就是指银行网站了,原本这是一个合法的请求,但这里被不法分子利用了),所以你的浏览器会带上你的银行网站A的Cookie发出Get请求,去获取资源“http://www.mybank.com/Transfer.php?toBankId=11&money=1000”,结果银行网站服务器收到请求后,认为这是一个更新资源操作(转账操作),所以就立刻进行转账操作......
防御
优先考虑的就是利用已有的CSRF防护方案。许多框架,如Spring, Play, Django以及AngularJS,都内嵌了CSRF防护,一些web开发语言如.Net也提供了类似的防护,OWASP CSRF Guard对Java应用提供了CSRF防护。否则需要在每个HTTP请求中添加一个不可预测的令牌,这种令牌至少应该对每一个用户会话来说是唯一的。
1、 服务器端验证HTTP Referer字段
根据HTTP协议,在HTTP头中有一个字段叫Referer,记录了该HTTP请求的来源地址。访问一个安全受限页面的请求必须来自于同一个网站。比如某银行的转账是通过用户访问http://bank.test/test?page=10&userID=101&money=10000页面完成,用户必须先登录bank.test,然后通过点击页面上的按钮来触发转账事件。当用户提交请求时,该转账请求的Referer值就会是转账按钮所在页面的URL(本例中,通常是以bank. test域名开头的地址)。而如果攻击者要对银行网站实施CSRF攻击,他只能在自己的网站构造请求,当用户通过攻击者的网站发送请求到银行时,该请求的Referer是指向攻击者的网站。因此,要防御CSRF攻击,银行网站只需要对于每一个转账请求验证其Referer值,如果是以bank. test开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果Referer是其他网站的话,就有可能是CSRF攻击,则拒绝该请求。
2、 在请求地址中添加token并验证或验证码
CSRF攻击之所以能够成功,是因为攻击者可以伪造用户的请求,该请求中所有的用户验证信息都存在于Cookie中,因此攻击者可以在不知道这些验证信息的情况下直接利用用户自己的Cookie来通过安全验证。由此可知,抵御CSRF攻击的关键在于:在请求中放入攻击者所不能伪造的信息,并且该信息不存在于Cookie之中。鉴于此,系统开发者可以在HTTP请求中以参数的形式加入一个随机产生的token,并在服务器端建立一个拦截器来验证这个token,如果请求中没有token或者token内容不正确,则认为可能是CSRF攻击而拒绝该请求。
3、 考虑对所有cookie使用”SameSite”标签,该标签逐渐被各类浏览器所支持。
防止 CSRF 攻击的办法已经有 CSRF token 校验和 Referer 请求头校验。为了从源头上解决这个问题,Google 起草了 一份草案 来改进 HTTP 协议,那就是为 Set-Cookie 响应头新增 SameSite 属性,它用来标明这个 cookie 是个“同站 cookie”,同站 cookie 只能作为第一方 cookie,不能作为第三方 cookie。
参考:http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html
-
失效的认证和会话管理
身份认证
最常见的是登录功能,往往是提交用户名和密码,在安全性要求更高的情况下,有防止密码暴力破解的验证码,基于客户端的证书,物理口令卡等。
会话管理
HTTP本身是无状态的,利用会话管理机制来实现连接识别。
身份认证的结果往往是获得一个令牌,通常放在cookie中,如jsessionid。之后对用户身份的识别根据这个授权的令牌进行识别,而不需要每次都要登录。
-
失效的认证和会话管理
开发者通常会建立自定义的认证和会话管理方案。但要正确实现这些方案却很难,结果这些自定义的方案往往在如下方面存在漏洞:退出、密码管理、超时、记住我、秘密问题、帐户更新等等
案例
1、机票预订应用程序支持URL重写,把会话ID放在URL里:
http://example.com/sale/saleitems;jsessionid=2P0OC2JDPXM0OQSNDLPSKHCJUN2JV?dest=Hawaii
该网站一个经过认证的用户希望让他朋友知道这个机票打折信息。他将上面链接通过邮件发给他朋友们,并不知道自己已经泄漏了自己的会话ID。当他的朋友们使用上面的链接时,他们将会使用他的会话和信用卡。
2、应用程序超时设置不当。用户使用公共计算机访问网站。离开时,该用户没有点击退出,而是直接关闭浏览器。攻击者在一个小时后能使用相同浏览器通过身份认证。盐
3、攻击者进入系统的数据库。存储在数据库中的用户密码没有被哈希和加盐, 所有用户的密码都被攻击者获得。
如何验证程序是否存在失效的认证和会话管理?
最需要要保护的数据是认证凭证(credentials) 和会话ID。
1、当存储认证凭证时,是否总是使用hashing或加密保护吗?
2、认证凭证是否可猜测,或者能够通过薄弱的的帐户管理功能(例如账户创建、密码修改、密码恢复, 弱会话ID)重写?
3、会话ID是否暴露在URL里(例如, URL重写) ?
4、会话ID是否容易受到会话固定(session fixation) 的攻击?
5、会话ID会超时吗? 用户能退出吗?
6、成功注册后,会话ID会轮转吗?
7、密码、会话ID和其他认证凭据是否只通过TLS连接传输?
防御
1、区分公共区域和受限区域
站点的公共区域允许任何用户进行匿名访问。受限区域只能接受特定用户的访问,而且用户必须通过站点的身份验证。
2、对最终用户帐户使用帐户锁定策略
当最终用户帐户几次登录尝试失败后,可以禁用该帐户或将事件写入日志。
3、支持密码有效期
密码不应固定不变,而应作为常规密码维护的一部分,通过设置密码有效期对密码进行更改。在应用程序设计阶段,应该考虑提供这种类型的功能。
4、能够禁用或锁定帐户
如果在系统受到威胁时使凭证失效或禁用帐户,则可以避免遭受进一步的攻击。
5、不要在用户存储中存储密码
如果必须验证密码,则没有必要实际存储密码。相反,可以存储一个单向哈希值,然后使用用户所提供的密码重新计算哈希值。为减少对用户存储的词典攻击威胁,可以使用强密码,并将随机 salt 值与该密码结合使用。
6、要求使用强密码
要求输入至少 8 位字符,其中要包含大写字母、小写字母、数字和特殊字符。无论是使用平台实施密码验证还是开发自己的验证策略,此步骤在对付粗暴攻击时都是必需的。在粗暴攻击中,攻击者试图通过系统的试错法来破解密码。使用常规表达式协助强密码验证。
7、不要在网络上以纯文本形式发送密码
以纯文本形式在网络上发送的密码容易被窃听。应加密传输。
8、保护身份验证 Cookie
身份验证 cookie 被窃取意味着登录被窃取。可以通过加密和安全的通信通道来保护验证票证。另外,还应限制验证票证的有效期,以防止因重复攻击导致的欺骗威胁。
不要通过 HTTP 连接传递身份验证 cookie。在授权 cookie 内设置安全的 cookie 属性,以便指示浏览器只通过 HTTPS 连接向服务器传回 cookie。
9、对身份验证 cookie 的内容进行加密
即使使用 SSL,也要对 cookie 内容进行加密。如果攻击者试图利用XSS攻击窃取 cookie,这种方法可以防止攻击者查看和修改该 cookie。在这种情况下,攻击者仍然可以使用 cookie 访问应用程序,但只有当 cookie 有效时,才能访问成功。
10、限制会话寿命
缩短会话寿命可以降低会话劫持和重复攻击的风险。会话寿命越短,攻击者捕获会话 cookie 并利用它访问应用程序的时间越有限。
-
失效的访问控制
当生成web页面时,数据、应用程序和APIs经常使用对象的实名或关键字。功能、URLs和函数名称经常容易被猜解。而应用程序和APIs并不总是验证用户对目标资源的访问授权,如普通用户可以访问管理员的页面,这就导致了访问控制失效。测试者能轻易操作参数值以检测该漏洞。代码分析能很快显示应用程序是否进行了正确的权限验证。
攻击
猜一些页面的url,进行攻击。
案例
管理员页面并没有菜单管理的权限,但是却可以在浏览器中输入菜单管理的url:menu来访问菜单管理页面
防御
1、检查访问。任何来自不可信源的直接对象引用都必须通过访问控制检测,确保该用户对请求的对象有访问权限。
2、使用基于用户或者会话的间接对象引用。这样能防止攻击者直接攻击未授权资源。例如,一个下拉列表包含6个授权给当前用户的资源,它可以使用数字1-6来指示哪个是用户选择的值,而不是使用资源的数据库关键字来表示。OWASP的ESAPI包含了两种序列和随机访问引用映射,开发人员可以用来消除直接对象引用。
3、自动化验证。利用自动化验证正确的授权部署。这是通常做法。
-
安全配置错误
没有正确的安全配置,导致外部的匿名攻击者和拥有帐户的内部用户都可能会试图破坏系统
攻击
攻击者访问默认账户,无效页面,没打补丁的漏洞,未受保护的文件及文件夹等,以获得未授权的访问或对应用系统进行了解和分析。
案例
1、服务器管理员控制台自动安装后没有被删除。而默认帐户也没有被改变。攻击者在你的服务器上发现了标准的管理员页面,通过默认密码登录,从而接管了你的服务器。
2、目录列表在你的服务器上未被禁用。攻击者发现只需列出目录,她就可以找到你服务器上的任意文件。攻击者找到并下载所有已编译的Java类,通过反编译获得了所有你的自定义代码。然后,她在你的应用程序中找到一个访问控制的严重漏洞。
3、应用服务器配置允许堆栈跟踪信息返回给用户,这样就暴露了潜在的漏洞。如已知的有漏洞的框架版本。
4、应用服务器自带的示例应用程序没有从您的生产服务器中删除。该示例应用有已知安全漏洞,攻击者可以利用这些漏洞破坏您的服务器。
防御
1、 配置所有的安全机制
2、 关掉所有不使用的服务和服务器上的示例应用程序
3、 设置角色帐号权限
4、 使用日志和警报
5、 所有错误只显示友好信息,不显示任何与实际错误相关的信息
6、 及时更新服务器补丁
-
敏感信息泄漏
攻击
通过SQL注入或命令执行或直接使用脚本进行爬虫,来获得用户的账号密码、实名信息泄露、行为记录等
防御
1、预测一些威胁(比如内部攻击和外部用户),加密这些数据的存储以确保免受这些威胁。
2、对于没必要存放的、重要的敏感数据,应当尽快清除。
3、确保使用了合适的强大的标准算法和强大的密匙,并且密匙管理到位。
4、确保使用密码专用算法存储密码
5、禁用自动完成防止敏感数据收集,禁用包含敏感数据的缓存页面。
6、加密传输
7、使用安全的加密算法