news 2026/9/9 1:38:16

NullBytes靶机通关:SQL注入与SUID提权实战记录

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
NullBytes靶机通关:SQL注入与SUID提权实战记录

看了一遍又一遍,NullBytes 这台 VulnHub 靶机给我的感觉就是:麻雀虽小,五脏俱全。它不像 DC 系列那样动不动就要打域环境,也不像那些动不动堆内核漏洞的靶机让人一脸懵,它老老实实走的是“Web 注入 → 口令复用 → 本地提权”这条经典路线。对新手来说,这条链路干净、清晰,每一步都是可以单独拿出来反复练的基本功;对准备 OSCP 或者已经在刷 PTE 的人来说,NullBytes 又是一个特别好的“考试模拟器”,因为它把最容易在真实渗透里犯的错误全部埋进去了,比如密码复用、SUID 滥用、哈希识别。

这篇文章是我自己从下载 VM 到拿到 root 的完整通关记录,不是那种只贴结果的复盘,而是把每一步怎么判断、为什么这么判断、踩了什么坑全部写清楚。文章以本地虚拟机环境的安全实验为背景,所有操作都在 VulnHub 提供的靶机上进行,适合刚入门想系统练一遍完整攻击链的朋友。

1. 认识 NullBytes:这靶机到底在考什么

1.1 靶机基本信息与部署环境

NullBytes 是 VulnHub 上由作者 Airtight 发布的一台 boot2root 类型靶机,镜像格式是 ova,下载后直接导入 VMware 或 VirtualBox 就能用。我这边使用的环境是 VMware Workstation,攻击机是 Kali,网络模式选的是 Host-Only。为什么选 Host-Only?因为这种模式把靶机和攻击机放在一个完全隔离的内部网络里,不会受到外部网络干扰,也避免了 DHCP 分配出来的地址漂移问题。

导入时有一个细节要注意:ova 导入之后,建议先检查一下虚拟机的网络适配器是不是“仅主机模式”。有些版本默认会给你 NAT,而 NAT 模式下攻击机和靶机是否在同一网段是不一定的,一旦不在一起,后面所有扫描都会白做。我的习惯是导入后立刻在 Kali 里执行ip a看一眼本机 IP,再决定要不要调整。

另外,启动这台靶机不要急,它开机速度比一般 Ubuntu 虚拟机慢不少,我第一次等了两分钟还没看到登录界面,差点以为镜像坏了。后来发现只是正常的启动慢,耐心等一下就好,不用去按键盘任何键。

1.2 通关链路全景:先建模再动手

打靶机最忌讳的是一上来就拿工具乱扫,然后不知道下一步干嘛。正确做法是先建立一个全局模型:这台机器现在对外暴露了什么,我作为一个攻击者能从哪里切入,拿到入口之后又该怎么扩大战果。

NullBytes 的攻击链大概是这样一个走向:

  1. 网络发现:通过 arp-scan 或 netdiscover 定位靶机 IP
  2. 端口扫描:nmap 确认开放的端口和服务
  3. Web 应用分析:发现 SQL 注入,提取数据库用户和密码
  4. 认证突破:用 Web 端拿到的密码尝试 SSH 登录
  5. 权限提升:利用 SUID 文件或 sudo 配置从普通用户提权到 root
  6. 拿到最终 flag 完成通关

这套链路不是 NullBytes 独有的,而是几乎全部 Linux boot2root 靶机的通用模板。真正拉开差距的地方,在于每一步做得到底扎不扎实:端口扫描有没有漏掉 UDP 或高位端口,Web 注入是直接用工具盲跑还是手工会更快,拿到凭据之后有没有下意识去试服务复用。所以这篇文章我会花比较大篇幅写“为什么这样做”,而不是单纯地把命令堆出来。

2. 信息收集:找到靶机并摸清它的底细

2.1 网络发现:三条路找到靶机 IP

靶机开机后,先从攻击机确认自己的内网地址。假设 Kali 的地址是 192.168.56.102/24,那么我们需要在 192.168.56.0/24 这个网段里找到新出现的主机。

我常用三个方法,按效率排序:

# 方法一:netdiscover,主动扫描当前网段 sudo netdiscover -r 192.168.56.0/24 # 方法二:arp-scan,从 ARP 表里找活主机 sudo arp-scan -l # 方法三:直接在 VMware 虚拟网络编辑器里看 DHCP 分配记录

netdiscover 和 arp-scan 的输出里,靶机一般会以一个新的 MAC 地址出现在列表里。这里有个小提示:VMware 的虚拟机网卡 MAC 通常以00:0c:29开头,看到这个前缀的新设备基本就是靶机了。如果网段里本来就有一堆虚拟机,这个方法能帮你快速排除干扰项。

实际扫描结果里我记下了靶机 IP:192.168.56.105。这个地址后面所有步骤都会用到,所以建议当场记下来,或者像我一样直接把扫描结果保存到文件里。

2.2 端口扫描:先全量再精准

确定 IP 后先做一次全端口 TCP 扫描,不要一上来就用-sV精确识别,因为版本探测对没开放的端口毫无意义,只会白白浪费时间。

nmap -sS -p- -T4 -oN full_scan.txt 192.168.56.105

TCP SYN 扫描结果出来,只有两个端口开放:

  • 22/tcp SSH
  • 80/tcp HTTP

看到这个结果的第一反应应该是:攻击面很窄,Web 服务几乎是唯一的突破口。于是再对这两个端口做版本识别和默认脚本扫描:

nmap -sV -sC -p 22,80 192.168.56.105

扫描结果显示 80 端口上是 Apache + PHP 环境,22 端口是 OpenSSH。到这里,脑子里应该已经有一个初步方向了:Web 层大概率存在可挖掘的漏洞,如果能拿到某些凭据,还可以尝试 SSH 远程登录。

2.3 目录枚举:把表面的隐藏接口挖出来

打开浏览器访问 http://192.168.56.105,页面上是一个比较简洁的站点。这种静态页面对渗透测试来说价值有限,真正有价值的是隐藏的后台和功能接口。所以下一步做目录枚举:

gobuster dir -u http://192.168.56.105 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,txt,bak

-x参数的目的是把常见的扩展名一起带上,很多后台脚本是 index.php 这个形态,不带php后缀扫描就漏了。扫描结果里出现了几个和后台、登录相关的路径。逐一访问之后,我发现一个页面有用户查询功能,另一个页面是登录入口。它们表面上功能不同,但实际请求都指向同一个后台处理脚本,差别只在于参数不同。

到这一步,信息收集阶段基本完成。接下来进入 Web 漏洞挖掘的重头戏。

3. Web 漏洞挖掘:SQL 注入从入门到拿下

3.1 用 Burp 梳理请求特征

信息收集结束,下一步就是对 Web 功能点进行交互测试。先把 Burp Suite 打开,把浏览器代理挂到 127.0.0.1:8080,然后在那个用户查询页面随便输入一个名字,点击查询。

Burp 的 HTTP History 里能看到这次请求的完整格式:

POST /search.php HTTP/1.1 Host: 192.168.56.105 Content-Type: application/x-www-form-urlencoded username=admin&submit=1

这个username参数是用户输入点,也是我们接下来要重点测试的目标。很多新手一上来就喜欢用 sqlmap 直接打,我完全不反对,但前提是你至少手工验证过一遍参数,知道它大概是个什么情况。这样用工具时才不会因为工具输出太抽象而看不懂结论。

3.2 手工注入验证:从报错到布尔盲注

我在 Burp 的 Repeater 里手工改了 username 参数,做了一次最简单的注入测试:

username=admin' -- -

回显直接出现 SQL 语法错误,并且报错内容里暴露了数据库查询语句的结构。这几乎可以断定参数存在 SQL 注入,而且是有回显的报错型注入,不需要靠猜。

继续验证字段返回逻辑,我使用:

username=admin' and 1=1 -- - username=admin' and 1=2 -- -

两次回显结果明显不同:第一次正常返回查询结果,第二次返回空记录。这确认了存在布尔盲注,我们可以通过条件为真或假时的页面差异来推断数据。

再进一步用 order by 探测查询结果集的列数:

username=-1' order by 3 -- - username=-1' order by 4 -- -

order by 4 时页面报错,说明当前查询正好是 3 列。接着尝试联合查询:

username=-1' union select 1,2,3 -- -

回显中 2 和 3 的位置有内容输出,这意味着我们完全可以在回显位填充要提取的数据。到这步,SQL 注入的利用条件已经全部具备。

3.3 用 sqlmap 快速提取数据库内容

手工验证完毕,接下来用 sqlmap 提升效率。指定注入点和数据库类型:

sqlmap -u "http://192.168.56.105/search.php" \ --data="username=admin&submit=1" \ --dbms=mysql --dbs --batch

sqlmap 跑了一会儿,成功枚举出两个数据库:information_schemanullbytes。前者是 MySQL 自带的元数据库,不用管;后者明显是目标业务库。

继续 dump nullbytes 库里的内容:

sqlmap -u "http://192.168.56.105/search.php" \ --data="username=admin&submit=1" \ -D nullbytes --dump --batch

dump 结果里出现了一个 users 表,字段包括用户名和密码哈希。用户名为 admin,哈希看起来是 MD5 格式。

这里说句实话,sqlmap 虽然强大,但在布尔盲注场景下速度并不快。如果着急,可以加上--threads=5提高并发,再搭配--technique=BE指定只使用布尔盲注和报错型注入,会明显快很多。

3.4 哈希识别与口令破解

拿到哈希后的第一件事不是直接跑字典,而是先确认哈希类型。我用hashid识别:

hashid "21232f297a57a5a743894a0e4a801fc3"

程序判断可能是 MD5。然后直接交给 john:

echo "21232f297a57a5a743894a0e4a801fc3" > hash.txt john --format=raw-md5 --wordlist=/usr/share/wordlists/rockyou.txt hash.txt john --show hash.txt

很快就跑出来了,明文是admin。看起来弱口令到哪儿都存在,不管你是真实业务还是靶机环境。

这里有个重要的提醒:哈希识别错了,后面破解就是浪费时间。如果 hashid 给出的结果不唯一,可以用 john 的--list=formats查一下支持的格式,或者干脆用 hashcat 的--identify功能。我见过有人把 SHA256 当 MD5 跑,跑了半个多小时一点动静没有,最后才发现是自己认错了哈希。

4. 获取初始权限:SSH 登录与系统内部侦察

4.1 密码复用:从 Web 到 SSH 的跳跃

拿到admin:admin这组凭据后,我的第一反应不是回 Web 后台继续找功能,而是直接尝试 SSH。为什么?因为在真实渗透里,用户为了省事,把同一个密码用在 Web、SSH、数据库等所有地方,是一个非常普遍的操作。CTF 靶机既然给你留了 22 端口,多半就是等着你拿这组密码来登录。

ssh admin@192.168.56.105

输入密码 admin,登录成功。注意这里我不是让你手动输入,而是建议你后续在脚本化批量尝试时使用sshpass,再加一个-o StrictHostKeyChecking=no跳过指纹确认,这样就不会卡在交互式确认上。

登录后执行id,显示当前用户是 admin,uid 是 1000,属于普通用户组。到这里,我们已经从“外部攻击者”变成了“拥有合法账号的普通用户”,初始权限达成。

4.2 系统内部侦察:每一步都是在为提权铺路

拿到初始权限只是第一步,最终目标还是 root。所以我登进去后的第二件事,就是系统枚举。下面这几条命令几乎是我在每台 Linux 靶机上都会跑一遍的“基础套餐”:

id sudo -l uname -a cat /etc/crontab find / -perm -4000 -type f 2>/dev/null ls -la /home cat /home/admin/.bash_history

逐条说下判断思路:

sudo -l如果输出的是类似User admin may run the following commands,那就直接看有没有我们可以利用的命令。如果输出的是Sorry, user admin may not run sudo,那就说明当前用户根本没有 sudo 权。

uname -a是用来判断内核版本的。如果内核特别老,可以尝试内核提权漏洞,但我一般把它放在备用方案里,不优先用。原因很简单:内核提权脚本很容易把系统打崩,一旦崩了,整个靶机重启,前面所有进度都得重来。

cat /etc/crontab是看计划任务。如果有脚本是以 root 身份定期执行的,而且路径又恰好可写,那提权思路就变成了“写一个反向 shell 到脚本所在目录”。

find / -perm -4000 -type f这一步是找 SUID 权限的文件,也是这轮枚举里收获最大的地方。执行完以后,我在列表里看到了一个非常显眼的文件:/usr/bin/find

5. 提权到 root:最后一百米的实战操作

5.1 分析 SUID 文件,确认提权可行性

为什么/usr/bin/find带着 SUID 权限就意味着提权?我试图把原理讲透。

Linux 里每个进程都有“真实用户 ID”和“有效用户 ID”两个概念。你执行一个程序时,进程的有效用户 ID 默认就是你的用户 ID。但是当一个文件被设置了 SUID 位(即权限位里的 s),你执行这个文件时,进程的有效用户 ID 会变成文件所有者的用户 ID。如果这个二进制文件的所有者是 root,那就相当于你执行它时,程序临时获得了 root 的权限。

find 本身有一个-exec参数,可以在找到文件时执行后面跟着的命令。如果 find 是 SUID root,那就等于你能以 root 身份执行任意命令,只是入口是 find 这个合法程序而已。

先确认权限位:

ls -l /usr/bin/find

输出是-rwsr-xr-x,注意 owner 权限位里的s,说明 SUID 确实生效。GTFOBins 里对这种“可执行任意命令的 SUID 二进制”有现成的利用方法,我们直接用标准姿势。

5.2 利用 find -exec 拿到 root shell

经典的利用命令如下:

find / -name "test" -exec /bin/bash -p \;

这里有个细节特别容易踩坑:/bin/bash后面的参数必须是-p,不能是-i。原因是当 bash 检测到有效用户 ID 和真实用户 ID 不一致时,它会主动把有效用户 ID 降回到真实用户 ID,这其实是 bash 的一种自我保护机制。加了-p之后,bash 才会保留 SUID 带来的特权。我第一次就是用-i启动的,结果执行完id一看,还是 uid=1000,当时还很疑惑,后来查了 GTFOBins 才明白是参数少了-p

执行成功后:

id

输出直接变成:

uid=0(root) gid=0(root) groups=0(root)

到这里,root 权限已经拿下。整个过程没有打内核漏洞,没有用复杂 exp,就是靠一个错误配置的 SUID 文件,这是 Linux 提权里最常见也最经典的场景。

5.3 找到最终 flag,验证通关

提权成功后的第一个动作,是去根目录找最终 flag:

cat /root/root.txt

看到 flag 的那一刻,这台靶机才算正式通关。整理一下这次的完整攻击路径:Web 查询点存在 SQL 注入 → sqlmap 提取数据库哈希 → john 破解出 admin 密码 → SSH 登录 → 发现 SUID find → 利用 -exec 拿到 root。每一步都是环环相扣的。

6. 通关中的常见问题与避坑心得

6.1 同一套命令,为什么会有人通关有人翻车

我在自己复现和帮朋友远程看问题的时候,遇到过不少“明明命令一样,过程就是不一样”的情况。这里整理一个高频问题速查表,希望能帮大家减掉一些不必要的返工。

问题表现排查和解决办法
靶机 IP 扫不到netdiscover 列表里没有新设备网络模式没配对;改成 Host-Only 或 NAT 后重启靶机,再用arp-scan -l重新扫
sqlmap 跑得太慢一直卡在布尔盲注阶段添加--threads=5--technique=BE;确认当前注入是延时型的话换--technique=T
john 破解跑不出结果字典跑完也没有命中先哈希识别;可能是 SHA256 或 bcrypt,换--format=raw-sha256或其他格式重新跑
SUID 提权后还是普通用户执行 bash -i 之后 id 显示 uid=1000必须用bash -p保留特权模式
SSH 脚本化登录卡住停在指纹确认提示-o StrictHostKeyChecking=no,用 sshpass 传密码
虚拟机启动后没有网络靶机 ping 不通网关等启动完成后 2 分钟再试;检查 VMware 网络服务是否正常

6.2 几条值得长期复用的实操心得

信息收集做得越扎实,后面越顺水推舟。Web 目录枚举多扫十分钟,可能就省掉后面两个小时的盲目测试。很多人一上来就丢 sqlmap,完全不看站点结构,最后只能靠运气。

口令复用永远值得优先试。Web 后台的密码不要只想着回页面里用,SSH、FTP、数据库、甚至控制台,所有能登录的地方都值得用同一套密码尝试一遍。真实渗透里,很多服务器就是这么被拿下的。

提权别一上来就上内核漏洞。内核提权脚本是“不得已才上”的方案,一旦失败,系统可能直接重启。CTF 环境下你还能重新加载快照接着打,真实环境里这就是一次事故了。优先看 SUID、sudo 配置、计划任务这些应用层面的错误配置。

6.3 尝试不用 sqlmap 再打一遍

这台靶机打完之后,我建议你回头再用纯手工的方式把 SQL 注入重新走一遍。就靠在 Burp 里一条一条地构造请求,用and 1=1and 1=2这种最基础的方法一点点把数据“问”出来。

整个过程会非常慢,但收获完全值得。当你能不看任何工具输出,就知道为什么一个 PUT 请求要多出一个引号,为什么 order by 的列数会决定 union select 能不能成功,说明你已经不是靠背命令打靶机了,而是真正理解了数据库和 Web 应用之间的交互逻辑。工具能帮你省时间,但只有亲手验证过原理,直觉才能真正建立起来。

7. 复盘:看懂出题人的设计思路

通关之后回头看 NullBytes 的设计,其实能明显感受到出题人的用心。Web 层没有给你太难的外壳漏洞,而是把重点放在了 SQL 注入和凭据复用上,这两点是真实 Web 渗透里最常发生的事情;提权环节也没有靠内核漏洞暴力解,而是让你通过系统枚举去发现错误配置。整个靶机练下来,你会发现所有考点都在“标准动作”里:扫描够不够全,注入判定准不准,哈希识别对不对,Suid 列表有没有仔细看。

这种设计思路本身就是一份很好的学习地图。我每次打一台新靶机,通关后会刻意把攻击过程写成一条时间线,然后问自己三个问题:哪个环节耗时最长?哪个环节当初没想到?如果把这台机器交给出题人自己加固,他会堵上哪个口子?这套复盘方式让我后面打 DC 系列和 Warzone 系列靶机时,明显比以前更有方向感。

如果你也是刚接触 VulnHub,建议不要把 NullBytes 当作最后一站,而是把它当作起点。先吃透这台,再去找一台同样走“Web 注入+提权”路线的靶机继续练,等到你看到端口开放列表就能在脑子里预判出下一步该做什么的时候,这个阶段就算毕业了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 1:38:07

基于STC89C51的双通道DHT11温湿度采集与LCD1602显示系统

简介:这是一套基于STC89C51单片机的双通道DHT11实时温湿度显示系统项目包,面向单片机初学者、电子设计与嵌入式系统爱好者,适合用于课程设计或毕业设计参考。项目以STC89C51为控制核心,通过单总线读取两路DHT11传感器数据&#xf…

作者头像 李华
网站建设 2026/9/9 1:38:02

PHP镜像克隆网站源码v4.0:整站备份与部署实战解析

简介:单域名PHP镜像克隆网站源码v4.0是一套以PHP开发的镜像站点程序,主要面向需要快速搭建单域名采集镜像站的开发者和个人站长,重点解决多蜘蛛抓取时IP易被限制、PC端与移动端适配成本高等问题。压缩包仅313KB,共58个文件&#x…

作者头像 李华
网站建设 2026/9/9 1:33:21

网站权威性与关键词排名的关系:长尾词策略撬动自然流量

1. 先搞明白:网站权威性到底是个什么东西做SEO的人天天把“权重”“权威性”挂在嘴边,但真被问一句“什么是网站权威性”,很多人的回答其实都停留在“外链多的网站就是权威网站”这种表面理解。我在这个行业摸爬滚打了十几年,见过…

作者头像 李华
网站建设 2026/9/9 1:32:11

前置过滤器避坑指南:从材质到反冲洗,别交智商税

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/9 1:31:24

用Rust构建轻量级异步流处理库:ruflo的设计与实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/9 1:29:23

ARM ABI规范全景解析:从arm-software/abi-aa仓库到编译器后端落地

做交叉编译这些年,我有个根深蒂固的习惯:只要遇到“函数调用传参传得好好的,一优化就炸”这类问题,第一反应不是去翻优化选项,而是去查编译器到底按哪一套 ABI 来生成代码。ABI 全称 Application Binary Interface&…

作者头像 李华