Aggregator
In Conversation: New Starters
网安独角兽CrowdStrike IPO分析(一)
路由器漏洞挖掘之 DIR-850/645 命令执行漏洞复现 - H4lo
路由器漏洞挖掘之 DIR-815 栈溢出漏洞分析 - H4lo
震惊!MSSQL眼里的00字符居然是这个亚子,sqlchop,安全狗,奇安信WAF被绕过
blogspot似乎有bug,我无法打出%+00,所以后文的00字符都用【00字符】代替
0x01Payload
id=1【00字符】union【00字符】all【00字符】select【00字符】null,@@version,null 为了防止这些厂商不认账,特地贴出bypass的图
他们又不是3█0怎么会这么做嘛
由于懒癌发作就截一张图
更新:发现奇█信的也能bypass,鉴于奇█信原来也是3█0的,故特此补图.由于他们非常无耻地直接拦截关键字@@version故select一些不关键的元素代替,但是只要细心构造也是能找到完全绕过的办法的.
0x02 为什么能Bypass? 似乎mssql会把【00字符】当作空格于是导致bypass,真的神奇了
由于这个特性之前好像没人提,fuzz的时候都是从%01开始的,这个新发现的特性估计可以通杀一波WAF了?
突然感觉放出来好亏
Microsoft Hardlink缓解机制简单分析
Author: k0shl of 360 Vulcan Team
简述微软在Insider Preview引入了一个新的缓解机制来阻止普通用户创建硬链接(CreateHardlink),在逻辑漏洞的利用中,hardlink是一个非常实用且便捷的方法,当一个高完整性级别进程对低权限文件操作的时候(这里所谓低权限泛指normal user或更低权限用户可以完全控制的文件),可以利用hardlink将低权限文件链接到高权限文件(高权限是指需高权限例如SYSTEM操作的文件,比如C:\Windows目录下的绝大多数文件及子目录文件),从而会使高权限进程处理高权限文件(比如改变DACL,写入,创建等)这里简述一下利用hardlink的逻辑漏洞利用方法。
关于应用到hardlink技巧的漏洞可以参考Project Zero的James Forshaw的历史漏洞,他提交的逻辑类型漏洞中很多都应用到了hardlink的利用方法。
PS: 文中的代码示例均来自Insider preview(build 18898.1000),除了部分源码展示出处有单独说明。
Hardlink review关于hardlink的创建可以参考James Forshaw的项目symboliclink-testing-tools (https://github.com/googleprojectzero/symboliclink-testing-tools),通过调用NtSetInformationFile设置文件的FileLinkInformation的属性将指定文件链接到目标文件上。
当然,符号链接曾经也是用来sandbox escape的有效手段,在AppContainter(或者低完整性级别进程中,例如Low Integrity)中,许多权限操作需要通过medium integrity进程来帮忙完成,这样可以通过一个AC可以操作的目录文件,硬链接到高权限文件,再利用Medium integrity进程来完成对高权限文件的操作,但微软加入了针对这种方法的Mitigation,如果是在AppContainer中调用NtSetInformationFile,会调用RtlIsSandboxToken检查进程Token,若在沙盒中,则设置需求的访问权限。其实现在ntoskrnl!NtSetInformationFile函数中:
if ( a5 == 0xB || a5 == 0x48 )// 0xB和0x48都是FileLinkInformation { memset(&Dst, 0, 0x20ui64); SeCaptureSubjectContextEx(v6, *(_QWORD *)(v6 + 544), &Dst); v65 = RtlIsSandboxedToken(&Dst, v7);//检查沙盒Token SeReleaseSubjectContext(&Dst); if ( v65 ) v14 |= 0x100u;//设置需求的访问权限,必须要有写权限 }0xB和0x48是FileLinkInformation的enumerate,它最终会调用ntfs.sys中NtSetLinkInfo设置指定文件的硬链接到目标链接,其代码在ntfs!NtfsCommonSetInformation函数中实现
case 0xB: case 0x48: v47 = v11; v34 = NtfsSetLinkInfo(v4, v73, v10, v9, v47);ntfs.sys是Windows的文件系统驱动,其调用方法是在ntoskrnl的NT API中调用IofCallDriver,通过调用DriverObject的MajorFunction发送IRP封装,进入Ntfs!NtfsFsdSetInformation函数。
这里微软通过RtlIsSandboxedToken的方法阻止了AC调用硬链接,同样注册表和文件的符号链接,等方法也是通过类似方法缓解。
关于这次Insider Preview之前微软通常会通过两种方法来修补这类逻辑漏洞,第一种是模拟客户端,通过调用RpcImpersonateClient来模拟客户端Token,也就是说在接下来的上下文中,进程将以Client的权限执行代码,最后通过RpcRevertToSelf恢复原进程权限。第二种是通过调用GetFileInformationByHandle获取文件的属性,在GetFileInformationByHandle参数中有一个数据结构。
typedef struct _BY_HANDLE_FILE_INFORMATION { DWORD dwFileAttributes; FILETIME ftCreationTime; FILETIME ftLastAccessTime; FILETIME ftLastWriteTime; DWORD dwVolumeSerialNumber; DWORD nFileSizeHigh; DWORD nFileSizeLow; DWORD nNumberOfLinks; DWORD nFileIndexHigh; DWORD nFileIndexLow; } BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION, *LPBY_HANDLE_FILE_INFORMATION;其中nNumberOfLinks会获取文件符号链接的数量,如果大于1则证明当前文件存在符号链接,则阻止后续操作进行。
关于修补漏洞的方法这里不做过多讨论,读者可以通过对补丁的对比找到微软修补此类漏洞的方法。
Hardlink Mitigation在Insider Preview(build 18898.1000)中(可能更早),微软引入了针对hardlink的缓解措施,阻止普通用户创建高权限文件的硬链接,其主要思路是检查FileObject中ContextControlBlock的Flags,若其Flags不满足要求(RequirAccess),则最终调用SeAccessCheck检查进程对硬链接目标的真实访问权限,从而阻止普通用户创建高权限文件硬链接。
其主要代码在ntfs!NtfsSetLinkInfo中
if ( !(*(_WORD *)(a5 + 0x68) & 0x310) ) // mitigation { …… if ( !(unsigned __int8)TxfAccessCheck( v6, v90, *(_QWORD *)(v5 + 168), *(_QWORD *)(v6 + 200), 0, 0, 0x100u, 0, 0i64, v91, v99, (__int64)&v156, 0i64, &v157, 0i64) ) { v24 = 0xC0000022;//Access Denied if ( !NtfsStatusDebugFlags ) return (unsigned int)v24; v84 = 995043i64; goto LABEL_200; }TxfAccessCheck函数会调用SeAccessCheckEx检查进程的访问权限(写入,修改,删除等),若权限不满足,则返回0xC0000022拒绝访问。
我们需要回溯到外层函数调用NtfsCommonSetInformation来追踪a5+0x68的值,a5的值来自NtfsSetLinkInfo函数的第五个参数,关于回溯过程这里我不再赘述,a5的值来自于IRP封装的CurrentStackLocation,NtfsCommonSetInformation的第一个参数是一个IRP结构的参数,我简化了NtfsCommonSetInformation的代码,来看一下参数的传递过程。
signed __int64 __usercall NtfsCommonSetInformation@<rax>(_IRP *a1@<rdx>, __int64 a2@<rcx>, signed __int64 a3@<r15>) { v6 = a1->Tail.Overlay.CurrentStackLocation; v8 = *((_QWORD *)v6 + 0x30); v11 = *(_QWORD *)(v8 + 0x20); case 0xB: case 0x48: v47 = v11; v34 = NtfsSetLinkInfo(v4, v73, v10, v9, v47); }那么这个参数到底是什么呢,我们需要从CurrentStackLocation看起,CurrentStackLocation是IRP中的一个非常关键的成员,包括IRP封装调用Driver的方法MajorFunction都在此结构中,其数据类型是_IO_STACK_LOCATION。我们可以在这个地方下断点,命中时查看_IO_STACK_LOCATION结构。
3: kd> p Breakpoint 0 hit Ntfs!NtfsSetLinkInfo: fffff803`8434d694 4c8bdc mov r11,rsp 1: kd> dq ffffa402da68f010+b8 l1 ffffa402`da68f0c8 ffffa402`da68f3b0 1: kd> dt _IO_STACK_LOCATION ffffa402`da68f3b0 ntdll!_IO_STACK_LOCATION +0x000 MajorFunction : 0x6 '' +0x001 MinorFunction : 0 '' +0x002 Flags : 0 '' +0x003 Control : 0xe0 '' +0x008 Parameters : <anonymous-tag> +0x028 DeviceObject : 0xffffa402`d68f6030 _DEVICE_OBJECT +0x030 FileObject : 0xffffa402`dac559d0 _FILE_OBJECT这里需要解释一下,我在调试时直接在NtfsSetLinkInfo下断点是因为其第二个参数就是IRP结构,所以可以通过IRP直接跟踪到第五个参数的值,这里IRP结构的地址是0xffffa402da68f010,而_IO_STACK_LOCATION在IRP+0xb8偏移位置。
可以看到_IO_STACK_LOCATION + 0x30位置是FileObject,这个FileObject就是硬链接目标文件的FileObject。
接着可以跟踪FileObject+0x20是什么。
1: kd> dx -id 0,0,ffffa402ddde7080 -r1 ((ntdll!_FILE_OBJECT *)0xffffa402dac559d0) ((ntdll!_FILE_OBJECT *)0xffffa402dac559d0) : 0xffffa402dac559d0 [Type: _FILE_OBJECT *] [+0x000] Type : 5 [Type: short] [+0x002] Size : 216 [Type: short] [+0x008] DeviceObject : 0xffffa402d68cc860 : Device for "\Driver\volmgr" [Type: _DEVICE_OBJECT *] [+0x010] Vpb : 0xffffa402d47fa3a0 [Type: _VPB *] [+0x018] FsContext : 0xffffe388a39a11b0 [Type: void *] [+0x020] FsContext2 : 0xffffe388a6297370 [Type: void *]可以看到,其偏移+0x20处的对象是FsContext2,其值为0xffffe388a6297370,而第五个参数就是FsContext2,而a5+0x68检查的就是FsContext2+0x68位置的Flag。
我们可以从泄露的windows nt源码中找到关于FsContext2结构的蛛丝马迹,windows nt源码kdexts\ntfs.c的第963行
DumpCcb( (ULONG) File_Object.FsContext2, 1 );Ntfs通过调用DumpFileObject函数中的DumpCcb函数获取ccb(ContextControlBlock),看下DumpCcb函数,ntfs.c的第806行:
VOID DumpCcb ( IN ULONG Address,//FileObject->FsContext2 IN ULONG Options ) { …… pCcb = (PCCB) Address; …… }其实PCCB是上下文控制块,CCB中还包含了文件的信息,比如文件名。
1: kd> dt _FILE_OBJECT 0xffff800bbd4832c0 FsContext2 ntdll!_FILE_OBJECT +0x020 FsContext2 : 0xffffcc8a`116bde50 Void 1: kd> dq 0xffffcc8a116bde50 ffffcc8a`116bde50 00000003`00880709 00000000`00000841 ffffcc8a`116bde60 00000000`00380026 ffffcc8a`1320b4b0 1: kd> dc ffffcc8a`1320b4b0 ffffcc8a`1320b4b0 0057005c 006e0069 006f0064 00730077 \.W.i.n.d.o.w.s. ffffcc8a`1320b4c0 0073005c 00730079 00650074 002e006d \.s.y.s.t.e.m... ffffcc8a`1320b4d0 006e0069 00000069 4134342d 31392d45 i.n.iFileObject->FsContext2最终会直接被强制转换成PCCB对象,其实a5+0x68就是PCCB+0x68,这个值是由什么决定的呢?这需要经过一些逆向分析。这里我简述一下分析过程,首先,我们知道FsContext2的值来自于FileObject,而这些结构体都处于IRP封装中,在nt! NtSetInformationFile函数中:
LODWORD(v32) = IopAllocateIrpExReturn(DeviceObject, DeviceObject->StackSize, (unsigned __int8)(v31 ^ 1), retaddr);// Create IRP v34 = v32; Irp = v32; if ( v32 ) { …… *(_QWORD *)(v36 + 48) = v16; // Get FileObject …… }函数会创建IRP结构,如果创建成功,则会为IRP结构赋初值,其中v36+0x30是FileObject,v16的值来自于v83,而v83的则是通过句柄表获取的object,仍然在nt!NtSetInformationFile中。
v15 = ObReferenceObjectByHandle(Handle, v14, (POBJECT_TYPE)IoFileObjectType, v7, &v83, 0i64); v16 = v83;这个值是通过FileHandle获取的,FileHandle则是外层传入的,在James Forshaw的代码中通过OpenFile获取Handle,其打开的Access定义为MAXIMUM_ALLOWED,就是以最大的允许权限打开文件。
最终我们跟踪到NtOpenFile函数中调用ntfs!NtfsSetCcbAccessFlags设置+0x68偏移位置的flag,其调用路径为
2: kd> k # Child-SP RetAddr Call Site 00 ffffca88`5a766e48 fffff807`52d32d20 Ntfs!NtfsSetCcbAccessFlags 01 ffffca88`5a766e50 fffff807`52d37382 Ntfs!NtfsCommonCreate+0x2080 02 ffffca88`5a767040 fffff807`4fa08829 Ntfs!NtfsFsdCreate+0x202 03 ffffca88`5a767270 fffff807`52045b3d nt!IofCallDriver+0x59 …… 0c ffffca88`5a767980 fffff807`4fbdb3a5 nt!NtOpenFile+0x58 2: kd> p Breakpoint 0 hit Ntfs!NtfsSetCcbAccessFlags: fffff807`52c47c90 4c8bdc mov r11,rsp 2: kd> r rdx rdx=ffff800bc33b34e0 2: kd> dq ffff800bc33b34e0+b8 l1 // _IO_STACK_LOCATION ffff800b`c33b3598 ffff800b`c33b3880 2: kd> dt _IO_STACK_LOCATION ffff800b`c33b3880 FileObject ntdll!_IO_STACK_LOCATION +0x030 FileObject : 0xffff800b`c3d13670 _FILE_OBJECT 2: kd> dt _FILE_OBJECT 0xffff800b`c3d13670 FsContext2 FileName ntdll!_FILE_OBJECT +0x020 FsContext2 : 0xffffcc8a`15611620 Void +0x058 FileName : _UNICODE_STRING "\Windows\system.ini" 2: kd> dd 0xffffcc8a`15611620+68 l1 ffffcc8a`15611688 00000000这里还未赋值,接下来跟踪到NtfsSetCcbAccessFlags如下上下文位置,具体代码如下
fffff807`52c47ce0 0fb74714 movzx eax,word ptr [rdi+14h] fffff807`52c47ce4 6623c2 and ax,dx fffff807`52c47ce7 66094168 or word ptr [rcx+68h],ax 3: kd> dq ffff800bc65d22b0+14 ffff800b`c65d22c4 02000000`001200a9可以看到FsContext2+0x68值来源于0x1200a9和0x1a7与运算的结果,最后的值为0xa1,这个值会最后在NtfsSetLinkInfo中判断,而0x1200a9实际上就是ACE AccessMask,0x1200a9表示文件对当前进程只有Read Permission,而FullControl则是0x1f01ff,如果将File变成normal user可控的文件就会发现。
2: kd> dd ffff800b`bf2a7510+0x14 l1 ffff800b`bf2a7524 001f01ff因此最后0xa1和0x310进行与运算的结果是0x0。
1: kd> p Ntfs!NtfsSetLinkInfo+0x212: fffff807`52d4d8a6 b910030000 mov ecx,310h 1: kd> p Ntfs!NtfsSetLinkInfo+0x217: fffff807`52d4d8ab 6641854d68 test word ptr [r13+68h],cx 1: kd> dd r13+68 l1 ffffcc8a`167399c8 000000a1最终会进入SeAccessCheck检查文件访问权限,从而阻止创建硬链接。感兴趣的读者可以尝试用windbg修改FsContext2->Flag的值令其与0x310与运算后值为1,则可以创建高权限文件的硬链接。