联系我们联系我们
电子邮箱电子邮箱

浅析PHP变量解析复杂规则语法

[复制链接]
  • TA的每日心情
    开心
    2017-12-29 14:06
  • 签到天数: 1 天

    [LV.1]初来乍到

    gilgamesh 发表于 4 天前
    295 0

    前言
    翻了好久前写过的关于php复杂语法变量解析的文章,发现很多地方存在问题。因此又查阅文档重新理解了一遍该语法,谈谈个人的理解,并记录在此。

    题目简析
    一道很早之前的题目,代码(简化):
    $str= @(string)$_GET['str'];eval('$str="'.addslashes($str).'";');
    通过eval执行php代码获得flag,addslashes函数将字符串中的特殊字符转义,“{}”在双引号中可以标记变量边界来解析,利用该方式来达到代码执行的目的。
    eg:
    通过payload:${assert($_GET[cmd])}}即可获取shell,也可以利用system函数来执行命令读取flag等。

    变量解析之复杂语法
    当字符串用双引号或heredoc结构定义时,其中的变量将会被解析。共有两种语法规则,一种简单规则,一种复杂规则,这里讨论复杂规则。
    复杂规则语法的显著标记是用花括号包围的表达式。任何具有string表达的标量变量,数组单元或对象属性都可使用此语法,表达方式{$var_name}或${var_name}。
    根据php官方文档,这里提示在PHP5以后可以使用{$}来调用函数、方法等。看下面的例子:
    不难理解,{${getname()}} => {$s1ye},以函数返回值命名变量。这里我在函数中加入了echo "s1ye";,可以发现先执行了getname函数并输出了“s1ye”,接着才执行了echo(优先级)。
    为了方便理解payload,利用以下代码进行测试:
    构造了一个类似phpinfo的简化函数,利用变量解析在双引号中的复杂语法,先执行了test函数输出了“just for test”并返回true,可以看到,返回一条警告并且变量a的值是空的。
    为什么Notice为”Undefined variable: 1”呢?返回TRUE,变量应该为$TRUE的。前面官方文档说过了,$ string的变量会被解析,而TRUE是bool类型,并且是个常量,当返回TRUE并命名变量时php解析器将TRUE转换为了string类型。
    由于没有该变量导致赋值给a变量时返回为空(并不能用数字开头来命名变量)。

    理解payload
    直接利用payload{${phpinfo()}}或者${${phpinfo()}}会返回phpinfo信息,但都会报错。
    上面已经讲过了报错的原因,这里就很好理解了。接下来逐步的来分析payload成功执行的过程:
    eval函数将字符串当作php代码执行,因此,通过图中代码清晰可见相当于定义了str变量,赋值为一个字符串”{${phpinfo()}}”。
    $str = "{${phpinfo()}}",花括号定义了变量的边界,因此该条语句先执行括号中内容,获取函数返回值,并以返回值的string命名变量再赋值给str变量(同上面分析的test函数一样)。
    到了这里只要修改”{${?}}”中的?为其他php代码就可以达到写文件读文件或者getshell等操作了,只需要注意addslashes函数即可。

    思考
    先看一下原题代码
    eval('$str="'.addslashes($str).'";');
    在双引号中可以利用花括号定义变量边界,调用函数等,如果修改为单引号包裹addslashes函数,还能执行代码了吗。
    $str = @(string)$_GET['str'];eval("$str='".addslashes($str)."';");
    很容易就发现虽然addslashes函数部分内容被单引号包裹,但是变量str却变成了双引号包裹。这说明还是可以被利用的,直接尝试上面的payload:
    发现报错,变量同样被双引号包裹(其实并没有被双引号包裹),这里却报错了。但是payload2${${phpinfo()}}却可以正常执行。
    其实这里只要稍微思考一下就可以理解了,用两个例子来解释:
    可以看到payload1不能执行成功的原因就是并没有被双引号包裹,所以外层标记变量边界的花括号无用。而payload${phpinfo()}/${${phpinfo()}}(无论加几个”${}”都无差,只不过报错更多而已)相当于$a=’string’,a==(phpinfo()的返回值string形式),即执行函数后利用返回值定义变量并赋值,因此可以执行成功。

    总结
    整体看下来感觉还是很绕的,总结就是遇到问题除了百度谷歌,要多认真读官方文档, 其实文档已经写得很清楚了。


    本文转自:360安全客

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    发表新帖

    小黑屋|手机版|Archiver|华盟论坛 ( 京ICP证070028号 )

    Powered by 华盟网 X 8.0  © 2001-2013 Comsenz Inc.  华夏黑客同盟