Writeup Final KKS TNI AD 2021 – Vaksinasi (Misc)

Last Update Article: 2021-09-29 04:55:44


Writeup Final KKS TNI AD 2021 – Vaksinasi (Misc)

Assalamualaikum warahmatullahi wabarakatuh, kali ini saya akan mencoba menulis cara menyelesaikan soal Final KKS TNI AD 2021 berjudul Vaksinasi dan berkategori Misc.

Untitled

Diberikan sebuah file pyc bernama peserta.pyc yang di-compile menggunakan lastest python version, yang mana hal ini membuat pyc ini tidak bisa di-uncompile dengan tools uncompyle6. Berikut ini tampilan dari net servicenya

Untitled

Untuk mengetahui alur kerja dari aplikasi tersebut, maka cara salah satunya adalah melakukan dumping bytecode dari pyc-nya. Saya menggunakan script seperti berikut ini

Untitled

Jalankan script tersebut dan akan mendapatkan banyak dump dari bytecode dari file peserta.pyc seperti ini contohnya

Untitled

Silahkan dilakukan translasi sendiri ke algoritma yang dipahami, namun untuk source code yang asli berbentuk seperti ini:

#!/usr/bin/env python

import sys
import json
import os
from random import randint as ra
import requests as r

caps = 0

try:
    urls = os.environ['url_api'] + "/readfile"  # export url_api=http://192.168.77.62:8080
    get_secret = r.post(urls, data={'files': 'secret.txt'}).text
    caps = get_secret
    sys.stdout.write("Connection was ok!")
except:
    sys.stdout.write("Connection was failed!")
    caps = 10

if not os.path.isdir("logs"):
    os.mkdir("logs")

anti_bot = ra(9999, 999999) + int(caps)

jenis_kelamin = {
    '1': "cowok",
    '2': "cewek",
    '3': "rajelas"
}

welcome = "Halo, selamat datang di Program Vaksinasi WKakut1337 (Wibu / Kpop Akut)\n\nKami sadar wabah ini sudah menjangkit banyak warganet yang dampaknya suka membuat gaduh"
welcome += "\n\nSetelah melakukan studi mendalam, panitia telah menemukan vaksinnya, daftarkan diri anda sekarang!\n"

sys.stdout.write(welcome)
sys.stdout.write("\n")
sys.stdout.write("Isikan data diri anda dulu\n")
sys.stdout.write("Masukan nama anda: ")
sys.stdout.flush()

nama_penerima = sys.stdin.readline().strip()

sys.stdout.write("\n1. Laki-Laki\n2. Perempuan\n3. Tidak ingin menyebutkan\n\n")
sys.stdout.write("Masukan jenis kelamin anda: ")
sys.stdout.flush()

jenis_kelamin_penerima = sys.stdin.readline().strip()

if str(jenis_kelamin_penerima) not in ['1', '2', '3']:
    sys.stdout.write("Pilihan cuman 1,2,3 gak usah milih yang lain")
    sys.stdout.flush()
    exit(0)

sys.stdout.write("Masukan umur anda: ")
sys.stdout.flush()

umur_penerima = sys.stdin.readline().strip()

if int(umur_penerima) <= 10:
    sys.stdout.write("Penerima vaksin setidaknya berumur 11 tahun!\n")
    sys.stdout.write("11 tahun kurang silahkan berikan pendidikan moral saja!\n")
    exit(0)

must_CAPTCHA = (((anti_bot * int(umur_penerima)) + anti_bot) / anti_bot)

with open("logs/" + str(anti_bot), 'w') as file:
    file.write(json.dumps({
        'nama': nama_penerima,
        'kelamin': jenis_kelamin[jenis_kelamin_penerima],
        'umur': umur_penerima
    }))

sys.stdout.write("Masukan CAPTCHA: ")
sys.stdout.flush()

gimme_CAPTCHA = sys.stdin.readline().strip()

if int(gimme_CAPTCHA) == int(must_CAPTCHA):
    sys.stdout.write("Apakah memiliki sebuah penyakit bawaan (yes/no): ")
    sys.stdout.flush()
    penyakit_pasien = sys.stdin.readline().strip()
    if str(penyakit_pasien).lower() == 'yes' or str(penyakit_pasien).lower() == 'y':
        sys.stdout.write("Kami memprioritaskan warganet yang sehat!\n")
        exit(0)
    else:
        alamat_pasien = input("Masukan alamat: ")
else:
    sys.stdout.write("Tolong lengkapi CAPTCHA dengan benar\n")
    exit(0)

Terlihat input dari awal terlihat biasa saja, namun ada 1 validasi penting yaitu diminta sebuah CAPTCHA yang mana angka dari captcha didapatkan dari sebuah REST API dan dibuat secara acak dengan jarak 9999-999999. Algoritma pengecekan captcha dibuat seperti ini:

Untitled

Satu-satunya input yang dapat kita kontrol dari algoritma di atas adalah inputan umur *sebenarnya algoritma ini cukup sederhana, angka random dikalikan dengan umur lalu ditambahkan dengan angka random lalu dibagi dengan angka random. Cara tercepat memahami letak celah dari algoritma ini adalah melakukan teknik brute force yang mana kita kontrol kedua angkanya, lalu diperhatikan outputnya berikut script* yang digunakan

Untitled

Dan saat dijalankan akan mengeluarkan output seperti berikut ini:

Untitled

Untitled

Untitled

Terlihat meskipun anti_bot bernilai 73,99,29 hasil dari must_captcha akan selalu sama, berarti anti_bot di sini tidak begitu berguna. Lalu saat inputan umur di isi 0 maka must_captcha akan selalu 1 tidak peduli berapapun nilai dari anti_bot. Maka dari sini rumus untuk mendapatkan must_captcha adalah di mana N adalah inputan dari umur. Menurut dari deskripsi di soal, versi python yang digunakan di server adalah python2, yang mana jika di lihat di bagian akhir input dari setelah captcha adalah input biasa bertanya apakah mempunyai riwayat kesehatan, namun setelah itu adalah input yang memiliki celah yang dapat mengarah ke RCE (Remote Code Execution) di bagian ini:

Untitled

Kita dapat mengatur exploit-nya seperti berikut ini

Untitled

Sesuai dengan instruksi saya di waktu Final KKS TNI AD 2021, saya mengatakan “Flag ada di dalam Database”. Setelah melakukan RCE di sini tidak ditemukan apapun yang menarik meski mendapatkan akses root langkah selanjutnya adalah melakukan review ulang di script yang telah ditranslasi dan berfokus ke:

Untitled

Di bagian itu, terlihat script mencoba mengambil valuasi dari environment variable bernama url_api dan melakukan post data pengambilan data di endpoint /readfile dengan parameter files dengan nama file adalah secret.txt*. Berarti kita perlu mendapatkan url aslinya di dalam environment* variable setelah RCE.

Untitled

Didapatkan url_api yang jika dibuka di browser akan mengembalikan hasil seperti berikut ini

Untitled

Hasil dari header balasannya seperti berikut ini

Untitled

Didapatkan informasi bahwa aplikasi ini dibangun menggunakan framework Express dari NodeJS. Sekarang dapat dicoba mengambil secret.txt seperti berikut ini, penulis menggunakan Thunder Client:

Untitled

Di situ berhasil mengambil file secret.txt dan berhasil, dan saat mengalami kesalahan nama files akan mengeluarkan hasil seperti berikut ini:

Untitled

Terlihat di situ, bahwa file secret.txt berada di dalam folder secret dengan informasi awal bahwa framework yang digunakan adalah Express maka kita dapat mengambil package.json yang ada di luar folder secret seperti berikut ini:

Untitled

Tapi ternyata, inputan yang mengandung kata .json ataupun .js akan dihilangkan, cara sederhana melakukan bypass adalah melakukan crafting seperti berikut ini:

Untitled

Terlihat di bagian package.json terdapat library “node-serialize”: “^0.0.4” yang memiliki celah RCE dan endpoint untuk inject pointnya ada di dalam routes/index.js

Untitled

Lalu di bagian routes /save terdapat serialize.unserizalize yang menerima inputan base64 dari field kelamin berbentuk base64. Kita dapat menyusun payloadnya menggunakan nodejsshell.js berikut susunan payloadnya.

{“rce”:”_$$ND_FUNC$$_function (){payload}()”}

Encode dengan base64 dan masukan ke dalam field kelamin seperti berikut ini

Untitled

Dan lakukan listen di server dengan nc -lvp 1339 seperti berikut ini:

Untitled

Dan dapatkan environment variable di dalamnya dengan printenv.

Untitled

Variabel yang dibutuhkan sesuai dengan koneksi yang dilakukan REST API di dalam app.js

Untitled

Tinggal melakukan remote koneksi ke dalam database

Untitled

Dapatkan flagnya di dalam tabel flag

Untitled

Decode hasil dari kolom flag

Untitled

Flag: KKST2021{Vaksin_Untuk_negeri}

Sampai akhir Final KKS TNI AD 2021, tidak ada satu tim pun yang berhasil menyelesaikan soal ini. Terima kasih untuk semua peserta!