AD

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!"








Posting Komentar

0 Komentar