本文学习XSS基础以及DVWA模拟环境的几道例题。
XSS介绍与原理
XSS攻击是在网页中嵌入客户端恶意脚本代码,一般是使用JavaScript语言编写。
JavaScript可以用来获取用户的Cookie、改变网页内容、URL跳转,因此攻击者需要做的是向Web页面注入JavaScript,就可以盗取用户Cookie、黑掉页面、导航到恶意网站。
通常在url中加入来实现一些特殊效果,也可以在JavaScirpt中利用url形式来加载外部脚本。
漏洞实现原理
XSS漏洞分类:反射型、存储型、DOM型
XSS漏洞修复
- HTML实体编码
- 使用白名单过滤用户输入的恶意字符
- 根据业务场景对症下药
存储型XSS实战
原理
攻击者在页面上插入XSS代码,服务端将数据存入数据库,当用户访问到存在XSS漏洞的页面时,服务端从数据库中取出数据展示到页面上,导致XSS代码执行,达到攻击效果。
允许用户存储数据的Web应用程序都可能会出现存储型XSS漏洞,当攻击者提交一段XSS代码后,被服务器端接收并存储,当攻击者再次访问某个界面时,这段XSS代码被程序读出来响应给浏览器,造成XSS攻击。
比起其他两种类型的XSS攻击,存储型XSS不需要用户手动去触发。
注意:判断输出数据是否在属性内
当输出数据在属性内,
以上JavaScript代码虽然插入到HTML中,但因为XSS代码在Value属性中,最终当做值来处理,浏览器在解析HML时,会将数据以文本的形式输出在网页。
因此我们需要根据响应的标签构造HTML代码来闭合,插入XSS代码为"/ ><script>alert(1)</script>
,最终在HTMl文档中为<input type="text" name="content" value=""/ ><script>alert(1)</script>"/>
,这样就可以闭合input标签,使得输出的内容不再Value属性内,从而造成XSS跨站漏洞。
存储型XSS测试步骤
添加正常留言’helloworld‘,审查元素得知该HTML代码为
<li><strong>username</strong><span class="message">helloword</span>
如果不清楚具体输出位置,有三种模糊测试方法
- 普通注入
<script>alert(document.cookie)</script>
- 闭合标签注入
" /><script>alert(document.cookie)</script>
- 闭合标签注入
</textarea>'"><script>alert(document.cookie)</script
- 普通注入
当存储型XSS代码注入后,每次加载留言界面XSS代码都会被执行
总结:留言就是恶意XSS代码伪装的。
反射型XSS
原理
攻击者在URL中插入XSS代码,服务端将URL中的XSS代码输出到页面上,攻击者将带有XSS代码的URL发送给用户,用户打开后受到XSS攻击。
代码解析
程序接受username值后再输出,如果username=<script>恶意代码</script>
,则会让恶意代码在服务器端执行。
1 |
|
攻击者利用站内信方式将带有恶意代码的URL发送给正常用户以获取用户的Cookie即登录信息,则攻击者可以利用Cookie(以正常用户的身份)登录该网站。
方法:寻找需要传入参数(形如?id=1
)的URL,在闭合标签再加入<script>
代码。
DOM型XSS
DOM简介
DOM全称Document Object Model(文档对象模型),使用DOM可以允许程序和脚本动态地访问和更新文件的内容、结果和样式。
HTML DOM树
原理
攻击者在URL中插入XSS代码,前端页面直接从URL中获取XSS代码并输出到页面,导致XSS代码执行,攻击者将带有XSS代码的URL发送给用户,用户打开后受到XSS攻击。(与反射型XSS漏洞相比,DOM型XSS漏洞不需要经过后端处理,只在前端进行)
经典DOM型XSS示例
1 | // 获取URL中的content值并输出 |
常见方法
输入http://127.0.0.1/dom.html?content=<script>alert(/xss/)</script>
就会产生XSS漏洞。
常用XSS漏洞修复函数
在下面实战中我们还会讲解一遍函数的具体作用
- Strip_tags() 所有HTML、XML、PHP元素均被删除
- htmlspecialchars 将部分字符转换为HTML实体,防止浏览器将其识别为HTML元素。
"
–>"
&
–>&
'
–>'
<
–><
>
–>>
- addslashes() 在字符串中出现预定字符之前添加反斜杠的字符串。
- stripslahes(string) 删除字符串中的反斜杠
XSS辅助测试工具
Beef
搭建:
- docker pull janes/beef
- docker run –rm -p 3000:3000 janes/beef
- 访问http://127.0.0.1:3000/ui/panel 默认账号密码beef/beef
使用:当用户执行XSS代码之后,获取信息进行详细分析。
XSS’OR
Encode/Decode 代码编码解码
Codz 测试CSS工具,生成一些POST数据
Probe 给你一个JS文件你可以插入到指定的网页中,以来获取信息。
XSS平台
网上JS漏洞集合平台
IE Tester
模拟IE低版本
DVWA XSS实战
安装DVWA模拟环境
下载并安装docker
docker pull citizenstig/dvwa
docker run -dt -p 8997:80 citizenstig/dvwa
访问http://127.0.0.1:8997 默认账号密码admin/password
XSS(Reflected) Low
代码分析
1 |
|
从源代码可以看到代码直接引用name参数,并没有任何的过滤与检查,存在明显的XSS漏洞。
漏洞利用
输入<script>alert(/nzy/)</script>
,弹框
url:http://127.0.0.1:8997/vulnerabilities/xss_r/?name=%3Cscript%3Ealert%28%2Fnzy%2F%29%3C%2Fscript%3E#
XSS(Reflected) Medium
代码分析
1 |
|
从源代码可以看出对输入进行了过滤,基于黑名单思想,利用str_replace()函数将输入中含有<script>
替换成
。但是这种防护机制仍可以轻松绕过。
漏洞利用
- 利用双写绕过,输入
<scr<script>ipt>alert(/nzy/)</script>
,在经过str_replace()函数处理后为<script>alert(/nzy/)</script>
- 大小写混淆绕过,黑名单思想只禁止
<script>
,因此可以利用大小写混淆绕过,输入<Script>alert(/nzy/)</scirpt>
XSS(Reflected) High
代码分析
1 |
|
从源代码可以看出同样是使用了黑名单思想,但是preg_replace()函数用于正则表达式的搜索和替换,这样使得Medium级别的双写绕过、大小写混淆绕过方法都是小。
Preg_replace()函数中i表示忽略大小写
漏洞利用
虽然无法再使用带有<script>
字样的标签来注入XSS代码,但是可以利用img、body等标签事件或者iframe等标签src来注入恶意的JS代码。
输入<img src=1 onerror=alert(/nzy/)>
XSS(Reflected) Impossible
代码分析
1 |
|
在High级别中,我们可以利用img、body等标签事件进行注入恶意JS代码,所以在impossible级别中,利用上文讲到过的htmlspecialchars()函数将部分字符(& " ' < >
)转换为HTML实体,防止浏览器将其识别为HTML元素。
XSS(Stored) Low
代码分析
1 |
|
针对代码中提到的几个函数解释一下
- trim(string,charlist) 功能:移除字符串两侧的空白字符或者其他预定义字符(
\t \n \x0B \r
),可选参数charlist支持增添额外需要删除的字符 - Mysql_real_escape_string(string,connection)这个函数在 SQL注入防御绕过曾经提到过。功能:对字符串中的特殊符号(
\x00 \n \r \ ' " \x1a
)进行转义。 - stripslahes(string) 功能:删除字符串中的反斜杠
从源代码可以看出对输入没有做XSS方面的过滤与检查就直接存储至数据库了,因此存在明显的存储型XSS漏洞。
漏洞利用
直接输入<script>alert(/nzy/)</script>
,需要注意的是name变量在前端中对字数有限制,我们将其修改至30。
XSS(Stored) Medium
代码分析
1 |
|
针对代码中提到的几个函数解释一下
- Strip_tags() 功能:删除字符串中的HTML、XML以及PHP标签,但保留
<b>
标签。 - addslashes() 功能:在字符串中出现预定字符(
' " / NULL
)之前添加反斜杠的字符串。
从源代码可以看出对输入中的message参数使用了htmlspecialchars()函数进行标签转换,因此无法再通过message参数进行XSS注入,但是对name参数只进行形如XSS(Reflected) Medium中的过滤<script>
字符串而已,因此存在存储型XSS漏洞。
漏洞利用
基本参见XSS(Reflected) Medium中的双写绕过、大小写混淆绕过两种办法,并且对name参数进行修改maxlength=30。
- 双写绕过,输入
<scr<script>ipt>alert(/nzy/)</script>
- 大小写混淆绕过,输入
<Script>alert(/nzy/)</scirpt>
XSS(Stored) High
代码分析
1 |
|
从源代码可以看出这道题类似于XSS(Reflected) High,具体参见上文。
漏洞分析
基本参见XSS(Reflected) High中的利用img、body等标签事件或者iframe等标签src来注入恶意的JS代码的办法,并且对name参数进行修改maxlength=30。
输入<img src=1 onerror=alert(/nzy/)>
XSS(Stored) Impossible
代码分析
1 |
|
还是终极函数htmlspecialchars()函数的出场,解决XSS问题。有一点需要注意的是,如果htmlspecialchars()函数使用不当,攻击者就可以通过编码的方式绕过函数进行XSS注入,尤其是DOM型的XSS。
htmlspecialchars()完整用法:https://www.runoob.com/php/func-string-htmlspecialchars.html