Như tên bài, easy thật :)))
Bài này cung cấp cho ta sẵn symbol của dump file luôn nên độ khó và thời gian làm coi như giảm tới 80% rồi :)))
Mình bỏ symbol vào đường dẫn \volatility3\volatility3\symbols\linux
file zst chứa json
Sau đó mình giải nén và nén lại bằng đuôi .xz
vì nếu không thì sẽ không chạy.
Rồi thì chạy volatility thôi :)))
Đề bài bảo là "in as shell command" nên mình dùng plugin linux.bash
Đề bài có đề cập tới việc flag trông giống UUID, vậy flag là:
08ffea76-b232-4768-a815-3cc1c467e813
Bài này cho file mail, việc của mình làm tìm ngày giờ thật sự mà mail đó được gửi.
Mở bằng notepad
Mình dùng phần mềm eml viewer mở lên nhưng không tìm thấy gì. Sau đó mình nghĩ tới DKIM nhưng mà không phải, sau đó mình stuck và đi hỏi a @Bquanman thì ảnh gửi cái link này
Mình tải phần mềm về và nhập boundary delimiter vào
Flag là: utflag{03/04/2023-06:06}
Mở bằng IDA64:
Shift + f12 để xem string và tìm được flag
Bài này cho file game, kiểm tra bằng lệnh linux thì thấy đây là Macromedia Flash data
Bài này khó ở chỗ đi tìm được và đúng tool để decompile, ban đầu mình tìm được cái tool gì đó mà bị sai nên mình đi hỏi thì được tool: JPEXS Free Flash Decompiler
Mở file Game -> Text search -> "utflag", bùm ra flag
Hoặc có thể dùng nmap:
Ở bài này thì server dùng SMB Port (port 445). Ban đầu mình nghĩ theo hướng dùng SMBClient để tương tác với SMB Server nhưng không được
Thế nên sau đó mình google để tìm một giải pháp khác, mình search với cụm từ "smb port ctf" để tìm kiếm những write-up nào đấy tương tự bài này. Thật may mắn khi ngay sau đó mình tìm được bài này và đây cũng là bài của giải này 2 năm trước.
Mình sử dụng smbget
(smbget is a simple utility with wget-like semantics, that can download files from SMB servers) để download files từ SMB Server
Sau khi download xong thì mình xem qua các file trong thư mục đã tải thì tại đường dẫn WorkShares\shares\IT\Itstuff
có một file tên là notetoIT
, mình mở lên bằng notepad và đọc nội dung trong đó
Lưu ý là nội dung trong file này còn được sử dụng cho challenge tiếp theo.
Okay vậy là mình đã tìm được flag.
Challenge này sử dụng máy chủ SSH (port 22). Nhìn vào tiêu đề thì cũng có thể đoán được muốn giải được bài này phải tìm được ussername và pasword để truy cập vào máy chủ SSH. Vậy nên mình tìm hiểu về Hydra cũng như cách brute force SSH https://www.geeksforgeeks.org/how-to-use-hydra-to-brute-force-ssh-connections/
Sau khi tìm hiểu thì mình bị bí ở cái chỗ dùng từ điển vì rockyou
thì có quá nhiều từ mà brute force SSH qua Hydra nhìn chung thì khá lâu, vậy nên mình tìm thử common SSH username password wordlist
, mình tìm được cái này nhưng không bruteforce được.
Thế là mình tìm giải pháp trên google "ssh port ctf utctf" thì mình tìm được bài này, bài này giống đến 80% bài mình đang giải và cũng cùng tác giả luôn.
Sau khi đọc một hồi và nhớ tới dòng "We've gathered a lot of information…" thì mình nhớ tới đống dữ liệu mình tìm ở bài trước
Oke, thế là mình quay lại, dùng đống dữ liệu đấy để làm cái wordlist, bao gồm những cái tên: Crystal Ball, Wade Coldwater, Jay Walker, and Holly Wood và password mặc định có thể là "abracadabra". Tất cả word được tạo theo quy tắc standard unix username conventions
.
Cái wordlist mình tạo có khoảng >200 words, bao gồm những cái tên kia, con mèo của Jay Walker và những thứ mà mình nghĩ có thể là username, mình brute force quá trời mà vẫn không đúng nên mình bruteforce cả password, sau đó 2 tiếng vẫn không ra gì nên mình đọc kỹ lại file "notetoIT" và mình chú ý đến cụm Can you please reach out to them and get them to change thier passwords or at least get them append a special character
mà ban đầu mình nghĩ là câu này để nói với người chơi.
Sau đó mình tạo thêm 1 đống words là abracadabra + ký tự đặc biệt
Rồi mình brute force lại và bùm, thành công.
Rồi mình dùng username và password tìm được để đăng nhập vào máy chủ SSH và lấy flag
Clear network
:siuuuuuu:
Challenge cho 2 file commands.zip.b64
verìy_hash.py
server netcat: nc betta.utctf.live 12748
Theo như description thì mình sẽ gửi một đoạn mã base64 đến server, server sẽ decode nó thành dữ liệu của một file zip, sau đó đọc file commands/command.txt
rồi hash nội dung trong file đó sao cho đoạn hash đó bằng đoạn hash đã cho, nếu bằng thì nó sẽ thực thi câu lệnh shell trong file command đó
Mình cũng bỏ ra khá nhiều thời gian cho bài này, đầu tiên là đoạn hash đề bài cho chính là hash md5 của chuỗi echo 'Hello World!'
. Ý tưởng ban đầu của mình là pad thêm các bytes phía sau nội dung để có được một đoạn hash md5 hợp lệ, nhưng mà cách này không có khả dụng :)), và tác giả cũng nói là đây không phải là cách hợp lệ nên mình cũng bỏ qua luôn
Sau một hồi lâu suy nghĩ và tính toán thì mình có ý tưởng zip 2 file command.txt lại để rồi khi extract ra thì nó sẽ ghi đè lên nhau.
Đầu tiên mình tạo ra 2 file command.txt và commans.txt trong folder commands sau đó zip folder này lại. Mình sử dụng câu lệnh sed -i 's/commans/command/g' commands.zip && cat commands.zip | base64 -w 0
, câu lệnh này có nghĩa là thay thế các chuỗi có tên commans thành command
Vậy là thành công, khi nó extract là sẽ ghi đè lên nhau
Flag: utflag{https://youtu.be/bZe5J8SVCYQ}
Đây là một chương trình đoán số mà chương trình random, nếu đoán trúng thì mình sẽ được một password để qua level này
Level 0:
Mình thử truyền vào một chuỗi "abc"
thì chương trình trả về lỗi
Từ đó mình biết được đây là một chương trình python sử dụng hàm eval để thực thi đầu vào của mình. Trong python hàm eval()
sử dụng để thực thi các câu lệnh python
Vậy nên ở level này mình sẽ thử sử dụng hàm dir()
trước. Dir() sẽ trả về một danh sách các thuộc tính hợp lệ của đối tượng.
Thử gửi print(dir())
Như mình có thể thấy thì mình có thể sử dụng biến password
và solution
luôn. Vậy nên mình cứ print(password)
là win
Gửi print(password)
và mình có được password Level 0: PuXqj7n4WNZzStnWbtPv
Level 1:
Ở level 1 khác với level 0 là sử dụng hàm eval(answer, {"open": None})
. Có nghĩa là mọi hàm open sử dụng trong answer đều được trả về None
print(dir())
thì mình thấy các thuộc tính hợp lệ ở đây đã có giới hạn, có nghĩa là mình không thể trực tiếp print(password)
được nữa
Thử RCE với câu lệnh exec()
trong python thì câu lệnh eval()
có chức năng thực thi câu lệnh python, nhưng câu lệnh exec()
có chức năng thực thi đoạn code python
Gửi đi exec("import os; os.system('ls')")
, kết quả trả về 2 file password.txt và problem.py
Đọc file password.txt exec("import os; os.system('cat password.txt')")
Password level 1: Krdi9yQuY8mHoteZDCF5
Level 2:
Ở level 2 thì ta có hàm eval như sauresult = eval(answer, {})
, khác với level 1 thì ở đây nó không còn hạn chế tham số open nữa, nhưng mà như bài trước thì mình vẫn có thể RCE
RCE để đọc source problem.py
: exec("import os; os.system('cat problem.py')")
Như mình thấy trong source code thì sau khi đọc file password thì chương trình xoá luôn file password.txt
Mình cũng đã thử nhiều cách để recovery lại file password này nhưng mà đều fail hết :))
Nhưng mà suy nghĩ theo luồng chương trình thì mỗi lần chạy file problem.py thì chương trình đều phải đọc file password.txt rồi sau đó là xoá file password.txt này luôn, nếu như chương trình này cùng chạy trên một server thì chương trình phải tạo ra file password mới sau đó là xoá nó. Vậy nên mình sẽ liên tục RCE và cat password.txt dù chỉ có một vài milisecond
Sử dụng Burp Intruder
Payload:
Kết quả sau khi attack
Password level 2: E46Dnqb5enAMgGArbruu
Level 3:
Ở level này mình không thể RCE như các level trước được nữa, vì ở đây hàm eval đã chặn mình sử dụng __builtins__
, nếu như không có __builtins__
thì mình không thể sử dụng các hàm, câu lệnh như open, import, print,...
Nhưng mà trong bộ nhớ python cũng đã có import rất nhiều thư viện rồi, trong số đó cũng có thể thực hiện được RCE
Mình có thể xem cách bypass eval khi không có builtins ở đây https://book.hacktricks.xyz/generic-methodologies-and-resources/python/bypass-python-sandboxes#no-builtins
Và mình có được payload __builtins__.__class__.__base__.__subclasses__()[132].__init__.__globals__['popen']('ls+-al').read()
Như mình có thể thấy thì trên server có tồn tại 3 file
cat exploit.txt và mình có được password: 5F4p7aLgQ5Nfn5YM8s68
Sau khi submit password level 3 thì mình có được flag: utflag{LGvb7PJXG5JDwhsEW7xp}
Giao diện trang web như sau
Ở cuối trang web có một phần submit confession
Mình thử đọc qua source code trước thì mình thấy chương có một phần khả nghi ở bức ảnh đầu trang web
IDOR để đến /images/img1.png
thì mình thấy được một hình ảnh có chứa một đoạn code ó vẻ là đoạn INSERT confession vào database
Mình cũng đoán ra được đây là lỗi SQL injection, và phần submit form kia chính là post confession lên database
Mình thử POST confession lên thử xem sao nhưng mà lúc được lúc không
Lúc post được thì nó trả về thanks for confessing[]
còn không thì nó trả về Hey that's not a confession!
Xem lại source code để đối chiếu thì phía sau thanks for confessing
là str(comments)
cũng chính là []
ở phía sau output ở ảnh trên
Mình xem lại đoạn code trên và phân tích, 3 dòng đầu chỉ là thực thi câu query insert, đoạn code comments = c.fetchall()
có nghĩa là trả về kết quả câu query dưới dạng list, với mỗi phần từ là tuple là kết quả của các cột
Để inject vào câu query trên thì mình có thể đóng câu query trước để thực hiện câu query sau, payload: "); SELECT * FROM confessions-- -
Flag: utflag{thanks_for_confessing_your_sins}