zoukankan      html  css  js  c++  java
  • [0CTF 2016]piapiapia

    很有意思的一道题

    访问页面之后是登录界面

    尝试弱口令登录一下,无果

    查看源代码之后也没有什么提示,扫描敏感目录,发现有源码泄露。

    这里我用御剑没有扫出来源码泄露,可能跟扫描线程太快了有关,查看www.zip里面泄露的源代码

    class.php里面定义了user和mysql两个类

    config.php里面是服务器搭建环境的时候设置的参数,如果读者有自己本地搭建环境的经验就会知道,我们下载下来源码之后,还需要根据自己本地的环境进行相应的配置,比如说我们需要在config.php里面设置自己本地数据库的用户名和密码,这些在下载下来的config.php的源代码里面都是暂时空缺的。

    所以题目环境docker下发的时候,一定也设置了自己本地的$flag的值,于是我们的目标就是需要读取服务器端config.php文件,就能够得到flag了。

    在register.php里面,可以看到是注册一个用户,输入用户名和密码,接着跳转到index.php界面进行登录

    在index.php里面我们输入用户名和密码进行登录,接着跳转到profile.php页面。

    在此之前我们需要传递$profile的值

    这里对我们输入的phone,email,nickname都进行了过滤,在源码的注释里面我已经进行了说明,很明显最后一个if语句的判断跟前两者有所不同,前两者如果phone为数组的话,匹配失败则为null,取反后就die,而第三个if当nickname为数组的时候,它不会匹配到非数字字母的值,也就为false,长度处使用数组strlen函数也会失效,返回NULL,则绕过了此处的if过滤。

    这里添加一个知识点,正则表达式[]内的^表示匹配不存在这类字符的,如图上的第三个if里面的,表示匹配非数字字母的值,在[]外的^表示匹配字符串开头。

    所以对于输入的nickname的值我们是可控的。

    再去看profile.php

    可以看到这里对$profile的值进行了反序列化,接着依次读取,此时对于$photo有一个file_get_contents()文件读取函数,所以这里是我们破题的关键。

    值得一提的是,在class.php的mysql类的定义中,过滤函数为

    可以看出来将黑名单数组里面的值都换成了hacker

    现在我们整理一下思路,update.php中有一个$profile数组变量,这个数组里有$phone, $email, $nickname, $photo几个变量,序列化后profile字段存入数据库,当我们访问profile.php的时候,则会从数据库里面读取profile字段同时反序列化,我们需要控制$photo为config.php,才可以在访问的时候获取到base64编码之后的有flag值的服务器端的config.php

    而我们唯一能够控制的变量则是之前说到的nickname,参考了很多师傅的WP之后,写一下这道题的主要知识点:

    PHP序列化长度变化导致字符逃逸

    首先, PHP反序列化中值的字符读取多少其实是由表示长度的数字控制的,而且只要整个字符串的前一部分能够成功反序列化,这个字符串后面剩下的一部分将会被丢弃

    简单举几个例子大家就明白了


    得到这个结果很正常

    接着我们改变一点点

    得到的结果变成了hello woxxx

    我们可以看到,原来的字符串hello world内被填充了几个字符串,即xxx”;},在PHP进行反序列化时,由字符串初始位置向后读取8个字符,即使遇到字符串分解符单双引号也会继续向下读,此处读取到 woxxx ,而后遇到了正常的结束符”;},达成了正常反序列化的条件,反序列化结束,后面的 rld”;}  几个字符均被丢弃。

    我们用另外一个例子来学习一下这个知识点的应用

    可以看到bad_str函数会将序列化之后的单引号转换成为字符串no,实际上这里就已经有了长度的变化,因为单引号长度是1,而no字符串长度是2

    接着,我们修改用户的签名

    这里偷一张别的师傅的图,虽然输入的值不同,但是思想是相同的

    在我们这里,则是想将hello world改变掉。

    于是构造

    输出的结果跟我们想要的是相同的,hello world变成了hhh

    参考一下大佬博客里面对此的解释

    在反序列化输出之前,我们的字符串是在某过滤函数的过滤替换之后得到的,在经过过滤处理了之后,字符串的某一部分会加长,但是描述其长度的数字没有发生改变(由反序列化时变量的属性决定),这就可能导致PHP在按描述其长度的数字读取相应长度的字符串之后,本该属于该字符串的内容逃逸出了该字符串的管辖范围。轻则反序列化失败,重则自成一家成为一个独立于源字符串的变量,若是这个独立出来的变量末尾是个结束符";},则可能导致反序列化成功结束,而后面的内容也顺理成章的被丢弃了,此处能够逃逸出的字符串长度由过滤后字符串增加的长度决定,如上图第四个语句,@号内就是我们要逃逸出来的字符串,长度为33,百分号内为我们输入的username变量,要想让@号内的字符串逃逸,我们就需要原来的字符串增加33,这样的话@号内的字符串就会被挤出它原来所在的位置,username的正常部分和增长的部分正好被php解析成一整个变量,@号内的内容就被解析成一个独立的变量,而且因为它的最后有";},所以使反序列化成功结束。
    

    再回到我在本地的例子上面,我们为了使hhh替换掉hello world,于是这一段是需要逃逸出来的字符串

    ";i:1;s:3:"hhh";}

    长度为17,而单引号替换成no之后长度只是增加1,所以为了增加17个长度,我们需要17个单引号,这样才能够将逃逸字符串挤出原来的位置。

    紧接着,17*no+test,一共是38个字符,所以在s处我们填写长度为38

    最后的$fakes就为

    a:2:{i:0;s:38:"test'''''''''''''''''";i:1;s:3:"hhh";};i:1;s:11:"hello world";}

    所以在此处我们最终字符串替换成为了hhh

    先闭合了一个变量的正确格式,又写入了一个变量的正确格式,最后闭合了一个反序列化的操作。该挤出的被挤出逃逸了,该丢弃的丢弃了,最后想要达成的目标也实现了。

    于是我们再回归到题目里面来,因为我们最后是从数据库里面读取反序列化之后的结果,所以我们先在本地搭建序列化,看看序列化的格式之后编写相应的payload

    可以看到,根据泄露的源码序列化之后的结果为

    a:4:{s:5:"phone";s:6:"123456";s:5:"email";s:12:"test@126.com";s:8:"nickname";a:1:{i:0;s:4:"hell";}s:5:"photo";s:5:"hello";}

    我们能够构造的是nickname,在这里我已经是传递数组给他了

    我们需要将photo的值hello改变成config.php

    根据之前的基础知识,本地的直接构造为:

    a:4:{s:5:"phone";s:6:"123456";s:5:"email";s:12:"test@126.com";s:8:"nickname";a:1:{i:0;s:72:"hell''''''''''''''''''''''''''''''''''";}s:5:"photo";s:10:"config.php";}s:5:"photo";s:5:"hello";}
    

    需要逃逸的字符串为

    ";}s:5:"photo";s:10:"config.php";}

    长度为34,所以添加34个单引号,长度为34*2+4即72

    可以看到本地的查看的文件已经修改为了config.php

    我们在题目里面使用相同的思想

    因为where转换成hacker会由5–>6,字符有一个增加,所以我们为了逃逸34个字符,就添加34*where

    警告无伤大雅,因为我们传递的是数组类型的值,所以这里会有警告

    源代码里面的base64编码就是config.php的base64编码,解码即可

    可以看到成功读取了config.php,里面有flag的值

    贴上参考的师傅的博客链接

     https://www.jianshu.com/p/3b44e72444c1 
  • 相关阅读:
    巴洛克式和哥特式的区别
    推荐阅读书籍,是时候再行动起来了。
    AtCoder ABC 159F Knapsack for All Segments
    AtCoder ABC 159E Dividing Chocolate
    AtCoder ABC 158F Removing Robots
    AtCoder ABC 158E Divisible Substring
    AtCoder ABC 157F Yakiniku Optimization Problem
    AtCoder ABC 157E Simple String Queries
    AtCoder ABC 157D Friend Suggestions
    AtCoder ABC 156F Modularness
  • 原文地址:https://www.cnblogs.com/Cl0ud/p/12177095.html
Copyright © 2011-2022 走看看