记一次ctf招新
PHP反序列化漏洞
什么是序列化
我们在运行代码的时候一个对象在代码结束的时候就被销毁了,我们如果在另一个地方要调用的话还要重新去声明,如果我们将这个对象序列化成一个字符串储存,在要调用的时候再把它反序列化出来。
我们定义的类里面的变量是有自己的属性的。
PHP 对属性或方法的访问控制,是通过在前面添加关键字 public(公有),protected(受保护)或 private(私有)来实现的,字母对应的类型
- public(公有):公有的类成员可以在任何地方被访问。
- protected(受保护):受保护的类成员则可以被其自身以及其子类和父类访问。
- private(私有):私有的类成员则只能被其定义所在的类访问。
1 | a - array 数组 |
序列化的实例

在这里我们把file的值定为flag.php,但是因为这里的$file是privat形式的所以我们在写脚本的时候要将flag.php放到()里面,同时这里因为是private类型的变量在反序列化的时候在变量名的长度是会有两个空格的,在你生成代码后直接复制是不行。

输出为:O:+4:”Demo”:2:{s:10:”Demofile”;s:8:”fl4g.php”;}因为这里有一个base64的解码我们直接在这里加密了
说以真正输出是TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQo=
PHP魔法函数
常见的魔法函数
1 | __construct: 在创建对象时候初始化对象,一般用于对变量赋初值。 |

反序列化漏洞的成因大多就是我们定义的类对象中的函数中存在危险指令被利用而导致的,而这些特有的函数是可以被重写的,这里就是可以利用这些函数去构造pop链,然后触发敏感函数执行我们的恶意代码,反序列化漏洞的出现一般就是程序员对魔法函数的触发没有考虑好出现的。
tips
绕过_wakeup函数:当我们的设置的属性的个数大于实际的个数的时候wakeup就可以做到绕过上面那个题目就是把xctf中的属性值改为2就好了,这是CVE-2016-7124适用版本
PHP5 < 5.6.25
PHP7 < 7.0.10
绕过正则匹配:在反序列化后的数据的O:4的4前面加上一个+号就能够绕过这个,这是PHP的bug参考:https://www.phpbug.cn/archives/32.html
复现
有关骑士CMS<6.0.48的任意文件包含漏洞

在这里看到骑士的版本是6.0.20然后在网上去找到了方法 http://127.0.0.1/74cms/upload/index.php?m=home&a=assign_resume_tpl 这个是漏洞地址
我们要将ariable=1&tpl=“)?>; ob_flush();?>/r/n<qscms/company_show 列表名=”info” 企业id=”$_GET[‘id’]”/>一post形式传参过去
然后包含日志文件
post传variable=1&tpl=data/Runtime/Logs/Home/22_03_02.log完成操作
同样我们可以放
variable=1&tpl=“)?>; ob_flush();?>/r/n<qscms/company_show 列表名=”info” 企业id=”$_GET[‘id’]”/>这段代码这样就可以在保含日志文件的时候将这段代码给执行写一个后门上去
当我们的concat被过滤的情况下sql注入该怎么办呢
make_set用法:在mysql中使用make_set,函数的第一个参数为字符串,后面的可以理解为回显位。当第一个参数为1时,根据其二进制的反过来的值,如果对应后面的位置为1的,将1上的内容显示出来:1的二进制为0001,反过来为1000,因此显示的为1所在位置的值a:那么如果是3的话二进制是0011反过来就是1100就会把前两个给输出
这个题目需要用到make_set()函数make_set(1,’a’,’b’,’c’)返回的是那我们的思路就是利用报错函数(这里把union 也过滤了就不用联合查询了)and updatexml(1,make_set(‘2’,’~’,(select database())),1)这里之后就直接往下做就好了。