1. Identifikasi Service yang Rentan Menggunakan nmap
Kami melakukan scaning menggunakan nmap nmap -sV -Pn -T4 10.1.19.10. Kami menemukan beberapa service yg terbuka:
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.11 (Ubuntu Linux; protocol 2.0)
3000/tcp open ppp?
8000/tcp open http Gunicorn
A
1. Kami memulai dengan service 3000/tcp open ppp?
Kami akses melalui chrome dengan mengetikan http://10.1.19.10:3000/. Tampilan awal halaman adalah sebuah aplikasi kalkulator sederhana berbasis web yaitu pada port 3000.
2. Kami coba menginputkan penjumlahan tapi menggunakan browser di burpsuite yaitu 2+2
dan Hasilnya: 4
→ Artinya server melakukan evaluasi terhadap input.


3. Nah Karena server mengevaluasi input, saya coba masukkan payload JavaScript karena Server menjalankan Node.js. Kami coba untuk mengakses modul internal dengan bebrapa payload hingga ketika kami menggunakan payload berikut:
process.mainModule.require('child_process').execSync('id').toString()
Yang saya dapat adalah:
uid=1002
: ID user sistem operasi Linux dari server.
wrth
: adalah nama user.
4 .Nah disini server menjalankan ekspresi langsung dari input pengguna menggunakan eval()
tanpa validasi. Artinya dengan memanipulasi input saja kami mendapatkan akses RCE.
Jadi singkatnya Server tidak memeriksa input yang kami masukan di form. Jadi apapun yg kmai inputkn langusng di eksekusi olh server. Dan singkatnya payload yg kami masukan di input, jika dianalogikan seperti kami menyuruh server untuk menjalankan perintah id di terminal server, lalu kirim hasilnya balik ke kami sebagai teks.
B
mov rbx, 0x6f6c6c6548
push rbx
mov rsi, rsp
mov rdx, 5
mov rdi, 1
mov rax, 1
syscall
mov rax, 60
xor rdi, rdi
syscall
outputnya halo
iki ws termasuk kerantanan
tapi golet conoth nng dunia nyatane, output apa yg real life

const http = require('http');
const url = require('url');
const querystring = require('querystring');
const server = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url);
const pathname = parsedUrl.pathname;
const method = req.method.toUpperCase();
if (pathname === '/' && method === 'GET') {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<!DOCTYPE html>
<html>
<head>
<title>Calculator</title>
</head>
<body>
<h1>Simple Calculator</h1>
<form action="/calculate" method="post">
<input type="text" name="expression" placeholder="Enter expression (e.g., 2+2*3)" required>
<button type="submit">Calculate</button>
</form>
<div id="result"></div>
</body>
</html>
`);
} else if (pathname === '/calculate' && method === 'POST') {
let body = '';
req.on('data', chunk => {
body += chunk.toString(); // convert Buffer to string
});
req.on('end', () => {
const formData = querystring.parse(body);
const expression = formData.expression;
let result;
let error = null;
if (typeof expression !== 'string') {
error = 'Invalid input type.';
} else {
try {
// WARNING: Using eval with user input is insecure and can lead to Remote Code Execution.
// This is included specifically as requested by the user prompt.
// In a real-world application, use a safer math expression parser library.
result = eval(expression);
} catch (e) {
error = `Error evaluating expression: ${e.message}`;
}
}
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<!DOCTYPE html>
<html>
<head>
<title>Calculator Result</title>
</head>
<body>
<h1>Calculation Result</h1>
<p>Expression: <code>${expression || ''}</code></p>
<p>Result: <strong>${error ? `<span style="color:red;">${error}</span>` : result}</strong></p>
<a href="/">New Calculation</a>
</body>
</html>
`);
});
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found');
}
});
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
console.log(`Server listening on port ${PORT}`);
console.warn('WARNING: This server uses eval() for calculations, which is insecure and vulnerable to code injection.');
});
Langkah pertama kami mencari file config service yg vuln di server.
Untuk Service 3000 (Simple Calculator) ada di /home/ubuntu/calc/server.js
Dan untuk service 8000 (Assembly x86-64 Runner) ada di /home/rui/shellrunner/server.py
Setelah ketemu, kami coba ubah bagiana code yg rentan saja
Service 3000 (Simple Calculator)
pada file konfig ini ketika kita cari code yg membuat rentan ada di bagian:
result = eval(expression);
lalu kami ubah menjadi
if (/^[\d+\-*/ ().]+$/.test(expression)) {
try {
result = Function('"use strict"; return (' + expression + ')')();
} catch (e) {
error = `Invalid expression: ${e.message}`;
}
} else {
error = 'Invalid characters in expression.';
}
Service 8000 (Assembly x86-64 Runner)
pada file konfig ini ketika kita cari code yg membuat rentan ada di bagian:
compiled_code = asm(user_input)
result = subprocess.check_output(["./main", compiled_code.hex()], stderr=subprocess.STDOUT)
lalu kami ubah menjadi:
allowed = re.compile(r'^(mov|push|pop|xor|syscall|ret|add|sub|cmp|inc|dec|nop|and|or|shr|shl)\b', re.IGNORECASE | re.MULTILINE)
if all(allowed.match(line.strip()) for line in user_input.splitlines() if line.strip()):
from pwnlib.asm import asm
from pwnlib.context import context
context.arch = 'amd64'
context.os = 'linux'
compiled_code = asm(user_input)
result = subprocess.check_output(["./main", compiled_code.hex()], stderr=subprocess.STDOUT)
output = result.decode(errors="replace")
else:
output = "Instruction not allowed!"
0 Komentar