FPTU SecAthon 2020 | Web Writeup | IAW301 & IAW302

FPTU SecAthon 2020 | Web Writeup | IAW301 & IAW302


author: Hades

IAW301

0

SOLUTION

Dựa vào hint 2 ta đọc source và biết ngay vuln tại phần email trong chức năng registration.

$regexEmail = array("options" => array("regexp"=>"/^(?!(?:(?:\\\\x22?\\\\x5C[\\\\x00-\\\\x7E]\\\\x22?)|(?:\\\\x22?[^\\\\x5C\\\\x22]\\\\x22?)){255,})(?!(?:(?:\\\\x22?\\\\x5C[\\\\x00-\\\\x7E]\\\\x22?)|(?:\\\\x22?[^\\\\x5C\\\\x22]\\\\x22?)){240,}@)(?:(?:[\\\\x21\\\\x23-\\\\x27\\\\x2A\\\\x2B\\\\x2D\\\\x2F-\\\\x39\\\\x3D\\\\x3F\\\\x5E-\\\\x7E]+)|(?:\\\\x22(?:[\\\\x01-\\\\x08\\\\x0B\\\\x0C\\\\x0E-\\\\x1F\\\\x21\\\\x23-\\\\x5B\\\\x5D-\\\\x7F]|(?:\\\\x5C[\\\\x00-\\\\x7F]))*\\\\x22))(?:\\\\.(?:(?:[\\\\x21\\\\x23-\\\\x27\\\\x2A\\\\x2B\\\\x2D\\\\x2F-\\\\x39\\\\x3D\\\\x3F\\\\x5E-\\\\x7E]+)|(?:\\\\x22(?:[\\\\x01-\\\\x08\\\\x0B\\\\x0C\\\\x0E-\\\\x1F\\\\x21\\\\x23-\\\\x5B\\\\x5D-\\\\x7F]|(?:\\\\x5C[\\\\x00-\\\\x7F]))*\\\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\\\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\\\]))$/iD","default"=>false));
    if (filter_var($username, FILTER_VALIDATE_REGEXP, $regexUsername)){
      if (filter_var($email, FILTER_VALIDATE_REGEXP, $regexEmail)){
.............
}}

Và dưới đây là câu query signup bị vuln:

$sql = 'INSERT INTO Users (username, email, password) VALUES ("'.$username.'", "'.$email.'", "'.md5($password).'")';

Để inject và lấy dữ liệu trong database được, chúng ta cần bypass cái regex ở trên, bằng một số kĩ thuật fuzzing và document

PAYLOAD

#payload bind-sqli username=a&password=b&email="||(ascii(substr((select 'aa'),1,1))>53)||"@aaaaaagmail.com

⇒ Flag: FUSEC{Fuzzing_Email_For_SQLi}

IAW302

1

Source code:

<?php
    session_start();
    @include '/flag.php';

    if(!isset($_GET['choose'])){
        highlight_file("result.php");
        die();
    }

    $name = md5(date("ms").md5($_GET['choose']).@$_COOKIE['PHPSESSID']);
    session_destroy();
    $log_file = "./".$name.".txt";
    echo "Log: $log_file</br>";

    file_put_contents($log_file,$_GET['choose']);
    if(@unlink($log_file)){
        die("Loser");
    }
    echo @$flag;
?>

SOLUTION

Sau khi test sơ qua mình đã thấy được code mà author cung cấp ở http://35.198.195.87:7002/result.php. Đây cũng là 1 dạng được khá nhiều người biết đến, dùng kĩ thuật race condition để khai thác. Và bây giờ mình sẽ phân tích, tại sao lại có thể exploit bằng race-con.

  • Đầu tiên giá trị của $name được gán bằng md5-encode của date, get parametersession, tiếp theo đó $name được lấy làm tên file txt và được nạp nội dung vào, sau đó kiểm tra xóa file thông qua đoạn if(@unlink($log_file)), nếu false thì echo flag, và ngược lại thì die("Loser").

  • Nhìn thì có vẻ như không có bất kì vuln nào, nhưng các bạn hãy chú ý vào đoạn session_destroy(); được đặt giữa source code và nó có chức năng hủy session. Điều này rất nguy hiểm, vì nếu session bị hủy giữa chừng và đồng thời có nhiều request được gửi tới thì sẽ gây ra tình trạng mất dữ liệu bất ngờ, trong trường hợp trên thì sẽ mất dữ liệu của $name

Do đó để unlink trả về false thì chỉ cần làm cho $name bị mất dữ liệu thì sẽ không tồn tại tên file , bằng cách dùng race condition để tạo ra nhiều request đồng thời:

"Warning Immediate session deletion may cause unwanted results. When there is concurrent requests, other connections may see sudden session data loss. e.g. Requests from JavaScript and/or requests from URL links. Although current session module does not accept empty session ID cookie, but immediate session deletion may result in empty session ID cookie due to client(browser) side race condition. This will result that the client creates many session ID needlessly. To avoid these, you must set deletion time-stamp to $_SESSION and reject access while later. Or make sure your application does not have concurrent requests. This applies to session_regenerate_id() also." - From PHP Main Page

PAYLOAD

Chỉ cần dùng thread để spam là okie !

⇒ Flag: FUSEC{Hua_voi_moi_nguoi_lan_nay_lan_cuoi_dao_de}