lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date: Fri, 28 Mar 2014 09:00:27 +0100
From: Adam Zabrocki <pi3@....com.pl>
To: fulldisclosure@...lists.org
Subject: Re: [FD] Adventure with Stack Smashing Protector (SSP)

> Hi Adam,

Witaj Robert,

> Quite an interesting read! Thx for preparing it.

Thank you for appreciating my work!

> So it seems to me that revealing the VM layout or SSP cookies is important
> when we're attacking application which is operating with different set of
> privileges or having access to different resources than the attacker has.
> IMO it boils down to 2 basic cases
> 

Yes

> a). attacking a network/remote service
> b). attacking a local service which is operating with different set of
> privileges (a system service, a setuid binary)
>

Yes, but just to be clear, network/remote service may be "low" privilage
but (as you said) having access to different resource than attacker has
- it's quite important from the situation which you are describing below.
 
> Some of the presented ideas require ability to read output from
> stdout/stderr, what limits the attack to set-uid binaries (or, to other
> esoteric & and not-likely cases, like 644 stdout/stderr log files etc).

From the security perspecitve bugs, yes. Just want to exclude applications
sending errors to the socket - I believe it's not so esoteric... (subjective
opinion)

Of course we are not talking here about mmap() case and potential Resource
Exhaustion scenario :)

> When set-uid application is executed libc is more "cautious" about printing
> debug data, or accepting env-vars (like LIBC_FATAL_STDERR_).
> 

Yes, which can be seen from the listening in my paper. Bottom 5th page:

--- CUT ---
Let's look closer for the following line:

	const char *on_2 = __libc_secure_getenv ("LIBC_FATAL_STDERR_");

Which essentially executes:

	"stdlib/secure-getenv.c"
	char *
	__libc_secure_getenv (name)
	const char *name;
	{ 
		return __libc_enable_secure ? NULL : getenv (name);
	}
--- CUT ---

I've made (maybe too far-fetched) assumption reader knows "__libc_enable_secure"
is declared for SUID/SGID binaries. For my absolution I will quote glibc doc:

--- CUT ---
char * secure_getenv (const char *name)				 [Function]
Preliminary: | MT-Safe env | AS-Safe | AC-Safe | See Section 1.2.2.1 [POSIX
Safety Concepts], page 2.
This function is similar to getenv, but it returns a null pointer if the
environment is untrusted. This happens when the program file has SUID or SGID
bits set. Generalpurpose libraries should always prefer this function over
getenv to avoid vulnerabilities if the library is referenced from a SUID/SGID
program.
This function is a GNU extension.
--- CUT ---


Thanks for paying special attention when reading my work!


> So my point would be that some of those conditions required for successful
> exploitation seem mutually-exclusive, e.g. you can try to attack/crash an
> app with LIBC_FATAL_STDERR_, but it's ignored for set-uid apps, and I'm not
> sure I'm seeing any other attack vector on privileged apps, unless I'm
> missing sth.
> 

At this point we need to return to the beginning of your mail where you
summarized possible victims to 2 basic cases.

> a). attacking a network/remote service

From my understanding - no. That's why I want to be clear network/remote service
may be "low" privilage and still be a desired resources. What do you think? Do
you agree with me?


> b). attacking a local service which is operating with different set of
> privileges (a system service, a setuid binary)
>

Yes and no. SUID/SGID binaries by default print output to the attacker's terminal
and there is no need to play with LIBC_FATAL_STDERR_.

Some quick test:

--- CUT ---
*root terminal*

[root@...alhost ~]# echo 2 > /proc/sys/fs/suid_dumpable # needed for generating SUID/SGID crashdumps
[root@...alhost ~]# cat /proc/sys/fs/suid_dumpable
2
[root@...alhost ~]# cp /home/pi3/test /      # I'll use the same binary from write-up
[root@...alhost ~]# chown root.root /test
[root@...alhost ~]# chmod +s /test
[root@...alhost ~]# ls -al /test
-rwsr-sr-x. 1 root root 8666 Feb 17 00:40 /test


*default user terminal*

[pi3@...alhost ~]$ /test `perl -e 'print "A"x110'`
DONE!
*** stack smashing detected ***: /test terminated
======= Backtrace: =========
/lib64/libc.so.6(__fortify_fail+0x37)[0x3afb30d657]
/lib64/libc.so.6(__fortify_fail+0x0)[0x3afb30d620]
/test[0x4006b1]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x3afb221b45]
/test[0x400569]
======= Memory map: ========
00400000-00401000 r-xp 00000000 fd:01 16                                 /test
00600000-00601000 r--p 00000000 fd:01 16                                 /test
00601000-00602000 rw-p 00001000 fd:01 16                                 /test
00b37000-00b58000 rw-p 00000000 00:00 0                                  [heap]
3afae00000-3afae21000 r-xp 00000000 fd:01 1060070                        /usr/lib64/ld-2.17.so
3afb020000-3afb021000 r--p 00020000 fd:01 1060070                        /usr/lib64/ld-2.17.so
3afb021000-3afb022000 rw-p 00021000 fd:01 1060070                        /usr/lib64/ld-2.17.so
3afb022000-3afb023000 rw-p 00000000 00:00 0
3afb200000-3afb3b6000 r-xp 00000000 fd:01 1060071                        /usr/lib64/libc-2.17.so
3afb3b6000-3afb5b6000 ---p 001b6000 fd:01 1060071                        /usr/lib64/libc-2.17.so
3afb5b6000-3afb5ba000 r--p 001b6000 fd:01 1060071                        /usr/lib64/libc-2.17.so
3afb5ba000-3afb5bc000 rw-p 001ba000 fd:01 1060071                        /usr/lib64/libc-2.17.so
3afb5bc000-3afb5c1000 rw-p 00000000 00:00 0
3afda00000-3afda15000 r-xp 00000000 fd:01 1062155                        /usr/lib64/libgcc_s-4.8.1-20130603.so.1
3afda15000-3afdc14000 ---p 00015000 fd:01 1062155                        /usr/lib64/libgcc_s-4.8.1-20130603.so.1
3afdc14000-3afdc15000 r--p 00014000 fd:01 1062155                        /usr/lib64/libgcc_s-4.8.1-20130603.so.1
3afdc15000-3afdc16000 rw-p 00015000 fd:01 1062155                        /usr/lib64/libgcc_s-4.8.1-20130603.so.1
7f1a072df000-7f1a072e2000 rw-p 00000000 00:00 0
7f1a072f4000-7f1a072f7000 rw-p 00000000 00:00 0
7fff8e8ea000-7fff8e90b000 rw-p 00000000 00:00 0                          [stack]
7fff8e93e000-7fff8e940000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted (core dumped)
[pi3@...alhost ~]$ /test `perl -e 'print "A"x1000'`
DONE!
Segmentation fault (core dumped)
[pi3@...alhost ~]$ gdb -q /test core.30164
Reading symbols from /test...(no debugging symbols found)...done.
[New LWP 30164]

warning: the debug information found in "/usr/lib/debug//lib64/libc-2.17.so.debug" does not match "/lib64/libc.so.6"
(CRC mismatch).


warning: the debug information found in "/usr/lib/debug//lib64/ld-2.17.so.debug" does not match
"/lib64/ld-linux-x86-64.so.2" (CRC mismatch).

Core was generated by `/test AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
Program terminated with signal 11, Segmentation fault.
#0  0x0000003afb2866e1 in __strlen_sse2 () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-20.fc19.x86_64
(gdb) x/i $rip
=> 0x3afb2866e1 <__strlen_sse2+17>:     movdqu (%rdi),%xmm1
(gdb) i r rdi
rdi            0x4141414141414141       4702111234474983745
(gdb) bt
#0  0x0000003afb2866e1 in __strlen_sse2 () from /lib64/libc.so.6
#1  0x0000003afb275b6a in __libc_message () from /lib64/libc.so.6
#2  0x0000003afb30d657 in __fortify_fail () from /lib64/libc.so.6
#3  0x0000003afb30d620 in __stack_chk_fail () from /lib64/libc.so.6
#4  0x00000000004006b1 in main ()
(gdb)
--- CUT ---

For "normal" SSP execution output is exactly the same. What is important for us if program's name
are still in the output (which means reference the "argv[0]"). Internally execution is slightly
different, like you mentioned, "secure_getenv()" always return NULL (LIBC_FATAL_STDERR_ code path not executed).

In second case, pointer was overwritten and SSP crashed in the "strlen()" function on referencing "argv[0]".
Essentially leaking "secrets" from the program are still possible (passwords? keys? strings? bytes?)


For local services I think you are right :)


> Just wondering about your thoughts on that.
> 

I don't know if my answers are satisfactory to you. Do they?

Btw. Thanks for concerns! This paper is long and I'm very happy someone read it and was paying
special attention and discover interesting corner cases. I'm really happy! :)


Ps. Mozemy przeniesc dalsza dyskusje na prywatne maile jesli Ci to nie przeszkadza :)
    Jesli jednak wolisz tu, bylbym wdzieczny jakbys dodal moj mail do CC przy odpowiedzi,
    poniewaz wylaczylem opcje dostarczania kazdego posta z fd na moja skrzynke co utrudnia
    odpowiadanie na watek ;/


> -- 
> Robert Święcki


Best regards,
Adam

-- 
pi3 (pi3ki31ny) - pi3 (at) itsec pl
http://pi3.com.pl

_______________________________________________
Sent through the Full Disclosure mailing list
http://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: http://seclists.org/fulldisclosure/

Powered by blists - more mailing lists