本Lab學習到關于AngularJS的 xss 漏洞利用
直接輸入回顯頁面,但是把<>進了 html 編碼了
當我們輸入{{1+1}}
,沒有當作字符處理,而是執行了
{{}}
是多種前端框架(如 Vue、Angular、Django 模板等)中常見的模板插值語法,主要用于將數據動態綁定到視圖,雙花括號 {{1+1}}
包裹的表達式會執行運算。
測試{{alert()}}
,因為存在沙箱機制過濾了危險字符
這里用到新的繞過方法{{ $eval.constructor('alert()')() }}
下面分析為什么這樣可以執行alert()
創建 AngularJS 代碼
<!DOCTYPE html>
<html><head><title>AngularJS</title><!-- 引入AngularJS庫(1.6.9版本) --><script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script></head><!-- 定義Angular應用(模塊名為myApp)和控制器(myCtrl)的作用域 --><body ng-app="myApp" ng-controller="myCtrl"><!-- 雙向數據綁定:顯示$scope.firstName的值 -->{{ firstName }}<!-- 表達式計算:直接輸出1+1的結果2 -->{{ 1+1 }} </body><script>// 創建AngularJS模塊(名為myApp),空數組表示無依賴模塊var app = angular.module("myApp", []);// 定義控制器myCtrl,注入$scope服務app.controller("myCtrl", function($scope) {// 在$scope上定義firstName屬性,初始值為"John"$scope.firstName = "John";});</script>
</html>
當我們在代碼中加入{{ $eval.constructor('alert()')() }}
,通過構造函數執行alert()
創建一個<p id="test"></p>
angular.element(document.getElementById('test')).scope();
獲取的作用域對象
$id=2
是子作用域
任何時候我們創建 javascript 對象,都會從原型Prototype繼承一些默認屬性,例如$eval
和$on
$id=1
是根作用域,來自Prototype
我們可以定義一個函數function test()
,最后通過test()
調用這個函數執行打印輸出Hello world!
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/Function
手冊中查看關于Function() Constructor
雖然這是創建函數的方式,但不推薦這樣做
根據上面的方法重新寫一個函數
若不將函數賦給某個變量,將不會執行
記住前面說的
我們直接在后面加()
即可調用函數
所以此時再看本次Lab解題 payload最后這個
()
就是在調用前面通過構造函數創建的函數
這次我們直接看下test()
函數的構造函數,就是Function()
構造函數,因為它可以創建Function
對象
在AngularJS中,$on
是Scope
對象的方法,用于監聽事件。作為函數,它本身是Function的實例,因此其constructor
屬性指向Function
構造函數
$on.constructor('alert()')
等價于 Function('alert()')
,生成一個匿名函數,再通過 ()
調用該函數,于是就形成了最終的 payload
為什么不能直接{{Function('alert()')()}}
,因為有防護機制,所以要用scope
對象的方法的構造函數傳入 payload 執行
PortSwigger 靶場實戰持續更新中
echo "Quermeinhumike+8mmh0dHBzOi8vd3d3LmJpbGliaWxpLmNvbS92aWRlby9CVjE4cDdyejhFaDgv
P3ZkX3NvdXJjZT0zMGU4ODFmYzYxYjJkYWFjMDVmYWFkN2RmZjAyMjMxZgo="|base64 -d