热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ThinkPHP之SQLI审计分析(三)

说明该文章来源于徒弟lu2ker转载至此处,更多文章可参考:https:github.comlu2ker文章目录说明0x00测试代码做了什么0x01分


说明

该文章来源于徒弟lu2ker转载至此处,更多文章可参考:https://github.com/lu2ker/



文章目录


  • 说明
      • 0x00 测试代码做了什么
      • 0x01 分析调用链
      • 0x03 总结






Time:9-23

影响版本:ThinkPHP=5.1.22

Payload:

/public/index.php/index/index?orderby[id`|updatexml(1,concat(0x7,user(),0x7e),1)%23]=1

这是一篇由已知漏洞寻找利用过程的文章,跟着**参考链接**学习分析。以下是收获记录。

感谢七月火的高质量文章。




0x00 测试代码做了什么


namespace app\index\controller;
class Index
{
public function index()
{
$orderby = request()->get('orderby');
$result = db('users')->where(['username' => 'mochazz'])->order($orderby)->find();
var_dump($result);
}
}

以GET方式从orderby中获取参数值,查询users表中username=mochazz,再用order方法添加排序语句最后find获取结果。

request类是在thinkphp/library/think/Request.php中定义的,其get方法:

在这里插入图片描述

并没有什么比较关键的东西,之前在研究(username/a)a是什么意思时,对getinput方法的调用处理流程也分析过,最终的过滤代码是在thinkphp/library/think/Request.php1408行filterValue函数,但是由于仅仅是一个框架,并没有添加自定义的过滤器进行过滤。所以这边基本上是传入什么值就获取什么值。未来如果没有特殊情况就不用分析测试代码的作用了。


0x01 分析调用链


  • where()方法

emm,这个版本的parseWhereExp方法与之前分析过的5.0.10版本的不太一样,所以还是学习一下吧。

在这里插入图片描述

1474-1477行像是修了个小BUG的样子,之所以会这么想是因为getOptions方法是这么写的:

在这里插入图片描述

总的来说感觉大概是防止为空时出错吧。不重要。

但有了5.0.10版本分析的经验,知道parseWhereExp方法中主要看的是if-else语句块。这段代码如下:

在这里插入图片描述

因为$field是一个数组($field就是测试代码中where中的参数值)所以直接跳到1495行看起,进入parseArrayWhereItems方法。并且,在parseArrayWhereItems处理完后就会直接return了。

在这里插入图片描述

1564行if条件满足,foreach拆分usernamemochazz,之后会进入1571行的else中对$where数组进行赋值,这里三元运算因为mochazz不是数组,所以第二个元素最终为’=',然后到1580行的if,也是简单的取值赋值操作。

where方法分析完毕,好像也没什么不同。区别在于5.0.10中没有看parseArrayWhereItems方法,这次补上了。下断点看一下处理后的最终结果:

在这里插入图片描述


  • order()方法,本次的主角

thinkphp/library/think/db/Query.php1823-1864行,因为测试代码给定参数的特殊性,程序不会进入部分代码,也为了舍去不必要的篇幅,直接来到1853行开始看起:

在这里插入图片描述

1854行,既然whereoptions中是个数组,那么orderoptions也应是个数组,很合理。

1857行,判断为数组,之后也是用array_merge进行简单的赋值操作。还是下断点看看执行完的情况:

在这里插入图片描述

自始至终没有任何有效的过滤存在意味着whereorder值都是可控的。但是具体怎么触发漏洞还是没有个清晰的逻辑,往后看find的执行流程吧。

。。。

实际上,也没什么看头,基本上是在解析$this->options中的值,然后在3041行调用另一处的find方法,而后执行的代码与前几次分析SQLI漏洞的流程基本一致。em先下个断点看一下SQL语句构造完成后是什么:
最终在thinkphp/library/think/db/Connection.phpfind方法的826行生成的SQL语句。

在这里插入图片描述

明显可以看到是通过反引号闭合id前一个反引号导致的注入攻击。

既然是order by之后的注入,那么漏洞点一定和select方法中调用的parseOrder这个方法有关系:

有了以往的经验,知道具体代码都在thinkphp/library/think/db/Builder.php中,来到847行parseOrder

在这里插入图片描述

阅读855-871行,暂时不看程序不会进入的代码直接来到最后一个else,863-869都没有什么特殊的地方,870会把$sort置为空,871行parseKey方法很关键,跟进。

在这里插入图片描述

它的作用是获取key的值。但是下断点步进发现,调用的实际上不是Builder.php中的parseKey而是Mysql.php中的parseKey,是因为自始至终Mysql都是extends于Builder的,前面一直在Builder中分析代码是因为Mysql中没有写相应的函数,自然就向父类查找了,但是与以往不同的是,parseKey是在Mysql中定义好的。(涨记性,有经验了也得根据实际情况来。)

来到实际执行的parseKey:

thinkphp/library/think/db/builder/Mysql.php113行:

在这里插入图片描述

在这里插入图片描述

已知的payload并不满足123行的if,直接会到143行处的if,因为$strict是写死的true,这个if必然会进入,然后执行的操作是往$key的两边直接拼接加反引号,这个时候想到payload的形式,毫无疑问漏洞点就在这里。

最后,将return的$key拼接上$sort,再在parseOrder中的875行拼接前缀ORDER BY,SQL注入就构造好了。


0x03 总结

这次分析并没有那么细,也没有想太多,只是根据payload和测试代码的流程过了一遍。并不是严格意义上的白盒审计,很多程序没有进入的代码并没有认真去分析,不知道其他代码做了什么就很可能还存在漏洞点。还是一样的感觉:目前所学习的代码审计就是一个跳过某段代码和进入某段代码的过程,也就是所谓的“链”。至于绕过过滤这些,感觉不是代码审计的重点,只能算是一种奇巧的思路吧。

加油。







推荐阅读
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 本文介绍了使用postman进行接口测试的方法,以测试用户管理模块为例。首先需要下载并安装postman,然后创建基本的请求并填写用户名密码进行登录测试。接下来可以进行用户查询和新增的测试。在新增时,可以进行异常测试,包括用户名超长和输入特殊字符的情况。通过测试发现后台没有对参数长度和特殊字符进行检查和过滤。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 本文讨论了如何在codeigniter中识别来自angularjs的请求,并提供了两种方法的代码示例。作者尝试了$this->input->is_ajax_request()和自定义函数is_ajax(),但都没有成功。最后,作者展示了一个ajax请求的示例代码。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
author-avatar
情感顾问世界
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有