跨站脚本攻击XSS(Cross Site Script) 为了不和层叠式演示表(Cascading Style Sheets,CSS) 的缩写混淆,顾将跨站脚
本攻击缩写为XSS。恶意攻击者网web页面插入恶意Script代码,当用户浏览该页面时,嵌入web里面的script代码就会被执行,从
而达到攻击用户的目的。XSS攻击针对的是用户层面的攻击!
XSS存在的根本原因是,对URL中的参数和对用户输入提交给web server的内容,没有进行充分的过滤。如果我们能够在web程序
中对用户提交的URL中的参数,和提交的所有内容进行充分的过滤,将所有的不合法的参数和输入内容过滤掉,那么就不会导致“在用
户的浏览器中执行攻击者自己定制的脚本”。
|--->窃取cookie
|--->网络钓鱼
|------->针对用户-->|--->放马挖矿
| |--->广告刷流量
XSS----|
|
| |--->篡改页面
|----->针对web服务->|--->传播蠕虫
|--->内网扫描
|--->劫持后台
从以上我们可以知道,存储型的XSS危害最大。因为他存储在服务器端,所以不需要我们和被攻击者有任何接触,
只要被攻击者访问了该页面就会遭受攻击。而反射型和DOM型的XSS则需要我们去诱使用户点击我们构造的恶意的URL,
需要我们和用户有直接或者间接的接触,比如利用社会工程学或者利用在其他网页挂马的方式。
XSS一般分为:存储型、反射型、DOM型
存储型和反射型区别:是否有交互
易用性排序:存储型 > DOM型 > 反射型
存储型XSS:持久化,代码是存储在web服务器中的,比如在跟人信息或发表文章等地方插入代码,
如果没有过滤或者过滤不严,那么这些代码将存储在服务器中,用户访问该页面的时候触发代码执行。
这种XSS比较危险,容易造成蠕虫、盗窃cookie。每一个访问特定页面的用户,都会受到攻击。
特点:
1> XSS攻击代码存储于web server上;
2> 攻击者,一般是通过网站的留言、评论、博客、日志等等功能(所有能够向web server输入内容的地方),
将攻击代码存储到web server上的;
反射型XSS:非持久化,需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),
一般容易出现在搜索页面。反射型XSS大多是是用来盗取用户的cookie信息。只要用户点击特定恶意
链接,服务器解析响应后,在返回的响应内出现攻击者的XSS代码,被浏览器执行。一来一去,XSS
攻击脚本被Web server反射回给浏览器执行,所以称为反射型XSS。
特点:
1> XSS攻击代码非持久性,也就是没有保存在web server中,而是出现在URL地址中;
2> 非持久性,那么攻击方式就不同了。一般是攻击者通过邮件,聊天软件等等方式发送攻击URL,
然后用户点击来达到攻击的;
有时持久性XSS和反射型XSS是同时使用的:
比如先通过对一个攻击url进行编码(来绕过xss filter),然后提交该web server(存储在web server中), 然后用户在浏览页面时,
如果点击该url,就会触发一个XSS攻击。当然用户点击该url时,也可能会触发一个CSRF(Cross site request forgery)攻击.
不经过后端,DOM-XSS漏洞是基于文档对象模型(Document Object Model,DOM)的一种漏洞,
DOM-XSS是通过url传入参数去控制触发的,其实也属于反射型XSS。
(dom-xss取决于输出位置,并不取决于输出环境,因此domxss既有可能是反射型的,也有可能是存储型的)
特点:
web server不参与,仅仅涉及到浏览器的XSS。
可触发DOM-XSS的属性:
document.referer
window.name
location
innerHTML
document.write
1.Bob拥有一个Web站点,该站点允许用户发布信息/浏览已发布的信息;
2.Tom检测到Bob的站点存在存储型的XSS漏洞;
3.Tom在Bob的网站上发布一个带有恶意脚本的热点信息,该热点信息存储在了Bob的服务器的数据库中,然后吸引其它用户来阅读该热点信息;
4.Bob或者是任何的其他人如Alice浏览该信息之后,Tom的恶意脚本就会执行;
5.Tom的恶意脚本执行后,Tom就可以对浏览器该页面的用户发动一起XSS攻击。
1.Alice经常浏览某个网站,此网站为Bob所拥有。Bob的站点需要Alice使用用户名/密码进行登录,并存储了Alice敏感信息(比如银行帐户信息);
2.Tom 发现 Bob的站点存在反射性的XSS漏洞;
3.Tom 利用Bob网站的反射型XSS漏洞编写了一个exp,做成链接的形式,并利用各种手段诱使Alice点击;
4.Alice在登录到Bob的站点后,浏览了 Tom 提供的恶意链接;
5.嵌入到恶意链接中的恶意脚本在Alice的浏览器中执行。此脚本盗窃敏感信息(cookie、帐号信息等信息)。然后在Alice完全不知情的情况下将这些信息发送给 Tom;
6.Tom 利用获取到的cookie就可以以Alice的身份登录Bob的站点,如果脚本的功更强大的话,Tom 还可以对Alice的浏览器做控制并进一步利用漏洞控制。
以下所有标签的 > 都可以用 // 代替,例如 < script> alert(1)
#弹出hello
#弹出hello
#弹出1,对于数字可以不用引号
#弹出cookie
#引用外部的xss
------------------------------
*用户输入作为script标签内容
*用户输入作为HTML注释内容
*用户输入作为HTML标签的属性名
*用户输入作为HTML标签的属性值
*用户输入作为HTML标签的名字
*直接插入到CSS里
**通过上述可插入的位置可知:千万不要引入任何不可信的第三方JavaScript到页面里!
----------------------------------
#用户输入作为HTML注释内容,导致攻击者可以进行闭合绕过
#用户输入作为标签属性名,导致攻击者可以进行闭合绕过
#用户输入作为标签属性值,导致攻击者可以进行闭合绕过
#用户输入作为标签名,导致攻击者可以进行闭合绕过
<用户输入 id="xx" />
<>
#用户输入作为CSS内容,导致攻击者可以进行闭合绕过
----------------------------------
黑盒测试:
尽可能找到一切用户可控并且能够输出在页面代码中的地方,比如下面这些:
*URL的每一个参数
*URL本身
*表单
*搜索框
---------------------
常见业务场景:
*重灾区:评论区、留言区、个人信息、订单信息等
*针对型:站内信、网页即时通讯、私信、意见反馈
*存在风险:搜索框、当前目录、图片属性等
----------------------
白盒测试(代码审计):
关于XSS的代码审计主要就是从接收参数的地方和一些关键词入手:
PHP中常见的接受参数$_GET、$_POST、$_REQUEST等,可以搜索所有接受参数的
地方,然后对收到的数据进行跟踪,看看有没有输出到页面中,然后看输出到页面的
数据是否进行了过滤和编码等处理。
也可以搜索类似echo这样的输出语句,跟踪输出的变量是从哪里来的,我们能否
控制,如果从数据库中取的,是否控制存到数据库中的数据,存到数据之前有没有进
行过滤等。
大多数程序会对接受参数封装在公共文件的函数中同一调用,我们就要审计这些
公共函数看看有没有过滤,能否绕过等。
同理审计DOM-XSS可以搜索一些js操作DOM元素的关键字进行审计。
----------------------
------------------------------------
//前端 1.html:
反射型XSS
------------------------
//后端 action.php:
--------------------------------------
提交数据: 弹框hack,插入的语句被执行;
数据流向:前端-->后端-->前端
------------------------------
//前端:2.html
存储型XSS
-------------------------------
//后端:action2.php
------------------------------
//供其他用户访问页面:show2.php
---------------------------------
这里有一个用户提交的页面,数据交给后端后,后端存储在数据库中。然后当其他用户
访问另一个页面时,后端调出改数据,显示给另一个用户,XSS代码执行。
-----------------------------------
我们输入1和,注意,这里的hack的单引号要进行转义,
因为sql语句中的$name是单引号的,所以这里不转义的话就会闭合sql语句中的单引号。
-----------------------------------
当我们提交1和后,XSS代码被插入数据库,
然后当其他用户访问show2.php时,查询id=1,echo $row['name'],xss代码被执行。
-----------------------------------
数据流向:前端-->后端-->数据库-->后端-->前端
----------------------------------
// 前端3.html
DOM型XSS
-----------------------
// 后端action3.php
------------------------------
这是一个用户提交页面,用户可以在此提交数据,数据提交后给后台处理:
------------------------------
提交数据: ,弹窗hack
------------------------------
数据流向:前端-->浏览器
----------------------------------
1.区分大小写过滤标签:
过滤:$name=preg_replace("/
绕过:可以使用大小写绕过
----------------------------------
2.不区分大小写过滤标签:/i:不区分大小写
过滤:$name=preg_replace("/
绕过:可以使用嵌套的script标签绕过:ipt>alert('hack') ipt>
----------------------------------
3.不区分大小写,过滤之间的所有内容:
过滤:$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] ); //过滤了
思考:怎么构造恶意代码用来诱使用户点击并且用户点击后不会发现点击了恶意链接呢?
--------------------------------
构造代码:
核心:
----------------------------
404 页面不存在
404很抱歉,您要访问的页面不存在!
------------------------------
将其保存为html页面,然后放在我们自己的服务器上,作为一个链接。当用户登录了存在漏洞的网站,并且用户点击了
我们构造的恶意链接时,该链接页面会偷偷打开一个iframe框架,iframe会访问其中的链接,然后执行我们的js代码。
该js代码会把存在漏洞的网站的cookie发送到我们的平台上,而用户却浑然不知,只会获得一个404错误页面。
注:我们的攻击代码可以利用的前提是存在XSS漏洞的网站的X-Frame-options未配置,并且会话Cookie没有设置Http Only属性
=======================================
post型
假设一网站的用户名输入框存在反射型XSS漏洞:
构造代码:
-------------------------------
404 页面不存在
404很抱歉,您要访问的页面不存在!
------------------------------------//form表单target属性:指定框架打开的位置
将其保存为html页面,然后放在我们自己的服务器上,作为一个链接。当用户登录了存在漏洞的网站,并且用户点击了
我们构造的恶意链接时,该链接页面会偷偷打开一个iframe框架,iframe会访问其中的链接,然后执行我们的js代码,
完成表单的提交,表单的用户名参数是我们的js代码。提交完该表单后,该js代码会把存在漏洞的网站的cookie发送到
我们的平台上,单用户却浑然不知,只会获得一个404错误页面。
这里的404页面中隐藏了一个form提交表单,为了防止提交表单后跳转,在表单中添加一个iframe框架,并且iframe框架
的name等于form表单的target,并且设置iframe框架不可见。
当用户点击我们构造的恶意链接时,发现是一个404页面。实际上这个页面偷偷地进行了页面的提交,提交到了我们
指定的平台位置。
构造代码:
--------------------------------------
hello,word!
-------------------------------------
当用户访问了该页面,我们后台就可以看到用户访问记录。
未进行过滤,构造payload
payload:
过滤规则:把< script>用str_replace()函数替换为空了:
尝试双写ript>-->
发现返回hello ript>:问题很奇怪,查看源码,发现:ript>没有被过滤,仅过滤了
弹窗
Hello
ript>
------------------------------
试一下改变大小写可以不:加载payload:弹窗,说明没有对大小写过滤
------------------------------
action one:双写型payload:
action two:大小写型payload:< sCrIPt>alert(“x”); sCrIpT>
过滤规则:$name = preg_replace( ‘/<(.)s(.)c(.)r(.)i(.)p(.)t/i’, ‘’, $_GET[ ‘name’ ] ); 对任何模式的script都过滤了,换标签:
构造payload:
服务器端核心代码:
Hello ${name}
";
}
// Generate Anti-CSRF token
generateSessionToken();
?>
-------------------------------------------------
可以看到,Impossible级别的代码使用htmlspecialchars函数把预定义的字符&、”、 ’、<、>转换为 HTML 实体,
防止浏览器将其作为HTML元素。
可以看出,impossible级别的代码先判断name是否为空,不为空的话然后验证其token,来防范CSRF攻击。
然后再用 htmlspecialchars函数将name中的预定义字符转换成html实体,这样就防止了我们填入标签
当我们输入 时,因为 htmlspecialchars 函数会将 < 和 > 转换成html实体,并且${name}取的是$name的值,
然后包围在标签中被打印出来,所以我们插入的语句并不会被执行。
当我们提交时,通过可以查看源代码,表单提交的过程中,把我们的user_token也一并提交了,
来和服务器端的session_token做验证,防止CSRF攻击。我们输入的代码,直接被当成html文本给打印出来了,并不会被当成js脚本执行
------------------------------
相关函数介绍
trim(string,charlist)
函数移除字符串两侧的空白字符或其他预定义字符,预定义字符包括、\t、\n、\x0B、\r以及空格,
可选参数charlist支持添加额外需要删除的字符。
mysql_real_escape_string(string,connection)
函数会对字符串中的特殊符号(\x00,\n,\r,\,‘,“,\x1a)进行转义。
stripslashes(string)
函数删除字符串中的反斜杠。
------------------------------
未进行过滤
构造payload: name=1
massage=
strip_tags() 函数剥去字符串中的HTML、XML以及PHP的标签,(未过滤使用标签)。
addslashes() 函数返回在预定义字符(单引号、双引号、反斜杠、NULL)之前添加反斜杠的字符串。
可以看到,由于对message参数使用了htmlspecialchars函数进行编码,因此无法再通过message参数
注入XSS代码,但是对于name参数,只是简单过滤了
message =132
构造payload:name =
message = 123
构造payload:name =
message = 123
构造payload:name =
message = 123
通过使用htmlspecialchars函数,解决了XSS,所以无法注入。
通常有一些方式可以测试网站是否有正确处理特殊字符:
>
='>
">
%3Cscript%3Ealert('XSS')%3C/script%3E
(这个仅于IE7(含)之前有效)
没有过滤,只是通过选择框限制了输入,通过Firefox的hackbar直接构造payload
payload:
使用stripos对"
2.输入的值会在value中显示,直接被过滤,换用标签
使用payload:
此时:
发现标签未被显示,接着想办法闭合标签
这里high级别的代码先判断defalut值是否为空,如果不为空的话,再用switch语句进行匹配,如果匹配成功,则插入case字段的
相应值,如果不匹配,则插入的是默认的值。此时,在URL中添加注释#注释的内容不会提交到服务器,而是在浏览器执行:
尝试English#< script >alert(“x”);
构造payload:English#