Hooray! Chưa gì đã hết 4 tuần rồi. Dưới đây sẽ là Writeup cho Week 4 – tuần cuối cùng của NCSA Secure Coding CTF. Sẽ có 5 challenge mỗi tuần, liên tục trong 4 tuần. Flag được tìm bằng cách phân tích mã nguồn web server được viết hầu hết bằng Java, PHP và Python, tất cả đều có mức độ phù hợp cho beginner.Challenge đầu tiên here we go!Password GuessingỞ challenge này mình cần phải điền đúng password. Cùng xem mã nguồn có gì nào:Server lấy password mình nhập và truyền vào file main:File main trông như thế này:Một đoạn code khá đơn giản: Nó khai báo biến check = “F”, sau đó so sánh string mình nhập và string ACTUAL_PASS được khai báo ở đâu đó khác mình không thể biết. Nếu 2 string đó bằng nhau thì biến check sẽ được chuyển thành “T”. Và một khi biến check bằng “T” thì mình sẽ có được flag.Điểm yếu của đoạn code này là nó không kiểm tra độ dài string mình nhập vào, cho phép mình nhập ra ngoài cả giới hạn bộ nhớ của biến đó. Trong trường hợp này, pass chỉ được giới hạn [10] ký tự, nhưng nếu mình nhập 11 ký tự thì 1 ký tự thừa đó sẽ được viết đè lên biến check được khai báo ngay phía trên:Vậy là ký tự thứ 11 của mình nhập sẽ được viết đè lên biến check, và chúng ta đang cần biến check = “T”:aaaaaaaaaaTflag{iES4ZNwB8ZLt4f2SghFKT86rXTXcOiZNt3lD}Real ID 2Challenge này gần giống hệt challenge Real ID 1 ở Week 1. Sự khác biệt nằm trong mã nguồn:Đoạn code này kiểm tra có file nào trùng tên với id được truyền vào không. Nếu có thì sẽ gửi file đó. Như tuần 1, định dạng id là các số tự nhiên nên mình hoàn toàn có thể brute force id để tìm ra file flag.txt. Tuy nhiên ở challenge này mình không biết định dạng các id trông như thế nào, nên không thể brute force được. Kiểm tra các id file xem được thì mình thấy đều có điểm chung:Chúng đều có 13 ký tự. Sau khá lâu mày mò thì mình mới phát hiện ra id của các file chính là 13 ký tự đầu của giá trị hash MD5 của chính tên file đó.Vậy file flag.txt sẽ có id là 13 ký tự đầu giá trị hash của “flag.txt”, chính là “159df48875627“:http://insecure.vford.com:8010//files.php?id=159df48875627flag{P9PvPrKyRVBTkVLdS3cVYXZkgrD4WGL6AsHw}Juggling 2Mình lại phải nhập đúng mật khẩu. Mã nguồn thì khá đơn giản:Điểm yếu của phép so sánh trong PHP là NULL sẽ bằng giá trị 0. Vậy ta chỉ cần làm hàm strcmp trả về NULL là xong. Mà hàm strcmp sẽ trả về NULL khi có lỗi trong quá trình so sánh 2 string. Cụ thể là khi so sánh 1 thứ không phải string với 1 string thì hàm strcmp sẽ trả về NULL. Vậy nên thay vì gửi mật khẩu dưới dạng string, mình sẽ gửi một object mảng:http://insecure.vford.com:8005/?password[]=niceĐương nhiên shell sẽ báo lỗi và sau đó ta vẫn có được string nhờ điểm yếu trong PHP mình nói phái trên,flag{J3Sz8wPQX5rlflfK0pektPuqsbckAcSwnF8U}ThunderstruckMột phần login quen thuộc. Cùng mình check thử mã nguồn xem sao:Password được tạo từ một hàm có tên generateSecurePassword():Hàm này khai báo biến random là 1 số ngẫu nhiên từ 0 đến 20, sau đó nhân với 16578, rồi XOR 654321. Tiếp theo là chuyển đổi từng ký tự trong biến password phía trên (“magicallysecure”) thành số theo bảng ASCII, rồi cộng vào giá trị random đang có. Như vậy, với 1 giá trị của random ban đầu sẽ cho ra 1 và chỉ 1 output. Điểm yếu của hàm gen pass này là số lượng password chỉ có 21 (tương ứng với 21 giá trị ban đầu của random). Mình sẽ chỉ cần gen ra 21 cái password này và thử từng cái một là oke. random = 0 --> password: 655915 random = 1 --> password: 639341 random = 2 --> password: 622767 random = 3 --> password: 606193 random = 4 --> password: 589619 random = 5 --> password: 573045 random = 6 --> password: 558519 random = 7 --> password: 541945 random = 8 --> password: 787483 random = 9 --> password: 770909 random = 10 --> password: 754335 random = 11 --> password: 735713 random = 12 --> password: 719139 random = 13 --> password: 702565 random = 14 --> password: 685991 random = 15 --> password: 669417 random = 16 --> password: 917003 random = 17 --> password: 900429 random = 18 --> password: 883855 random = 19 --> password: 867281 random = 20 --> password: 850707Thử từng cái một với username là “admin” và mình tìm được flag:flag{gKNmYKvVMhaqfapF2ZWTEoiRKbKaaYZXMRBQ}Git GudHmn… Lại là một trường login.Mã nguồn server không chỉ xử lý mỗi “username” và “password” trong path mà còn cả “git”, “log” và “checkout”. Nếu trong path có “git” và “log” thì server sẽ trả về lịch sử commit:http://insecure.vford.com:7009/?git=logCommit log được server trả về khá nhiều. Để xem một commit, theo như trong mã nguồn, ta cần gán parameter “git” = “checkout” và cung cấp mã hash của commit đó. Trong đống commit kia mình thấy có một cái rất thú vị:Thử xem trong đó có gì nào:http://insecure.vford.com:7009/?git=checkout&hash=c1dce57829668b82678d4868ec58917fa37cfeabNice. Sử dụng chúng để đăng nhập, ta có ngay flag:flag{L3US0fverKRZwS2ZvaDTYuNXVo3dYKNzWpsj}Whoosh… Vậy là 4 tuần của NCSA Secure Coding Challenge đã kết thúc. Tuy challenge chỉ dừng lại ở mức độ beginner nhưng debug mã nguồn các challenge cũng khiến mình đau não phết. Các bạn hãy đón đọc writeup của các kỳ CTF khác nữa nhé! Peace!