Aggregator
在IoT设备中查找端口对应进程的四种方法
禅道开源版自动化安全审计
QQ后台读取历史记录?有点冤枉企鹅了!
局域网监控软件WFilter ICF 鸡肋0day RCE漏洞挖掘
0x00关于本文逛freebuf的时候看到了这篇文章,关于PDD员工发帖溯源联想到的相关技术与实现,其中提到了一个叫做wfilter的局域网监控软件。这个软件官网提供了下载链接,支持10天实用,于是我就下下来研究一番。
作为一个搞安全的人,我最感兴趣的是这个软件本身是否存在缺陷,毕竟这类用于监控的安全软件自身出现漏洞是最有戏剧性的事情了
0x01不同寻常Web管理Wfilter通过串联/旁路的方式进行部署,同时提供一个Web管理接口供管理员进行远程管理。而作为一个Web狗,我自然把重心放在了这个Web管理接口上了。这个Web管理接口不同寻常的第一点就是登录之后不会返回任何Cookies,而且请求接口的时候也不会带Cookies或者任何特殊的Headers
那它是怎么进行鉴别的呢?测试了一番之后发现居然是根据IP地址来鉴别的,一旦管理者登录,wfilter就会记录下管理者的IP地址,然后允许其访问这些接口。这么诡异的鉴别方式大概率搭配了一个诡异的后端实现,结果我用火绒剑一看,发现后台是通过CGI运行的。也就是说想要审计这个软件还得去逆向这个EXE!算了,逆向就逆向吧,正好试试IDA7.5效果怎么样
0x01对于cgiproj.exe的逆向分析
这个Web接口的特点是通过/fcgi?cmd=【功能名】来调用,因此在IDA里面搜索相关的字符串就可以找到实现通过功能名来执行不同功能的函数了。
这个函数非常的大,以至于我需要修改IDA的hexrays支持的最大函数大小来让IDA能够成功反编译这个函数(Web狗实在是不想啃汇编了)。经过一番猜测和实验,我发现这个调用sub_BF65E0中的参数包含了功能名字,而v266[1]中存放的则是其对应的函数。通过这些信息我可以查看具体接口是如何实现。
0x02 思路1:找到无需鉴权的功能,直接拿下服务器!实现这个思路,简单来说就两个步骤,第一个是找到无需鉴权的功能,第二个是逆向分析然后找到有漏洞功能然后利用。为了找到无需鉴权就能使用的功能,简单起见,我搜集了那个大函数中的所有的字符串,然后拿到接口中去fuzz,接着发现viewHelp,helpSearch,login,mobileCode,mlogin,logout,remoteLogin,viewToolTip,ExecuteNoLogin,forgetPassword,resetPassword,viewHTML这些功能对应的接口无需登录。但是很快发现他们都无助于入侵。比如mobileCode功能虽然调用了system()但是所有的参数都是写死的,要么写死在程序里面,要么从配置文件里面读取
而viewHTML功能虽然可以玩路径穿越读取文件,但是后缀写死了htm,我尝试了00截断和Windows路径长度截断来绕过但是均未成功ExecuteNoLogin功能看名字很诱人,看样子似乎还可以直接给一个IP让它信任,但是我无论如何调用都显示错误,也没法直接RCE了
而其余的功能更是没法利用,因此目前看下来这条路就堵死了。
0x02 思路2:利用XSS/CSRF配合后台RCE ---XSS挖掘实现一键日天看起来是不现实了,但是XSS/CSRF配合后台RCE并不是没有可能的。首先我需要找一个靠谱的XSS漏洞。很快我就发现一个似乎可以利用的点,在“网页浏览”记录查看中,一旦请求带了User Agent,系统就会把User Agent放在前端
为了验证我这个猜测,我在安装了wfilter的机器上再装了个python requests库,以便于调试(简单起见,我并没有用串联/并联的方式将其接入我的网络),接着利用requests库构造一个包含XSS Payload的User-Agent,就像这样
接着再去看历史
0x03 思路2:利用XSS/CSRF配合后台RCE ---后台RCE挖掘
最开始我想的是直接搜system函数,查看引用,寻觅一波命令注入,但是并没有明显容易注入的点(主要是因为反编译出来的函数太大,而且一些不太清晰的反编译让我无法理清逻辑)。因此我采取另一种办法,即查看web界面有哪些有趣的功能,然后针对性地反编译。在翻找了一阵子后,我发现了这个系统包含了利用插件扩展的功能。
执行插件的时候抓个包,我发现了一个叫做runDll的功能,这不明显的让我为所欲为?
到IDA上一看,发现这个runDll的逻辑是根据接收到的dll参数加载dll
接着再去获取的proc参数作为函数名,通过GetProcAddress获取函数地址。最后再去把获取的para参数和另一个不知道干什么的v36传入到刚刚获取的函数中分析透了这个runDll之后,我们可以发现这里有执行shell的可能性。首先这个dll参数并没有任何过滤,这意味着我们可以穿越到任意目录中去调用任意位置的DLL,因此Windows的各种API我们都可以想办法去调用了。接着我需要找一个API函数,它接收两个参数,第一个参数是命令,第二个参数随便什么都可以,尽管看起来要满足这个条件相当的苛刻,但是真的有一个函数可以做到,那就是WinExec
而根据微软的描述,这个函数在Kernel32.dll中
于是构造如下Payload打过去
函数成功执行,但是并没有弹出计算器,不过这个执行的过程已经被火绒剑记录了下来,这证明我们成功地执行了shell
至此,整个利用链已经清晰了,就是通过XSS让管理员执行恶意JS,从而触发一个CSRF过去让服务器执行shell
0x04 完整的利用过程展示
首先用CS生成一个powershell的payload,这样就可以做到一执行命令就弹shell,接着编写CSRFPayload,用我写的CSRF 原理 利用 防御就可以了。
由于samesite Cookies机制,现在用POST来发CSRF包会导致Cookies不会发过去,但是现在是用IP来认证的,和Cookies无关,所以用POST来发是完全没问题的
接着用requests去插入一个带有XSS的访问记录,这个Payload的功能是去引入攻击机上面的JS来执行
再去访问历史记录查询页面,发现CS Shell弹回来了!,攻击成功!
在复现的时候发现有点坑,对于已经访问过的网站Wfilter似乎不是那么愿意再记录一次,并且有时候记录不下来,不知道原因是什么,猜测是软件自带的bug
0x04 结语这次就懒得写EXP出来了,毕竟这个漏洞用起来应该还是相对鸡肋的,写出来也没有什么用处。这个漏洞首先要求攻击者需要能让自己的流量被记录下来(所以需要能够进入内网中),而且还要管理员点击了历史记录查询页面才会触发,而且XSS Payload的引入过程还并不是那么的稳定因为有的时候还插入不了。因此想要成功利用这个漏洞进行攻击,需要天时(XSS 能够插入)地利(进入了内网)人和(管理员去查看历史访问记录)的配合,这个条件是相当苛刻的,在实战中也不太可能真正使用这么不稳定的攻击。不过逆向这么一个cgi程序还是挺有意思的,玩玩IDA陶冶身心也不错,权当是一次小练习吧
Using Direct Syscalls in Cobalt Strike's Artifact Kit
十分钟教会你MIPS编程入门
可以实现隐蔽持久性的Outlook后门
Newer Cryptographic Advances for the Domain Name System: NSEC5 and Tokenized Queries
This is the third in a multi-part blog series on cryptography and the Domain Name System (DNS). In my last post, I looked at what happens when a DNS query renders a “negative” response – i.e., when a domain name doesn’t exist. I then examined two cryptographic approaches to handling negative responses: NSEC and NSEC3. […]
The post Newer Cryptographic Advances for the Domain Name System: NSEC5 and Tokenized Queries appeared first on Verisign Blog.
XNU内核堆安全特性解读
Cryptographic Tools for Non-Existence in the Domain Name System: NSEC and NSEC3
This is the second in a multi-part blog series on cryptography and the Domain Name System (DNS). In my previous post, I described the first broad scale deployment of cryptography in the DNS, known as the Domain Name System Security Extensions (DNSSEC). I described how a name server can enable a requester to validate the […]
The post Cryptographic Tools for Non-Existence in the Domain Name System: NSEC and NSEC3 appeared first on Verisign Blog.
深度探索:解除文件占用那些坑
Can Bots Manipulate Data and Change Facts to Fiction?
Top Security Threats to Look Out for in 2021
Top Cyber Security Threats to Look Out for in 2021 2020 was unexpectedly defined by a global pandemic. Throughout the...
The post Top Security Threats to Look Out for in 2021 appeared first on McAfee Blog.
Security Update Guide Supports CVEs Assigned by Industry Partners
Security Update Guide Supports CVEs Assigned by Industry Partners
Internalship Program
The Story Of CVE-2021-1648
Author: k0shl of 360 Vulcan Team
SummaryIn January 2021 patch tuesday, MSRC patched a vulnerability in splwow64 service, assigned to CVE-2021-1648(also known as CVE-2020-17008), which merged my two interesting cases which bypass the patch of CVE-2020-0986, one of them also be found by Google Project Zero((https://bugs.chromium.org/p/project-zero/issues/detail?id=2096).actually this include one EoP and two info leak cases.
This vulnerability was planned to patch in October 2020, but MSRC seems found some other serious security problems in service, so they postpone the patch for four months.
BackgroundIn this blog, I don't want to talk more about the mechanism of splwow64, there are a lot of analysis of CVE-2020-0986 before, so let's focus on the vulnerability.
After CVE-2020-0986 had been patched, I make a quick bindiff on splwow64 and gdi32full, and found there are two check added after patch.
One is that Microsoft added two printer handle(or aka cookie?) check functions named "FindDriverForCookie" and "FindPrinterHandle", it will check printer driver handle which store in a global variable.
__int64 __fastcall FindDriverForCookie(__int64 a1) { v3 = qword_1800EABA0; if ( qword_1800EABA0 ) { do { if ( a1 == *(_QWORD *)(v3 + 56) ) //check driver index break; v3 = *(_QWORD *)(v3 + 8); } while ( v3 ); if ( v3 ) ++*(_DWORD *)(v3 + 44); } RtlLeaveCriticalSection(&semUMPD); return v3;// return driver heap } __int64 *__fastcall FindPrinterHandle(__int64 a1, int a2, int a3) { for ( i = *(__int64 **)(v3 + 64); i && (*((_DWORD *)i + 2) != v5 || *((_DWORD *)i + 3) != v4); i = (__int64 *)*i ) //check printer handle ; }Another is that MSRC added two pointer check functions "UMPDStringPointerFromOffset" and "UMPDPointerFromOffset" to check if pointer is validate.
FindDriverForCookie and FindPrinterHandle bypassFirst, I don't know the purpose that Microsoft add FindDriverForCookie and FindPrinterHandle, maybe it's not for mitigation? After quick review, I found there is a command named 0x6A that can set printer handle which the value we can controll in global variable of service to bypass this two check functions.
__int64 __fastcall bAddPrinterHandle(__int64 a1, int a2, int a3, __int64 a4) { v9 = RtlAllocateHeap(*(_QWORD *)(__readgsqword(0x60u) + 48), 0i64, 24i64); v10 = (_QWORD *)v9; if ( v9 ) { *(_DWORD *)(v9 + 8) = v6; *(_DWORD *)(v9 + 12) = v5; *(_QWORD *)(v9 + 16) = v8; RtlEnterCriticalSection(&semUMPD); *v10 = *(_QWORD *)(v4 + 0x40); v7 = 1; *(_QWORD *)(v4 + 0x40) = v10; //add print handle which can be controlled by user RtlLeaveCriticalSection(&semUMPD); } return v7; }By invoking command 0x6A, function bAddPrinterHandle will add print handle to driver heap which stored in global variable |qword_1800EABA0|.
//set print handle to 0xdeadbeef00006666 0:007> p gdi32full!bAddPrinterHandle+0x54: 00007ff8`380fc3bc 44897808 mov dword ptr [rax+8],r15d ds:00000000`0108a428=00000000 0:007> p gdi32full!bAddPrinterHandle+0x58: 00007ff8`380fc3c0 4489700c mov dword ptr [rax+0Ch],r14d ds:00000000`0108a42c=00000000 0:007> r r14d r14d=deadbeef 0:007> r r15d r15d=6666 //driver heap stored in global variable 0:007> dq gdi32full+0xEABA0 l1 00007ff8`381baba0 00000000`0108d000 0:007> dq 108d000+0x40 l1 00000000`0108d040 00000000`0108a420 0:007> dq 108a420+0x8 l1 00000000`0108a428 deadbeef`00006666So we can easy bypass printer handle check during invoking Command 0x6D, and hit the vulnerability code.
case 0x6Du: v31 = FindDriverForCookie(*(_QWORD *)(v6 + 24)); v32 = v31; if ( !v31 ) goto LABEL_137; v33 = FindPrinterHandle(v31, *(_DWORD *)(v6 + 32), *(_DWORD *)(v6 + 36)); ... [vulnerability code] CVE-2021-1648: arbitrary address readLet's talk about information disclosure, CVE-2020-1648 includes a arbitrary address read information disclosure.
if ( v51 != -1 ) { v57 = **(unsigned __int16 ***)(v6 + 0x50); //not check v57 if ( v57 ) { v58 = v57[34]; v59 = v58 + v57[35]; if ( (unsigned int)v59 >= v58 && (unsigned int)v59 <= 0x1FFFE ) memcpy_0(*(void **)(v6 + 88), v57, v59); //arbitrary address read } }The code of case Command 0x6D is too long, so I won't post all of them in my blog. In short, it will check destination address of memcpy if it's in "validate" range, the range of |v6+0x58|, but source address |v57| isn't checked, so we can read arbitrary address.
0:007> r rax=0000000000868a00 rbx=000000000001fffe rcx=0000000000000000 rdx=4141414141414141 rsi=0000000000150200 rdi=00000000008688d0 rip=00007ff9fc008403 rsp=000000000210f480 rbp=000000000210f4f9 r8=100297f000000002 r9=000000000022f000 r10=00000fff3c9c801d r11=000000000210f350 r12=0000000000868920 r13=0000000000868910 r14=0000000000000001 r15=0000000000461c50 iopl=0 nv up ei pl nz na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206 gdi32full!GdiPrinterThunk+0x1a73: 00007ff9fc008403 0fb74a44 movzx ecx,word ptr [rdx+44h] ds:4141414141414185=????Stack trace:
0:007> k Child-SP RetAddr Call Site 000000000210f480 00007ff7558e78ab gdi32full!GdiPrinterThunk+0x1a73 000000000210f560 00007ff7558e84de splwow64+0x78ab 000000000210f650 00007ff7558e9f28 splwow64+0x84de 000000000210f6b0 00007ff9fe3f2e93 splwow64+0x9f28 000000000210f6e0 00007ff9fe3f45b4 ntdll!RtlDeleteCriticalSection+0x363 000000000210f730 00007ff9fc487bd4 ntdll!RtlInitializeResource+0xce4 000000000210faf0 00007ff9fe42ce51 KERNEL32!BaseThreadInitThunk+0x14 000000000210fb20 0000000000000000 ntdll!RtlUserThreadStart+0x21 Another two cases of CVE-2021-1648Another two cases I reported to MSRC is about bypassing offset check functions "UMPDStringPointerFromOffset" and "UMPDPointerFromOffset", I think MSRC made a mistake in these two functions range check.
Splwow64 is a specail service which is compatible with x86 in x86-64 Windows OS, so it always allocate heap which is 32bits, but in CVE-2020-0986 patch, "UMPDStringPointerFromOffset" and "UMPDPointerFromOffset" only check if offset and |portview+offset| is less than 0x7fffffff.
signed __int64 __fastcall UMPDPointerFromOffset(unsigned __int64 *a1, __int64 a2, unsigned int a3) { [...] if ( v3 <= 0x7FFFFFFF && v3 + a3 <= 0x7FFFFFFF ) { *a1 = v3 + a2; return 1i64; } [...] } signed __int64 __fastcall UMPDStringPointerFromOffset(unsigned __int64 *a1, __int64 a2) { [...] if ( v3 > 0x7FFFFFFF ) goto LABEL_12; v4 = (0x7FFFFFFF - v3) >> 1; *a1 = v3 + a2; v5 = (unsigned int)v4; if ( v3 + a2 ) v2 = wcsnlen((const wchar_t *)(v3 + a2), (unsigned int)v4); [...] return result; }But in splwow64 service, so many heaps even stack is allocated in low address, like this:
0:004> pc splwow64!TLPCMgr::ProcessRequest+0x99: 00007ff6`846d7c71 e826490000 call splwow64!operator new[] (00007ff6`846dc59c) 0:004> p splwow64!TLPCMgr::ProcessRequest+0x9e: 00007ff6`846d7c76 488bf0 mov rsi,rax 0:004> r rax rax=00000000007d7c70 0:004> r rsp rsp=000000000217f400So it is possible to exploit through occupy to some important heaps or stack in splwow64 service, I suggest MSRC in my report to check range of pointer if it's in portview section instead of 0x7fffffff.
two cases crash dump:
0:006> r rax=0000000000000000 rbx=00000000012f8360 rcx=000000001363d9e0 rdx=00000000012f8360 rsi=0000000002d60200 rdi=000000001363d9d8 rip=00007fff728956d2 rsp=0000000002cdf230 rbp=0000000000000001 r8=0000000000000028 r9=0000000012345678 r10=000000007fffffff r11=2222222222222222 r12=00007fff57ea8fe0 r13=0000000001208210 r14=000000000120aa50 r15=00007fff72860000 iopl=0 nv up ei pl nz na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206 gdi32full!UMPDStringPointerFromOffset+0x12: 00007fff728956d2 4c8b09 mov r9,qword ptr [rcx] ds:000000001363d9e0=???????????????? 0:006> r rax=0000000000000001 rbx=0000000001628360 rcx=0000000042a3c4a1 rdx=0000000001628360 rsi=0000000000ff0200 rdi=0000000000000000 rip=00007fff7289568a rsp=0000000002ecf3d8 rbp=0000000000000001 r8=0000000000000028 r9=0000000041414141 r10=000000007fffffff r11=2222222222222222 r12=00007fff57ea8fe0 r13=0000000001407160 r14=000000000140a000 r15=00007fff72860000 iopl=0 nv up ei pl nz na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206 gdi32full!UMPDPointerFromOffset+0xa: 00007fff7289568a 4c8b09 mov r9,qword ptr [rcx] ds:0000000042a3c4a1=???????????????? The end of storyIt seems Microsoft redsigned splwow64 printer service, so they postponed the patch for four months, it's really a long time for me to wait a patch since I started my researching on Windows. Hope new printer service will be more secure:P.
Timeline
2020-07-27 Reported to MSRC.
2020-08-19 MSRC decided to put off patch.
2020-08-22 Bounty awarded
2021-01-13 Patch release