前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >复杂变量测试php7.1.20可能存在的漏洞

复杂变量测试php7.1.20可能存在的漏洞

作者头像
随心助手
发布2019-10-15 12:05:23
7710
发布2019-10-15 12:05:23
举报
文章被收录于专栏:nginx遇上redisnginx遇上redis

作者:zedd

近期有小伙伴问了我一道题,然后自己发掘到了一些关于 PHP 复杂变量不太被关注的问题。

起因

起因是因为一个小伙伴问了我一道题

<?php
highlight_file(__FILE__);
$str = $_GET['str'];
$str = addslashes($str);
if(preg_match('/[A-Za-z0-9]+\(/i',$str) == 1){
    die('hack');
}
eval('$a="' . $str . '";');
?>

自己想了好一会好像并没有能用自己当时的现有知识去解决这个问题,于是我去搜集了一些资料学到了一些新的知识。感兴趣的小伙伴可以先自己做一下哈~

题目解释

整个代码逻辑非常简单,接受一个$_GET['str']的传参,在经过addslashes()函数转义特殊符号与正则表达式检验之后,传入eval()当中拼接到$a="";变量当中。

既然有eval(),那是不是可以执行命令呢?答案是当然可以的。

首先我们来看正则表达式的效果如下图所示

如果小括号前有数字或者字母的话就会die()掉整个程序,大概意思就是防止直接使用函数,例如不能直接使用system('ls')这样子。

PHP 复杂变量

Introduction

下面我们简单介绍一个关注度比较少的一个 php 知识——PHP 复杂变量。按照 php 官方文档对复杂变量的介绍

{% colorquote success %}

复杂语法不是因为其语法复杂而得名,而是因为它可以使用复杂的表达式。

任何具有 string 表达的标量变量,数组单元或对象属性都可使用此语法。只需简单地像在 string 以外的地方那样写出表达式,然后用花括号 {} 把它括起来即可。由于 { 无法被转义,只有 $ 紧挨着 { 时才会被识别。可以用 {\$ 来表达 {$

{% endcolorquote %}

我们介绍一个简单的例子:

<?php
$great = 'fantastic';

// 无效,输出: This is { fantastic}
echo "This is { $great}";

// 有效,输出:This is fantastic
echo "This is {$great}";
echo "This is ${great}";

也就是说在 php 中,我们还可以利用${xxx}的形式来表达一个变量。

Usage

官方文档还给出了一个非常有意思的 Note:

{% colorquote success %}

Note:

函数、方法、静态类变量和类常量只有在 PHP 5 以后才可在 {$} 中使用。然而,只有在该字符串被定义的命名空间中才可以将其值作为变量名来访问。只单一使用花括号 ({}) 无法处理从函数或方法的返回值或者类常量以及类静态变量的值。

{% endcolorquote %}

函数、方法!所以我们根据文档可以怎么利用呢?

<?php
highlight_file(__FILE__);
$a = "${phpinfo()}";
?>

Thinking

然而为什么可以这么做呢?虽然官方文档很明确的指出了,但是是不是还是有一点费解的感觉?

其实在 php 中,我们可以查阅 php 文档知道有

{% colorquote success %}

PHP 中的变量用一个美元符号后面跟变量名来表示。变量名是区分大小写的。

变量名与 PHP 中其它的标签一样遵循相同的规则。一个有效的变量名由字母或者下划线开头,后面跟上任意数量的字母,数字,或者下划线。按照正常的正则表达式,它将被表述为:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'

{% endcolorquote %}

我们可以看到${phpinfo()}里面在严格意义上来说并不是一个变量,那为什么可以执行呢?

让我们来看一个例子

在 php 中,可以接受函数的返回值作为变量名,而phpinfo()的返回值为TRUE,所以先将phpinfo()执行了,将返回值返回作为了变量名。

Challanges

Easy

我们不妨先把问题简化,如果没有任何防护,我们可以怎么做呢?

<?php
error_reporting(0);
highlight_file(__FILE__);
$str = $_GET['str'];
eval('$a="' . $str . '";');
?>

直接传入拼接自然我们肯定有双引号闭合进而执行命令。

Medium

<?php
error_reporting(0);
highlight_file(__FILE__);
$str = $_GET['str'];
$str = addslashes($str);
eval('$a="' . $str . '";');
?>

那加上addslashes()方法呢?既然不能逃逸双引号,我们就可以利用 php 复杂变量来处理。

Difficult

<?php
highlight_file(__FILE__);
$str = $_GET['str'];
$str = addslashes($str);
if(preg_match('/[A-Za-z0-9]+\(/i',$str) == 1){
    die('hack');
}
eval('$a="' . $str . '";');
?>

好的,终于回到了我们题目,这样的话就不能单纯地使用函数方法了。那我们可以怎么做呢?

如果开启了Notice回显的话,我们可以利用反引号就可以简单实现命令执行了

那要是没开启呢?自然不可行了。

接下来就可以利用可变函数的与字符串拼接的特性了.

所以我们可以这里玩法就很多样了.

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 nginx遇上redis 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 起因
    • 题目解释
    • PHP 复杂变量
      • Introduction
        • Usage
          • Thinking
          • Challanges
            • Easy
              • Medium
                • Difficult
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档