SockPuppet学习记录(一) : 漏洞分析
Basic
这个漏洞是由pj0的 nedwill
发现的,而且是一个品相极佳的可以用于越狱的漏洞,本文只是对漏洞进行分析,并且思考/尝试使用CodeQL对该类型漏洞覆盖。当然,在看了原作者的文章之后,才发现nedwill是利用Fuzzing的手段发现的这个漏洞,并且在挖掘读/写原语的时候也是借助了Fuzzing的手段,可以说十分的巧妙和高效了。
系统版本:10.14.3
xnu代码:
poc
raw poc
在测试原始PoC获得的Crash信息如下:
原始PoC使用了raw socket
触发,但是美中不足,这个方式必须要root权限才能触发。
(定制化sockaddr_in6
需要raw socket
)
1 |
|
read
后续ned经过研究发现可以通过tcp socket方式触发,可以用于read free’d memroy:
1 |
|
write
经过nedwill的Fuzzing测试,发现了write free’d memory 的PoC:
1 | // |
bug analysis
根据漏洞描述,可以看到漏洞的 root cause如下:
1 | void |
漏洞路径 bsd/netinet6/in6_pcb.c
,协议族 AF_INET6
的处理函数,从函数名字来看是
断开连接时候会执行的一些操作(释放一些资源),但是释放之后忘记把指针置NULL,导致同一个套接字重连的时候又使用到了这个指针(悬垂指针)。
根据nedwill
的描述,连接断开再set/get socketopt
的场景可以触发。
进入函数之前有一个 socket so_flags
的检查,poc中的 setsockopt()
调用应该是为了能过进入漏洞逻辑设计的。
利用 socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
这个poc,逻辑应该是:
- 创建socket连接
- setsockopt,为了后续可以进入漏洞代码分支,同时设置要读的数据
- disconnectx 断开连接,触发 free 逻辑
- getsockopt,读取已经释放的内存
写的逻辑类似,不过作者是找到了另外特殊的成员来完成写操作: SONPX_SETOPTSHUT
这个洞的品相太好了 :-)
how to find by QL
xnu database
可以从semmle官方网站下载
Analyzing large open source projects
about this bug
看起来是:
1 | int demo(p){ |
释放了内存之后,没有对指针做置NULL处理。
- 需要在同一个函数里,同一个代码块里。
锁的问题考虑吗? - 释放逻辑,正则匹配下, xxxfree, freexxx, releasexxx之类的
query 1
根据上面的描述,我们找到free 调用,且free调用下一行是特定的赋值表达式的情况:
1 | import cpp |
这里有一个问题,我尝试过 free调用的参数作为赋值表达式的左值
这条约束,但是加上之后就找不到任何结果了,如果有人知道原因还请指点一下 : )
query 2
上面query可以找到 free后是set NULL的代码段,如果想找不满足条件的,可以检测free逻辑下一行是不是 instance of AssignExpr,当然这样比较粗糙,会存在误报。
1 | from FunctionCall call, Expr e |
这样写,虽然可以找到目标代码,但是存在误报(优化TODO):