swisskyrepo.github.io/_posts/2019-12-14-Ph0wn-CTF.md

12 KiB
Executable File
Raw Permalink Blame History

layout title image
post Ph0wn CTF 2019 - Smart Devices CTF /images/Ph0wn/Ph0wnBanner.png

Another week another CTF, this time it was the Ph0wn at Sophia Antipolis (France). I teamed up with members from @Maki, @iansus, @MansourCyril and @0hax. We reached the second place of this IoT/Hardware CTF.

![Banner]({{ site.baseurl }}/images/Ph0wn/Ph0wnBanner.png "Banner"){: .center-image }

Writeups' challenges

Rookie - Sunny day

The weather is always nice on the French Riveria. Yet, it is great to monitor this (sunny) weather with a weather station. There is a weather station in Biot, and there is an Android app for it. But somebody told me that there could be a hidden treasure in its main layout

First we ran the new MobSF application and drag'n dropped the APK file into it : docker run -it --name mobsf -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest. After inspecting the source code we stumbled upon the following Java/Android at http://localhost:8000/ViewSource/?file=tux/android/biotmeteo/MainActivity.java&md5=1b6d26562ca11c2d0c13fae063c93cd9&type=apk indicating the flag was around.

{% highlight java %} this.j = (Button) findViewById(R.id.badWeatherBtn); this.j.setText("Flag is not far :)"); {% endhighlight %}

We extracted the biotmeteo.apk as a zip file and started looking for the flag pattern ph0wn{ recursively. We will find inside biotmeteo\res\layout\main.xml.

{% highlight java %} $ grep ph0 -r . --text curvesButtonInfoTemp((tux.android.biotmeteo.AutoResizeTextViewRainWind ph0wn{IsTheWeatherNiceT0night?} BaHutLdityULIOLpL {% endhighlight %}

Flag : ph0wn{IsTheWeatherNiceT0night?}

Hardware - Ant-Maker

To receive the signal, you have to fabricate a RHCP antenna at 868MHz. Use the 3D_ant file as a model to mount the antenna. Collect your PCBs and use some tools and a soldering iron. Once your are ready, register on list to test if your prototype can receive the signal. 3 teams will make the test each 30mn. The Master of the Chamber, Fabien, will guide you to the anechoic room.

We were given two PCB and an antenna, in order to get the flag we had to solder them the right way. To help us the organizers provided each team with this file : [Ph0wn-3D_ant.step]({{ site.baseurl }}/files/Ph0wn-3D_ant.step).

It's a step file containing a 3D vizualization of the final PCB. From there we knew what to solder and where, we loaded it into https://3d-viewers.com/step-viewer.html.

![Ph0wn3Dant.png]({{ site.baseurl }}/images/Ph0wn/Ph0wn3Dant.png "3D Step file"){: .center-image }

The challenge wasn't hard but takes a lot of time and thorough effort to create a "working" antenna.

Flag : ph{LoRa_From_Space}

Misc - Compromised Sensor

I swear I saw a masked attacker come with a big syringe and a huge needle infect those glucose sensors for diabetics. What did he inject in those NFC sensors?!

  • Come and get a sensor at the organizer desk (see the attached image to recognize the device you need to get)
  • Nota. Due to a server crash, if you see an IP address, modify with 35.241.137.50 (no DoS)

Since the NFC is used by the sensor, let's check it with our proxmark3. With these data in mind we can find more informations about the sensor, it seems to be a FreeStyle Libre sensors.

{% highlight powershell %} [usb] pm3 --> hf search

UID : E0 07 A0 00 02 A6 99 C0
TYPE : Texas Instrument France

[+] Valid ISO15693 tag found {% endhighlight %}

On a StackOverflow post we find this goldmine :

Instead, you will have to find out what commands the blood sugar meter actually supports (probably it will support the ISO/IEC 15693 READ SINGLE BLOCK command

Now we know there is dump equivalent for NFC-V (ISO 15693), let's try it with the proxmark.

{% highlight powershell %} [usb] pm3 --> hf 15 dump f mydump
Reading memory from tag UID E0 07 A0 00 02 A6 99 C0
................................................... 45/0x2D | C2 43 08 08 | 0 | .C..
46/0x2E | 08 08 D2 42 | 0 | ...B
47/0x2F | D2 42 A3 F9 | 0 | .B..
48/0x30 | 4D 65 64 69 | 0 | Medi
49/0x31 | 4C 61 62 3A | 0 | Lab:
50/0x32 | 70 3A 2F 2F | 0 | p://
51/0x33 | 31 30 2E 31 | 0 | 10.1
52/0x34 | 3A 32 31 33 | 0 | :213
53/0x35 | 64 3A 70 69 | 0 | d:pi
54/0x36 | 77 64 3A 31 | 0 | wd:1
55/0x37 | 34 30 31 20 | 0 | 401
56/0x38 | E2 B3 C3 1C | 0 | ....
{% endhighlight %}

Some data are cropped, we tried several applications on our Android device. NFC TagInfo by NXP was the right one, it allows us to scan the entire memory.

![Ph0wnNXP.jpg]({{ site.baseurl }}/images/Ph0wn/Ph0wnNXP.jpg "NXP"){: .center-image }

We get the following credential for the IP 10.210.17.66

{% highlight java %} id: pico pwd: 19990401 {% endhighlight %}

![Ph0wnMedical.png]({{ site.baseurl }}/images/Ph0wn/Ph0wnMedical.png "Medical"){: .center-image }

From there we can download a PDF file containing a mention to Examen réalisé par marquage de type “Ange Albertini” CCC2014 ou PoC||GTFO. Ange Albertini gave a talk Funky File Formats on NoLimitSecu, we guess there is another file hidden in the PDF, running binwalk in extract mode will gave us thezip/FLAG containing the flag.

{% highlight powershell %} $ binwalk lab-results.pdf -e

DECIMAL HEXADECIMAL DESCRIPTION

0 0x0 PDF document, version: "1.4" 71 0x47 Zlib compressed data, default compression 1852 0x73C JPEG image data, JFIF standard 1.01 7162 0x1BFA Zlib compressed data, default compression 7419 0x1CFB Zlib compressed data, default compression 13863 0x3627 Zlib compressed data, default compression 14457 0x3879 Zlib compressed data, default compression 29155 0x71E3 Zlib compressed data, default compression 30196 0x75F4 Zlib compressed data, default compression 39508 0x9A54 Zlib compressed data, default compression 41694 0xA2DE Zip archive data, at least v2.0 to extract, compressed size: 437, uncompressed size: 1244, name: thezip/blah 42200 0xA4D8 Zip archive data, at least v2.0 to extract, compressed size: 584, uncompressed size: 1487, name: thezip/FLAG

$ cat _lab-results.pdf.extracted/thezip/FLAG| grep -i Ph0 ph0wn{BeS@feAndTakeCare} {% endhighlight %}

Flag : ph0wn{BeS@feAndTakeCare}

Misc - Domotics

Pico le Croco would like to control the power consumption of equipment in his wine cellar and in his pool. For that, he has bought a nice power meter, EcoCompteur from Legrand.

Configuration:

  • In Setup / Hardware, a Ph0wn EcoCompteur hardware is already partly configured for you (along with weather sensors), but you need to fix the IP address to: http://10.210.17.34:20000.

  • Unfortunately, you may encounter a bug where you are unable to modify the existing hardware. In that case, delete it and create a new one. Also, the port 20000 must be specified in both the remote address and the port (other bug).

  • Then, among Devices, you might like to tag "Conso 1" and "Conso 2": Conso 1 is the wine cellar, Conso 2 is the pool.

A new docker instance is deployed for each team when they click on the challenge, this instance is binded to a random port of the server 10.210.17.34. Since there is no authentication to access the EcoCompteur we guessed we could access other contestants panel.

{% highlight powershell %} ... 10040/tcp open unknown syn-ack 10050/tcp open zabbix-agent syn-ack 10060/tcp open unknown syn-ack 10070/tcp open unknown syn-ack 10081/tcp open famdc syn-ack 10100/tcp open itap-ddtp syn-ack 10130/tcp open unknown syn-ack 10151/tcp open unknown syn-ack 10160/tcp open qb-db-server syn-ack 10170/tcp open unknown syn-ack 10181/tcp open unknown syn-ack 10191/tcp open unknown syn-ack 10201/tcp open rsms syn-ack 10220/tcp open unknown syn-ack 10260/tcp open axis-wimp-port syn-ack 10281/tcp open unknown syn-ack 10310/tcp open unknown syn-ack 10340/tcp open unknown syn-ack 10360/tcp open unknown syn-ack ... {% endhighlight %}

We downloaded the usage for both Conso 1 and Conso 2.

{% highlight powershell %} ╭─user@crashmanjaro ~/CTF/Ph0wn/Domotics ╰─$ cat usage-last-24-hoursA.csv | cut -d "," -f3 | tr "\n" "," "Power Usage",,103,47,54,99,32,32,97,48,48,32,46,103,49,110,99,48,110,46,49,50,49,47,49,58,102,119,47,32,48,48,50,104,58,102,47,110,99,116,48,102,48,99,99,99,99,99,99,99,99,99,99,116,48,32,

╭─user@crashmanjaro ~/CTF/Ph0wn/Domotics ╰─$ cat usage-last-24-hours.csv | cut -d "," -f3 | tr "\n" "," "Power Usage",,119,110,32,102,108,97,103,32,97,116,32,104,116,116,112,58,47,47,49,48,46,50,49,48,46,49,55,46,54,54,58,50,48,48,48,48,47,110,49,99,101,102,102,102,102,102,102,102,102,102,102,112,104,48,% {% endhighlight %}

We can clearly identify some ASCII char, let's display them using Javascript.

{% highlight javascript %}

console.log(String.fromCharCode(119,110,32,102,108,97,103,32,97,116,32,104,116,116,112,58,47,47,49,48,46,50,49,48,46,49,55,46,54,54,58,50,48,48,48,48,47,110,49,99,101,102,102,102,102,102,102,102,102,102,102,112,104,48)); "wn flag at http://10.210.17.66:20000/n1ceffffffffffph0" {% endhighlight %}

The URL was a little buggy, we grabbed the flag at http://10.210.17.34:20000/n1ceflag

Flag: ph0wn{h0w_about_using_a_candle_instead}

Crypto - Shamir Quest

Ph0wn is so coooool. We've implemented a Dragon Ball game for your Android smartphone, so you can play and relax. Oh?! Looks like there's a flag in there!

The Android application is running Cordova, basically all the code is in some Javascript file. Every Dragon ball of the game is mapped like this int(1-7) - long(...). Based on the challenge name we know we have a Shamir Shared Secret. We can recover it with the following python script.

{% highlight python %} #!/usr/bin/python2 from secretsharing import points_to_secret_int

shares = [(7, 86280222218758143060577039723423036819702949921689517334729056400620503262863),
(6, 64853486060730513615551322784573665580194031012367687584714706161521361565423),
(5, 33814200739788654257795508969553514400370233867365839951719667470054751133890),
(4, 31566639759828849253104354287777292258537243784043419234402145787553977170879),
(3, 54008062481679211386368408327065859783198766778147014402616411673289639152699),
(2, 84515091397950443810021067510975505753043639566495880186943378404018469002849),
(1, 16977966888023650463948528650004025823243132426593812430821649423473014227191)]

print(hex(points_to_secret_int(shares))[2:-1].decode('hex')) {% endhighlight %}

Flag : ph0wn{Sh4m1r_4nd_G0ku_P4rtyt1me}