• Thinkphp 3.2.3 parseWhere设计缺陷导致update/delete注入 分析


    分析

    首先看一下控制器,功能是根据用户传来的id,修改对应用户的密码。

    13行把用户传来的id参数送入where()作为SQL语句中的WHERE语句,将pwd参数送入save()作为UPDATE语句。
    这里我们假设请求id参数为array("bind","aaa"),pwd参数为bbb。

    其中11行12行的意思是获取id、pwd参数,并通过I函数进行过滤。我们跟进一下I()

    可以看到,这里首先对参数进行htmlspecialchars过滤,然后在最后调用think_filter()函数进行过滤,跟进一下这个函数

    可以看到,这里通过匹配参数中的一些关键字,并在其后加上空格。
    到这里I函数就结束了。

    回到控制器继续往下走,首先进入where()

    可以看到由于$where是数组、$parser是null,所以三个if都不满足,直接到1813行,接下来就是将$this->options['where']与$where拼接到一起,用于最终拼凑成一条完整的SQL语句。

    继续跟进就到save函数了。

    由于$data非空,到409行。这里主要对比$data与数据库中的表中的各个字段的数据类型是否一致,如果不一致则会进行一些强制转换或是直接报错【TODO】。
    然后到416行调用了_parseOptions(),这里用于解析出表名、where中的字段名等【TODO】。

    下面直接跳到最后,调用update函数准备执行SQL语句

    跟进update,直接进入899行

    跟进parseWhere

    其中在536行调用了parseWhereItem,跟进

    可以看到,这里直接拼接了$key和$val[1]到$whereStr中

    最后可以看到,$whereStr="`id` = :aaa",其中aaa就是我们一开始传入的id=array('bind', 'aaa')数组中的第二项。由于后来直接被拼接到SQL语句中,因此这个里存在注入。

    http://127.0.0.1/thinkphp/thinkphp_3.2.3_full/index.php/home/index/sqli1?id[0]=bind&id[1]=0%20and%20(updatexml(1,concat(0x7e,user(),0x7e),1))&pwd=bbb
    

    总结

    本质原因是框架处理pdo时,将用户可控的字符串作为了占位符,导致sql注入在预处理之前就已经形成了,而所谓的过滤bind只是治标不治本而已(没做过开发,也有可能这本来就是一种写法?)。也有可能就是本来入口也就不多吧【TODO】。

    哎,好菜。
    01点46分

  • 相关阅读:
    让用户打开你app的位置功能
    函数递归与栈的关系
    公务员考试
    毕达哥拉斯的故事
    OC5_NSMutableString操作
    OC4_NSString操作
    OC_NSString
    OC3_MyRect
    OC6_类方法
    OC5_构造方法与self指针
  • 原文地址:https://www.cnblogs.com/litlife/p/11273647.html
Copyright © 2020-2023  润新知