CVE-2022-3602
具体内容
crypto/punycode.c
1 | int ossl_punycode_decode(const char *pEncoded, const size_t enc_len, |
1 | static int test_puny1(void) |
1 | static int test_puny2() |
1 | static int test_puny3(void) |
具体内容
crypto/punycode.c
1 | int ossl_punycode_decode(const char *pEncoded, const size_t enc_len, |
1 | static int test_puny1(void) |
1 | static int test_puny2() |
1 | static int test_puny3(void) |
首先介绍pcap文件格式
文件头,总共 24 个字节:
1 | struct pcap_file_header { |
magic:标识位:4 字节,这个标识位的值是 16 进制的 0xa1b2c3d4
major:主版本号:2 字节,默认值为 0x2
minor:副版本号:2 字节,默认值为 0x04
thiszone:区域时间:4 字节,实际上并未使用,因此被设置为 0
sigfigs:精确时间戳:4 字节,实际上并未使用,因此被设置为 0
snaplen:数据包最大长度:4 字节,该值设置所抓获的数据包的最大长度
linktype:链路层类型:4 字节,数据包的链路层包头决定了链路层的类型
数据包头,总共 16 个字节:
1 | struct pcap_pkthdr { |
查看包结构 xxd -g1 slip-bad-direction.pcap
1 | 00000000: d4 c3 b2 a1 02 00 04 00 00 00 00 00 00 00 00 00 ................ |
可见其链路层类型为 08,即 SLIP(Serial Line Internet Protocol) SLIP 的常见包结构如下:
1 | +-------------------------+ |
direction 字段指示发送或接收
在这里 direction 是 0xE7
漏洞程序代码
1 | static void |
gdb调试, 在sliplink_print 函数处下断点,并运行
1 | gdb ./tcpdump-tcpdump-4.9.0/tcpdump -q |
1 | Breakpoint 1, sliplink_print (length=0xe7e7e726, ip=0x61d000000090, p=0x61d000000080 '\347' <repeats 22 times>, <incomplete sequence \312>, ndo=0x7fffffffcff0) at ./print-sl.c:133 |
可见地址0x61d000000080存放着从pcap文件中读取出的39个Byte
1 | [ Legend: Modified register | Code | Heap | Stack | String ] |
语句 dir = p[SLX_DIR];
从 data 中取出第一个字节作为 dir,即 0xe7
然后程序将 dir==0xe7 与 SLIPDIR_IN==0 作比较,不相等,于是错误地把 dir 当成 SLIPDIR_OUT==1 处理
1 | [ Legend: Modified register | Code | Heap | Stack | String ] |
lastlen[dir][lastconn] = length - (hlen << 2);
访问不合法地址
1 | gef➤ c |
加了switch判断 不合法的输入将dir置为-1 , 后续代码遇到-1另外异常处理
1 | static void |
下载目标软件
1 | git clone https://github.com/zeromq/libzmq.git |
跳转到有漏洞的版本
1 | git reset --hard 7302b9b8d127be5aa1f1ccebb9d01df0800182f3 |
安装 libtool
1 | sudo apt-get install libtool pkg-config build-essential autoconf automake |
执行
1 | cd libzmq |
删去v2_decoder.hpp
中51行的private:
1 | class v2_decoder_t ZMQ_FINAL |
把fuzzer.cc放到当前文件夹下 编译
1 | clang++ -g -std=c++11 -fsanitize=address,fuzzer fuzzer.cc -I ./ .libs/libzmq.a -o fuzzer |
执行
1 | ./fuzzer |
漏洞原因:如果msg_size很大,溢出read_pos_指针范围,绕过检测 并且可以写入msg_size这么多数据
1 | //src/v2_decoder.cpp |
1 | // src/v2_decoder.cpp zmq::v2_decoder_t::size_ready() |
溢出块的后方紧接着,其中ffn为函数指针,参数为data和hint 可改写,执行任意函数
1 | 67 struct content_t |
1 | if (unlikely (!_zero_copy |
1 |
|
按照思路逆序构造
注意还要绕过过滤,system过不了 换成大写即可
1 |
|
1 | __construct //对象创建(new)时会自动调用。 |