0x00 前言:

这篇是去年组内分享的时候给小伙伴写的0基础快速审计tp3系列的文章,主要是对架构做个分析以及审计一些sql注入漏洞~

现在想想打算放出来,过了一年了,可能里面有一些问题,望看到的大佬不吝指教

0x01 架构:

应用入口文件index.php:

if(version_compare(PHP_VERSION,'5.3.0','<'))  die('require PHP > 5.3.0 !');

// 开启调试模式 建议开发阶段开启 部署阶段注释或者设为false
define('APP_DEBUG',True); // 定义应用目录
define('APP_PATH','./Application/'); // 引入ThinkPHP入口文件
require './ThinkPHP/ThinkPHP.php'; app_debug为调试模式,开启app_debug可使thinkphp报错,方便调试和报错注入 thinkphp入口文件中可查看当前的框架版本 const THINK_VERSION = '3.2.3';

应用文件目录在Application(也可能不叫这个名字,在index.php定义应用目录),也就是开发者的应用都是写在这个文件夹里的,我们审计的部分也在这里。

mvc架构: mvc即模型,视图,控制器

Model(模型)是应用程序中用于处理应用程序数据逻辑的部分,通常模型对象负责在数据库中存取数据。

View(视图)是应用程序中处理数据显示的部分,通常视图是依据模型数据创建的。

Controller(控制器)是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

而这个架构中我们的重点又放在controller里面,因为参数的传递是否可控通常是决定是否存在漏洞的根本因素。还有一个原因则是目前很多cms有一个问题就是完全的弱化了model层,controller层不但做了数据的接收,也同样处理了数据逻辑,和数据库进行交互。

因此一般来说,我们拿到一套thinkphp框架的cms时,逻辑应该是:

1.在index.php中开启debug方便调试,确认应用目录。

2.确定应用前台模块。(application的下一个目录,通常是Home,还可能存在Api和Admin。那么重点是审计Home和Api这种前台模块,主要后台注入也没啥意思...)

3.审计controller目录中的所有控制器文件。

0x02 路由和传参

传参:

php中获取参数一般是,$_GET,$_POST等,框架中也可以使用这种方式传参数,但更多的是使用框架自定义的函数I函数

I方法是ThinkPHP用于更加方便和安全的获取系统输入变量,可以用于任何地方,用法格式如下:

I('变量类型.变量名/修饰符',['默认值'],['过滤方法'],['额外数据源'])

example:I('id','','intval');

这种用法是使用intval过滤id参数,这个id参数可以来自get,post,它会自动辨别。

除了这种获取参数的方法,Thinkphp还有一种获取参数的方法,叫做参数绑定

example:

namespace Home\Controller;
use Think\Controller;
class BlogController extends Controller{
public function read($id){
echo 'id='.$id;
}
}

使用路由http://serverName/index.php?c=Blog&a=read&id=5即是给$id传值为5

因此我们在查看是否存在可控参数时切不要忘记还有这种方式传参。

路由:

thinkphp使用URL_MODEL=2 ;这种方式来指定路由模式,1,2,3分别代表不同的路由模式 具体可参考http://document.thinkphp.cn/manual_3_2.html#url文档来查看,但依据我的经验,除了某些特殊情况,我们可以在搭好cms之后通过黑盒快速找到路由规则。

0x03 TP常见的sql注入

1.智障拼接导致的sql注入:

 public function show(){
$article=M('article');
$id=I('id');
$article->where('id='.$id)->setInc('views');
$data = $article->field('title,content,addtime,views')->find($id);
$data['content']=htmlspecialchars_decode($data['content']);
$this->ajaxReturn($data);
}
}

这段代码中,$id参数被直接拼接到where方法中的id字段,导致sql注入。 I函数默认的过滤方法是htmlspecialchars,对sql注入的防御是没有作用的。 而where方法只对数组形式的参数进行过滤 具体可参考官方文档的说明: https://www.kancloud.cn/manual/thinkphp/1844
因此此处可总结为:
如果参数获取时没有进行有效过滤又通过字符串拼接的方式带入where方法,则基本可断定存在sql注入。
补天会收的cms中目前已经很少存在这种智障写法了,但是非常非常小的cms里还是存在这种写法的。还有就是安服的同学们做代码审计很可能会遇到:)

2.不能预编译的地方未作控制导致的注入:
tp3.x系列对于这种不能预编译的语句的参数貌似没做什么处理...包括limit order filed table..etc 因为按理来说这些地方是应该写死的。。。 limit注入代码示例:

public function read(){
$Customer=M('Customer_abroad);
$start = $_GET['start'];
$limit = $_GET['limit'];
$data['total'] = $Customer->count();
$data['success'] = true;
$data['message'] = '读取数据';
$data['data'] = $Customer->order('id DESC')->limit($start,$limit)->select();
$this->ajaxReturn($data,'JSON');
}

limit方法即对应sql语句中的limit,这里是没办法预编译的,thinkphp也没有对此处有防御方法,因此如果这里的参数可控就会存在limit注入
代码来源:https://github.com/focalhot/FHCRM/blob/master/System/Lib/Action/CustomerAction.class.php(已经没了)

表名注入代码示例:

public function zan_collect()
{
$data = $this->request->param();
$id = $data['id'];
$uid = session('userid');
if (!session('userid') || !session('username')) { return json(array('code' => 0, 'msg' => '登录后才能操作'));
} else { //状态:
// 0 用户 1 帖子 2 评论
$zan_collect = $data['zan_collect']; $msgsubject = '';
$zan_collect == 'zan' ? $msgsubject = '点赞' : $msgsubject = '收藏';
$tablename = '';
$type = $data['type'];
switch ($type) {
case 1:
$tablename = 'forum'; break; case 2: $tablename = 'comment';
break; case 3: $tablename = 'article';
break; default:
$msgsubject = '关注';
$tablename = 'user';
break;
}
$zuid = $id;
if ($type != '0') {
$zuid = Db::name($tablename)->where('id', $id)->value('uid'); }
if ($zuid == $uid) {
return json(array('code' => 0, 'res' => '减', 'msg' => '不可以孤芳自赏哦')); } $insertdata['type'] = $type;
$insertdata['uid'] = $uid;
$insertdata['sid'] = $id; $n = Db::name($zan_collect)->where($insertdata)->find();

这段代码的最后一行Db::name($zan_collect),如果$zan_collect是可控的,那么此处就存在一个表名注入。 另外,除了Db::name()之外,thinkphp3.2.x还使用M方法和D方法实例表,因此如果此处的写法为M($zan_collect)或者D($zan_collect)也是一样的效果。

代码来源:laysns-v2.4

注:对于order by ,limit,和表名的注入,一般的防御方法时将此处的参数写死,或者使用switch case语句。

3.不知道该怪开发还是怪框架的问题

举个例子,3.x系列不用I函数而直接原生取值基本可以说凉凉... 这里就不细说了,太多了说起来费劲,可以看看先知某师傅写的文章https://xz.aliyun.com/t/2630

内容非常全面,我就不赘述了,放一个栗子大家可以练手

https://github.com/duiying/TP3-CMS

Thinkphp3分析与审计的更多相关文章

  1. [Abp vNext 源码分析] - 文章目录

    一.简要介绍 ABP vNext 是 ABP 框架作者所发起的新项目,截止目前 (2019 年 2 月 18 日) 已经拥有 1400 多个 Star,最新版本号为 v 0.16.0 ,但还属于预览版 ...

  2. Eventlog Analyzer日志管理系统、日志分析工具、日志服务器的功能及作用

    Eventlog Analyzer日志管理系统.日志分析工具.日志服务器的功能及作用 Eventlog Analyzer是用来分析和审计系统及事件日志的管理软件,能够对全网范围内的主机.服务器.网络设 ...

  3. IIS Web服务器日志、日志服务器分析

    IIS Web服务器日志.日志服务器分析 EventLog Analyzer是一款全面的工具,用于审计.管理和跟踪您的Microsoft Internet Information Services(I ...

  4. syslog系统日志、事件日志分析、EventLog Analyzer

    syslog系统日志.事件日志分析.EventLog Analyzer Eventlog Analyzer是用来分析和审计系统及事件日志的管理软件,能够对全网范围内的主机.服务器.网络设备.数据库以及 ...

  5. 【转】webshell检测——使用auditd进行system调用审计

    本文档将介绍:如何通过Linux审计系统auditd监测WebShell执行系统命令的行为. 测试环境:CentOS7.0_x64 auditd简介 Linux审计系统提供了一种跟踪系统上与安全相关的 ...

  6. [Abp vNext 源码分析] - 9. 接口参数的验证

    一.简要说明 ABP vNext 当中的审计模块早在 依赖注入与拦截器一文中有所提及,但没有详细的对其进行分析. 审计模块是 ABP vNext 框架的一个基本组件,它能够提供一些实用日志记录.不过这 ...

  7. [原题复现+审计][0CTF 2016] WEB piapiapia(反序列化、数组绕过)[改变序列化长度,导致反序列化漏洞]

    简介  原题复现:  考察知识点:反序列化.数组绕过  线上平台:https://buuoj.cn(北京联合大学公开的CTF平台) 榆林学院内可使用信安协会内部的CTF训练平台找到此题 漏洞学习 数组 ...

  8. Oracle的回收站和闪回查询机制(二)

    上一篇中讲诉了Oracle中一些闪回查询(Flashback Query),这是利用回滚段信息来恢复一个或一些表到以前的一个时间点(一个快照).要注意的是,Flashback Query仅仅是查询以前 ...

  9. 【转载】LinkedIn是如何优化Kafka的

    http://www.wtoutiao.com/p/18d5RY0.html 在LinkedIn的数据基础设施中,Kafka是核心支柱之一.来自LinkedIn的工程师曾经就Kafka写过一系列的专题 ...

随机推荐

  1. 命令提示符CMD下切换用户

    工作中遇到需要在windows环境中命令提示符下切换为Guest用户执行程序,类似Linux中的su操作. 操作步骤如下:1.用管理员权限运行cmd.2:执行命令:runas /user:userna ...

  2. 什么样的 SQL 不走索引

    参考: MySQL 索引优化全攻略 索引建立的规则 1.能创建唯一索引就创建唯一索引 2.为经常需要排序.分组和联合操作的字段建立索引 3.为常作为查询条件的字段建立索引 如果某个字段经常用来做查询条 ...

  3. Linux系统启动过程内核文件丢失解决方法

    一.问题描述 公司近期因机房断电,导致服务器重启后,引导进入不了操作系统.经过检查发现启动文件缺失,导致系统启动失败,网上搜了好多资料,解决都比较零散,现结合实际处理经验和网友的建议整理接方案. 二. ...

  4. POJ - 3665 icow

    Fatigued by the endless toils of farming, Farmer John has decided to try his hand in the MP3 player ...

  5. 手撕 part1

    1.宏定义三个数最大值 挺有意思 max((a), (b), (c)) (a) > (b)? ((a) > (c)? (a) : (c)) ((b) > (c)? (b) : (c) ...

  6. 2019牛客多校第四场B xor(线性基求交)题解

    题意: 传送门 给\(n\)个集合,每个集合有一些数.给出\(m\)个询问,再给出\(l\)和\(r\)和一个数\(v\),问你任意的\(i \in[l,r]\)的集合,能不能找出子集异或为\(v\) ...

  7. Taro Advanced

    Taro Advanced aro 代码与小程序代码混写 https://nervjs.github.io/taro/docs/hybrid.html https://github.com/NervJ ...

  8. Flutter使用WebSockets

    文档 注意是WebSockets而不是socket.io install dependencies: web_socket_channel: demo import 'dart:convert'; i ...

  9. Flutter NotificationListener 监听列表的滚动

    import 'package:flutter/material.dart'; import 'package:flutter_imagenetwork/flutter_imagenetwork.da ...

  10. 主打开放式金融的Baccarat项目如何开疆拓土?

    DeFi在这个夏天迎来了大爆发,像无托管交易.流动性挖矿.保险协议.NFT代币都在今年看到了有别于以往的应用.随着比特币走入主流,DeFi热度下降,不少人都觉得DeFi热潮已死.但事实是,DeFi的总 ...