ThinkPHP的SQL注入漏洞学习

news2024/12/26 9:21:22

目录

漏洞环境

漏洞概要

函数学习

call_user_func函数

mplode函数

漏洞分析

漏洞修复

攻击总结


漏洞环境

漏洞存在于 Builder 类的 parseData 方法中。由于程序没有对数据进行很好的过滤,将数据拼接进 SQL 语句,导致 SQL注入漏洞 的产生。

漏洞影响版本: 5.0.13<=ThinkPHP<=5.0.155.1.0<=ThinkPHP<=5.1.5

 composer create-project --prefer-dist topthink/think=5.0.15 tpdemo
 # Windows的环境下通过composer下载情况不是很好,最好还Linux环境下下载

漏洞概要

本次漏洞存在于 Builder 类的 parseData 方法中。由于程序没有对数据进行很好的过滤,将数据拼接进 SQL 语句,导致 SQL注入漏洞 的产生。漏洞影响版本: 5.0.13<=ThinkPHP<=5.0.155.1.0<=ThinkPHP<=5.1.5

composer.json 文件的 require 字段设置成如下:

 "require": {
     "php": ">=5.4.0",
     "topthink/framework": "5.0.15"
 }

然后执行 composer update ,并将 application/index/controller/Index.php 文件代码设置如下:

 <?php
 namespace app\index\controller;
 ​
 class Index
 {
     public function index()
     {
         $username = request()->get('username/a');
         db('users')->insert(['username' => $username]);
         return 'Update success';
     }
 }

如果遇到无法下载,很有可能是被composer.lock锁住,导致无法更新。建议删除后尝试更新。

如果仍然不行,可以去github官方下载think相应版本 + framework 相应版本(5.0.15或者其他符合要求的版本)。将framework解压并且重命名为thinkphp,移动到think-5.0.15文件下。

连接数据库

进入接口文件

注意thinkphp的入口文件存放在public文件下的index.php

application/database.php 文件中配置数据库相关信息,并开启 application/config.php 中的 app_debugapp_trace 。在网站开启debug的情况下,也是可以从过报错信息获取到网站的物理漏洞。但是基本上99%都会关闭是。

创建数据库信息如下:

 create database tpdemo;
 use tpdemo;
 create table users(
     id int primary key auto_increment,
     username varchar(50) not null
 );

函数学习

call_user_func函数

call_user_func 是 PHP 中的一个函数,用于调用回调函数。回调函数是一个在特定时间点被调用的函数,它可以是一个匿名函数(闭包)、一个数组(包含对象和方法)、一个字符串(函数名)等。

语法

 mixed call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] )
参数说明
callback要调用的回调函数
parameter要传递给回调函数的参数。可以传递多个参数。

实例

 //url=http://127.0.0.1/tp5015/think-5.0.15/public/web.php?123=phpinfo()
 //url=http://127.0.0.1/tp5015/think-5.0.15/public/web.php?456=phpinfo()
 ​
 //web.php
 <?php
     assert($_GET[123]);
     call_user_func('assert',$_GET['456']);
 ?>

访问链接,即可触发 SQL注入漏洞 。(没开启 app_debug 是无法看到 SQL 报错信息的)

 ?username[0]=inc&username[1]=updatexml(1,concat(0x7e,user(),0x7e),1)&username[2]=1

mplode函数

implode — 用字符串连接数组元素,用一个 separator 字符串连接数组元素。

 语法
 implode([string] $separator, [array] $array): [string]
 ​
 替代写法(不支持命名参数):
 implode([array] $array): [string]
 ​
 遗留写法(从 PHP 7.4.0 起废弃,从 PHP 8.0.0 中移除):
 implode([array] $array, [string]: [string]
参数说明
separator可选。默认为空字符串。
array要使用字符串连接的数组。

返回值

返回一个包含所有数组元素并且顺序相同的字符串, 每个元素之间有 separator 分隔。

漏洞分析

首先在官方发布的 5.0.16 版本更新说明中,发现其中提到该版本包含了一个安全更新,我们可以查阅其 commit 记录,发现其修改的 Builder.php 文件代码比较可疑。大致可以猜到是对数据库的处理,对数据库的增减操作,通过将请求只拼接在一起。通过断点追代码查看分析漏洞。

对传递的username地方进行断点调试,下一步会直接跳转到数据库的连接函数。不用在意,继续走,

首先, payload 数据经过 ThinkPHP 内置方法的过滤后(不影响我们的 payload ),直接进入了 $this->builderinsert 方法,这里的 $this->builder\think\db\builder\Mysql 类。查看data内容是以数组形式储存传递内容。之后传递到parseExpress,但是最终SQL语句是在builder中执行的,所以直接跳过,不再追踪parseExpress。继续走,走到builder的insert方法中。

查看传入builder的insert方法的参数内容。

继续查看参数的内容。

过每次迭代将数组或对象中的一个元素赋值给指定的变量,直到遍历完所有元素为止。

  • $data:这是要遍历的数组或对象。

  • $key:这是当前元素的键(在数组中)或属性名(在对象中)。

  • $val:这是当前元素的值

Mysql 类继承于 Builder 类,即上面的 $this->builder->insert() 最终调用的是 Builder 类的 insert 方法。在 insert 方法中,我们看到其调用 parseData 方法来分析并处理数据,而 parseData 方法直接将来自用户的数据 $val 进行了拼接返回。我们的恶意数据存储在 $val[1] 中,虽经过了 parseKey 方法处理,当丝毫不受影响,因为该方法只是用来解析处理数据的,并不是清洗数据。准备开始写入内容,首先进行条件匹配。是否为插入内容。从代码中看得到是需要三个内容,第一个用来匹配条件。剩下两个进行拼接。如果一开始不写三个内容,在进行拼接的时候会报错。val[1]="updatexml(1,concat(0x7e,user(),0x7e),1)",进行字符串拼接。

经过函数处理之后返回内容为

拿出key和value

拼接SQL语句,进行两个函数拼接处理。动态生成SQL插入或替换语句,适用于需要根据不同条件生成不同SQL语句的场景,如数据导入、数据更新等,并且通过implode函数进行字符串的拼接。

上面,我们看到直接将用户数据进行拼接。然后再回到 Builder 类的 insert 方法,直接通过替换字符串的方式,将 $data 填充到 SQL 语句中,进而执行,造成 SQL注入漏洞

SQL语句构建

  • str_replace函数用于将模板中的占位符替换为实际的值。

  • 占位符包括%INSERT%%TABLE%%FIELD%%DATA%%COMMENT%

  • 根据布尔值$replace%INSERT%会被替换为REPLACEINSERT

  • %TABLE%会被替换为解析后的表名。

  • %FIELD%会被替换为逗号分隔的字段名字符串。

  • %DATA%会被替换为逗号分隔的字段值字符串。

  • %COMMENT%会被替换为解析后的注释。

最终执行我们定义好的SQL语句,从而爆出内容。

至此,我们已将整个漏洞分析完了。实际上,上面的 switch 结构中,3种情况返回的数据都有可能造成 SQL 注入漏洞,但是在观察 ThinkPHP 官方的修复代码中,发现其只对 incdec 进行了修复,而对于 exp 的情况并未处理,这是为什么呢?

实际上, exp 的情况早在传入 insert 方法前就被 ThinkPHP 内置过滤方法给处理了,如果数据中存在 exp ,则会被替换成 exp空格 ,这也是为什么 ThinkPHP 官方没有对 exp 的情况进行处理的原因了。具体内置过滤方法的代码如下:

漏洞修复

攻击总结

最后,再通过一张攻击流程图来回顾整个攻击过程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2049336.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Shell参考 - Linux Shell 训练营

出品方<Linux.cn & 阿里云开发者学堂> 一&#xff0c;Linux 可以划分为以下四个部分&#xff1a; 1. 应用软件 2. 窗口管理软件 Unity Gnome KDE 3. GNU 系统工具链 Software- GNU Project - Free Software Foundation 4. Linux 内核 二&#xff0c;什么是shell 1. L…

一款免费开源电脑流量监控软件,电脑流量统计工具!

TrafficMonitor是一个开源的网络速度监控工具&#xff0c;它能够在Windows平台上以悬浮窗的形式显示当前的网速、CPU和内存使用情况。该工具支持多种显示模式&#xff0c;包括悬浮窗和任务栏显示&#xff0c;并且允许用户更换不同的皮肤来自定义外观样式。此外&#xff0c;Traf…

【MySQL】数据库基础(库的操作)

目录 一、MySQL安装、连接、修改密码操作 二、库的操作 2.1 创建数据库 2.2 字符集和校验规则 2.3 操控数据库 2.4 修改数据库 2.5 删除数据库 2.6 数据库的备份和恢复 2.7 查看连接情况 前情提要&#xff1a; 我的服务器操作系统是Ubuntu20.04&#xff0c;安装的是M…

eNSP 华为远程访问路由器

华为远程访问路由器 前提&#xff1a;主机能与路由器通信就行&#xff0c;如果不同网段就配路由协议&#xff0c;这里直接模拟直连通信 Cloud&#xff1a; R&#xff1a; <Huawei>sys [Huawei]sys R [R]int g0/0/0 [R-GigabitEthernet0/0/0] [R-GigabitEthernet0/0/0]i…

Vue50 todolist自定义事件版本

代码 MyFooter.vue <template><div class"todo-footer" v-show"total"><label><!-- <input type"checkbox" :checked"isAll" change"checkAll"/> --><input type"checkbox" v…

【html】颜色随机产生器(补充包)

上一篇文章我们讲了如何制作一个通过滑动产色纯色背景的网页&#xff0c;今天&#xff0c;我们对那个网页进行一个补充&#xff0c;&#xff08;&#xff09; 因为很多人在设计网页的时候没有颜色的灵感这个时候我们我们就可以考虑通过随机产生一种颜色并且能够实时看到效果的…

Delphi5实现密码、姓名生成器

文章目录 目的效果图密码生成器类类定义成员函数 点击“密码生成”事件名字生成器类类的成员功能概述注意点 点击“姓名生成”事件点击“清空”事件“导出txt”事件“备注”输入框画图软件完整代码 目的 写这个程序的目的是生成一个密码和用于快递的名字&#xff08;生成密码和…

keepalived详细讲解

keepalived&#xff1a; Keepalived是一个基于VRRP&#xff08;‌Virtual Router Redundancy Protocol&#xff0c;‌虚拟路由冗余协议&#xff09;‌协议实现的LVS&#xff08;‌Linux Virtual Server&#xff09;‌服务高可用方案。‌它的主要作用是进行虚拟路由的故障切换&…

算法打卡 Day24(二叉树)-二叉搜索树的最近公共祖先 + 二叉搜索树中的插入操作 + 删除二叉搜索树中的节点

文章目录 Leetcode 235-二叉搜索树的最近公共祖先题目描述解题思路 Leetcode 701-二叉搜索树中的插入操作题目描述解题思路 Leetcode 450-删除二叉搜索树中的节点题目描述解题思路 Leetcode 235-二叉搜索树的最近公共祖先 题目描述 https://leetcode.cn/problems/lowest-comm…

江协科技STM32学习笔记(第10章 SPI通信)

第10章 SPI通信 10.1 SPI通信协议 10.1.1 SPI通信 SPI&#xff08;Serial Peripheral Interface&#xff09;是由Motorola公司开发的一种通用数据总线&#xff1b; 串行外设接口&#xff1b; I2C无论是软件还是软件电路&#xff0c;设计的都还是比较复杂的&#xff0c;硬件…

xss靶场详解

目录 1.第一题 2.第二题 3.第三题 4.第四题 5.第五题 6.第六题 7.第七题 8.第八题 1.第一题 在源码script标签里边&#xff0c;innerhtml是用于访问或修改 HTML 元素内的 HTML 内容的&#xff0c;这里是访问spaghet这个元素的&#xff0c;并通过括号里面的东西搜索当前…

【问题解决3】【已解决】Cannot determine path to‘tools.jar‘libraryfor17

前几天在IDEA运行JAVA项目时&#xff0c;出现这个报错。 这是因为是这个笔记本上安装的IDEA版本是“IntelliJ IDEA 2020.3.1”&#xff0c;与JDK17版本不兼容&#xff0c;这种情况下要想使得IDEA版本与JDK版本兼容&#xff0c;就需要升级IDEA版本或者使用JDK较低版本&#xff…

专题---自底向上的计算机网络(计算机网络相关概述)

目录 计算机网络相关概述 物理层 数据链路层 网络层 运输层 应用层 网络安全 1.计算机网络相关概述&#xff08;具体细节http://t.csdnimg.cn/NITAW&#xff09; 什么是计算机网络&#xff1f; 计算机网络是将一个分散的&#xff0c;具有独立功能的计算机系统&#x…

FusionSphere虚拟机网络不通

虚拟机侧 1、通过控制台Console或者VNC登录虚拟机。 获取VNC的token链接&#xff0c;因为token有超时失效&#xff0c;该链接获取后长时间不用要重新获取。 # nova get-vnc-console vmid novnc 2、登录VNC控制台之后&#xff0c;检查网卡和IP地址是否up, ARP学习是否正常…

Postman 问题汇总

1 postman Error: SSL Error: UNABLE_TO_VERIFY_LEAF_SIGNATURE 根因 SSL校验失败&#xff0c;可以在postman设置中关闭ssl校验&#xff0c;自测对ssl无要求。 解决方法 在postman设置中关闭ssl校验&#xff1a;

树莓派智能语音助手之聊天机器人-RASA

我的树莓派目前已经会“说”&#xff08;《树莓派智能语音助手之TTS - pyttsx3 espeak》&#xff09;&#xff0c;也能“听”&#xff08;《树莓派智能语音助手之ASR2 – sherpa-ncnn》&#xff09;了。接下来&#xff0c;就要让它能够和我们对话起来&#xff0c;即会“聊天”…

python 获取pdf文件中的超链接

pip install pymupdf pip install fitzimport fitz # PyMuPDFdef get_pdf_links(pdf_path):# 打开PDF文件document fitz.open(pdf_path)links []for page_num in range(len(document)):page document[page_num]# 获取当前页面的链接for link in page.get_links():links.app…

Mac升级系统文件都丢了怎么办?Mac更新后资料找不到了怎么恢复

Mac电脑由于其卓越的性能&#xff0c;受到了众多电脑用户的青睐。为了让用户获得更好的使用体验&#xff0c;Mac系统会定期推出新版本&#xff0c;来弥补前一个版本的不足。然而有用户反馈&#xff0c;Mac升级后&#xff0c;电脑里的部分资料消失了。mac升级会丢失文件吗?mac升…

iOS ColleCtionView 如何让cell 不重复创建并且只在展示的时候才创建

前言 使用 collectionView 一屏只展示一个 cell &#xff0c;一次只加载当前 cell&#xff0c;还要能够缓存已加载过的 cell &#xff0c;使 cell 不重复加载&#xff0c;听着好像就是将 collectionView 的复用机制禁用掉。用collectionView 实现这个需求&#xff0c;就出现了…

【GD32】从零开始学GD32单片机 | PMU电源管理单元+深度睡眠和待机例程(GD32F470ZGT6)

1. 简介 PMU电源管理单元通俗讲就是用来管理MCU的电源域的&#xff0c;它主要有两个功能——电压监测和低功耗管理。在GD32中一共有3个电源域——VDD/VDDA域、1.2V域和备份域。 VDD/VDDA域主要供PMU控制器、ADC、DAC等外设使用&#xff1b;1.2V域就是大部分外设都会使用的电源域…