Analisis JavaScript: Endpoint & Parameter (Ethical Recon)
Tujuan & ruang lingkup
Targetnya memetakan endpoint (REST/GraphQL/WebSocket) dan parameter (query/body/header) secara pasif dan/atau izin aktif (di lab sendiri, aset internal, atau program bounty yang in-scope). Tanpa eksploit, tanpa bypass otentikasi. Saat berinteraksi aktif (memuat situs, menjalankan hook), hormati rate-limit dan kebijakan robots untuk crawling lanjutan.
Gambaran alur kerja
- Kumpulkan kandidat JS (dari sitemap/robots/arsip—artikel sebelumnya).
- Static analysis: grep pola URL, parsing AST (Babel/Esprima/Acorn), deteksi GraphQL & runtime config.
- Source maps: coba ambil
*.map
buat melihat file sumber asli & simbol. - Runtime analysis: hook
fetch
/XMLHttpRequest
, pantau WebSocket, inspeksi Network (DevTools/CDP/Puppeteer). - Normalisasi & prioritas: dedup, beri skor berdasarkan kemunculan/recency/kritikalitas.
- Hasil: daftar endpoint + parameter (GET, body, header), catat sumber (file/line, bundle, capture).
Dasar teknis yang perlu dipahami
- Fetch API adalah cara modern melakukan HTTP request di web; ini menggantikan XHR di banyak use case.
- XMLHttpRequest (XHR) masih banyak dipakai dan sering di-polyfill; tetap wajib dipantau.
- WebSocket menyediakan kanal dua arah; banyak aplikasi modern mengirim event/data lewat sini.
- DevTools/Chrome DevTools Protocol (CDP) expose detail request/response untuk analisis jaringan.
A. Static analysis
1) Grep cepat untuk sinyal awal
Cari pola umum di bundel JS:
ripgrep -n --ignore-case \
-e 'https?://[^"'\''\s]+' \
-e '\b/graphql\b' \
-e '\b/api(/|v\d+)?\b' \
-e 'wss?://[^"'\''\s]+' \
-e '(apiKey|auth|token|client_id|x-api-key|Authorization)' \
dist/**/*.js src/**/*.js
2) Parse AST untuk akurasi (Babel/Esprima/Acorn)
Parser memberi struktur kode sehingga string literal, template literal, properti objek, dan nilai default param bisa di kumpulkan dengan struktur yang rapi.
- @babel/parser: dukung TS/JSX & proposal modern; dikombinasi
@babel/traverse
untuk walking. - Esprima dan Acorn: parser cepat/solid untuk tokenisasi & parsing.
Contoh skrip Node (ekstrak endpoint & “nama parameter berisiko”):
// ast-scan.js
import fs from 'fs';
import { parse } from '@babel/parser';
import traverse from '@babel/traverse';
const file = process.argv[2];
const code = fs.readFileSync(file, 'utf8');
const ast = parse(code, {
sourceType: 'unambiguous',
plugins: ['jsx','typescript','classProperties','dynamicImport']
});
const hits = new Set();
traverse(ast, {
StringLiteral({ node }) {
const s = node.value;
if (/^https?:\/\/|^\/graphql\b|^\/api(\/|$)|^wss?:\/\//i.test(s)) hits.add(s);
},
TemplateElement({ node }) {
const s = node.value.cooked || '';
if (/^https?:\/\/|^\/graphql\b|^\/api(\/|$)|^wss?:\/\//i.test(s)) hits.add(s);
},
ObjectProperty({ node }) {
const key = node.key.name || node.key.value || '';
if (/token|auth|apikey|client[_-]?id|session|signature/i.test(key)) {
hits.add(`param:${key}`);
}
}
});
console.log([...hits].join('\n'));
3) Deteksi GraphQL (termasuk Persisted/APQ)
Cek string
/graphql
, body operationName
, variables
, dan extensions.persistedQuery.sha256Hash
(atau ID manifest). Banyak implementasi mengirim hash SHA-256 alih-alih query untuk penghematan bandwidth dan safelisting; pola ini tampak di client Apollo dan gateway modern.B. Manfaatkan source map
Banyak bundel menyertakan komentar
//# sourceMappingURL=...
yang menunjuk ke berkas *.map
. Jika publik, file ini bisa membantu memetakan kode ter-minify ke sumber asli (nama file/fungsi/line), memudahkan pencarian endpoint tersembunyi.# ambil URL .map yang tersemat
grep -RhoE 'sourceMappingURL=([^\s*]+\.map)' dist/*.js \
| awk -F= '{print $2}' | sort -u > maps.txt
# unduh (sesuaikan BASE jika perlu)
while read -r m; do curl -sSLO "$m"; done < maps.txt
Spesifikasi Source Map v3 menjelaskan struktur
sources
, names
, mappings
, dsb., dan (per 2025) ada upaya standardisasi resmi di Ecma.C. Runtime analysis (izin & batas aman)
1) Hook fetch & XHR di browser
fetch()
kini jadi cara utama networking di web; respons bisa di-clone untuk dibaca tanpa mengganggu alur. Hook berikut mencatat method, URL, header, body (ringkas), dan snippet respons.(() => {
const orig = window.fetch;
window.fetch = async function(input, init = {}) {
const url = typeof input === 'string' ? input : input.url;
const method = (init?.method || 'GET').toUpperCase();
console.log('[fetch]', method, url, init.headers || {}, init.body || null);
const res = await orig.apply(this, arguments);
res.clone().text().then(t => console.log('[fetch][resp]', url, res.status, (t||'').slice(0,300))).catch(()=>{});
return res;
};
})();
B. Hook XMLHttpRequest (masih banyak dipakai)
Walau fetch makin dominan, XHR masih sering muncul (terutama di aplikasi legacy atau polyfill). Hook dasar berikut cukup untuk pemetaan awal.
(() => {
const open = XMLHttpRequest.prototype.open;
const send = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.open = function(m,u){ this.__m=m; this.__u=u; return open.apply(this,arguments); };
XMLHttpRequest.prototype.send = function(b){
console.log('[xhr]', this.__m, this.__u, b || null);
this.addEventListener('load', function(){ console.log('[xhr][resp]', this.__u, this.status, this.responseType); });
return send.apply(this, arguments);
};
})();
C. Hook WebSocket
Menangkap event dan payload (teks) membantu memetakan saluran realtime. Untuk biner, tampilkan ringkas/hex agar aman.
(() => {
const Orig = window.WebSocket;
window.WebSocket = function(url, prot){
const ws = new Orig(url, prot);
console.log('[ws][open]', url);
ws.addEventListener('message', ev => console.log('[ws][msg]', url, String(ev.data).slice(0,200)));
return ws;
};
})();
D. DevTools/CDP & Puppeteer (otomasi logging)
- Chrome DevTools → Network: inspeksi request/response dan ekspor HAR.
- Chrome DevTools Protocol (CDP) – Network domain: akses event & detail request/response secara programatik.
- Puppeteer: aktifkan request interception untuk log isi request/response; wajib memanggil
setRequestInterception(true)
dulu.
Contoh Node.js (log metode, URL, query, dan body singkat):
import puppeteer from 'puppeteer';
const url = process.argv[2];
const parseQS = (u) => { try { const usp = new URL(u).searchParams;
const o={}; for (const [k,v] of usp) (o[k]??=[]).push(v); return o; } catch { return {}; } };
const run = async () => {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.setRequestInterception(true);
page.on('request', req => {
const m = req.method(), u = req.url();
const qs = parseQS(u);
let body; try { body = req.postData(); } catch {}
console.log(JSON.stringify({ type:'req', m, u, qs, body }));
req.continue();
});
page.on('response', async res => {
const snippet = await res.text().catch(()=> '');
console.log(JSON.stringify({ type:'res', u: res.url(), status: res.status(), snippet: snippet.slice(0,200) }));
});
await page.goto(url, { waitUntil: 'networkidle2', timeout: 120000 });
await page.waitForTimeout(5000);
await browser.close();
};
run();
Ekstraksi parameter yang konsisten
- Gunakan
URL
&URLSearchParams
untuk querystring (stabil lintas kasus/encoding). Perhatikan interaksiURL.search
↔URL.searchParams
yang dapat memengaruhi serialisasi. - Body non-GET: cek
JSON.stringify({ ... })
,FormData
, atau opsi lib (axios/fetch). - Header:
Authorization
(Bearer),X-API-Key
, custom CSRF/trace id. - GraphQL: catat
operationName
, strukturvariables
, dan sinyal APQ (extensions.persistedQuery.sha256Hash
).
Skoring & prioritas
- Konsensus lintas metode: endpoint yang terlihat di AST + runtime > prioritas tinggi.
- Kebaruan: endpoint aktif di runtime (200/WS open) > string sejarah di bundel.
- Sensitivitas: path atau param yang menyiratkan auth/privilege (
/auth
,/admin
,token
,signature
). - Saluran: REST/GraphQL biasanya lebih mudah diuji; WebSocket perlu analisis format pesan dan alur subscribe.
Output yang di harapkan;
Sumber | Endpoint | Metode | Parameter | Catatan |
---|---|---|---|---|
AST | /api/v2/profile |
GET | user_id |
Muncul di src/api/profile.ts |
Runtime (fetch) | https://api.example.com/graphql |
POST | operationName=GetOrders |
Ada extensions.persistedQuery.sha256Hash |
Runtime (XHR) | /auth/refresh |
POST | refresh_token |
Status 200, cookie HttpOnly |
WebSocket | wss://ws.example.com/realtime |
— | channel=orders |
JSON tiap 5 detik |
Menggabungkan static analysis (AST + source map) dan runtime capture (fetch/XHR/WebSocket via DevTools/CDP/Puppeteer) bikin peta endpoint & parameter jadi presisi. Jalankan sebagai pipeline berkala di aset yang legal/in-scope; simpan bukti (file sumber, offset, log) untuk traceability. Strategi ini menjaga akurasi di 2025, ketika aplikasi makin bergantung pada Fetch, GraphQL persisted queries, dan kanal realtime.
Baca juga Tentang Github Dork