java代码审计思维导图_代码审计-MetInfo 6.0.0 sql注入漏洞

首先漏洞存在于app\system\message\web\message.class.php文件中,变量{$_M[form][id]}直接拼接在SQL语句中,且验证码检测函数是在SQL语句查询之后,这也就造成了我们可以无视验证码检测函数,进行SQL注入。具体问题函数代码如下:

63b9280c89cbc6cdef1a93960fbf01be.png

$met_fd_ok=DB::get_one("select * from {$_M[table][config]} where lang ='{$_M[form][lang]}' and name= 'met_fd_ok' and columnid = {$_M[form][id]}");

这行中$_M[form][id]}没有被单引号保护拼接在sql语句中,存在安全隐患。我们跟跟踪这个变量看是否有过滤操作。

首先这个类的基类是web类

051f7e31b51e993fcdf2c9fbae79f73b.png

跟进web类,没有对用户传入的数据进行过滤等操作,却初始化了common类

df3f3d02709ca387e13548c9fe0bcf17.png

我们继续看看common类

fcac97766f11f1a62be6f4bfc56cc7f3.png

在common类初始化时调用了表单过滤的函数load_form()

此函数中又调用了过滤SQL注入的函数sqlinsert

4e83fbddc848198ae46f1bd89e2ead20.png

281609a850502e5b7e8c1b46d9a417cb.png

那我们来看看这个sqlinsert函数过滤了什么

20a10b6bd1695402b7aff5fb6f4c7cbd.png

可以看到sqlinsert函数对sleep关键字进行了处理,但是我们还是可以使用MYSQL中的benchmark函数轻松绕过。当然我们本文绕过的姿势不是用函数绕过这个函数,而是让代码不执行这个过滤的函数来达到绕过。

我们回到daddslashes函数里:

30d502c8d769e6d5763efe65b4ff35f1.png

daddslashes()定义在app/system/include/function/common.func.php第51行,对传递的参数进行addslashes()操作。这里注意,在else语句中,如果之前定义了IN_ADMIN常量,进行trim(addslashes(sqlinsert($string)))操作,反之则进行trim(addslashes($string))。

之前所述的安全隐患点为int型,所以addslashes()函数没有作用,所以这里主要是要绕过sqlinsert(),需要寻找到定义过IN_ADMIN常量的入口。

98dd545955317e904e2464fe4e266e88.png

这里通过搜索找到了admin/index.php,文件第5行定义了IN_ADMIN常量。接着看从admin/index.php入口文件如何调用add()函数的,index.php定义了4个常量,并且包含了app/system/entrance.php。

45140d69a4841ba8c5296aa8dc809e2c.png

进入app/system/entrance.php,38-44行,入口文件没有定义M_TYPE,这里会设置M_TYPE常量为system;54-59行,由于定义了M_TYPE为system,进行设置PATH_OWN_FILE常量为PATH_APP.M_TYPE.'/'. M_NAME.'/'.M_MODULE.'/',其中M_NAME、M_MODULE均可控。88-99行包含app/system/include/class/load.class.php,并调用了module()方法。

b62972424430b8371bca8563c04c6c49.png

dabe57edbe7c44128a3611a0b37777d5.png

由于调用module()方法时缺省了参数,因此$path、$modulename、$action均有之前定义的常量赋值,然后再调用_load_class()方法。_load_class()方法可以引用并实例化一个类,

a437210d8144fa0f0ffb97384ff4d420.png

241f098f54696b79edb4506652de912a.png

当action为空的时候,只引用文件。当action为new时候,会实例化这个类。当action为do开头时候,会实例化类,并执行这个方法。

那么到这里我们理一下条件:

要想包含app/system/message/web/message.class.php文件,需要满足

M_NAME = $_GET['n'] =message;

M_MODULE= $_GET['m'] =web;

M_CLASS= $_GET['c'] = message;

要想调用add(),必须实例化类并执行方法,但这里限定只能实例化并执行do开头的方法。这里找到了message.class.php中的domessage(),它调用了add()方法。

7e73f78cc9044c69e0a7faf09120d7cc.png

在调用add()方法前,需要满足$this->check_field();,这里发现只要抓取正常的留言参数填充就可以了,验证码的判断是在add()方法中执行完漏洞语句之后。

75c14e7c1758b26ecd602d33a72e4471.png

为了实现布尔注入而不是时间盲注,需要正常时$met_fd_ok的值不为空,从而绕过46行判断,弹出"验证码错误",而异常时$met_fd_ok值为空,弹出"反馈已关闭"。

在数据库中执行一下存在漏洞的SQL语句,看看符合条件的id参数有哪些,满足的columnid有42和44。

mysql> select * from met_config where name = 'met_fd_ok' and lang='cn';+-----+-----------+-------+--------------+----------+---------+------+

| id | name | value | mobile_value | columnid | flashid | lang |

+-----+-----------+-------+--------------+----------+---------+------+

| 470 | met_fd_ok | 1 | | 44 | 0 | cn |

| 490 | met_fd_ok | 1 | | 42 | 0 | cn |

+-----+-----------+-------+--------------+----------+---------+------+

最终可以构造如下GET请求注入,注入点为id:

admin/index.php?m=web&n=message&c=message&a=domessage&action=add&lang=cn¶137=1¶186=1@qq.com¶138=1¶139=1¶140=1&id=42 and 1=1

sqlmap.py -u "192.168.5.172/admin/index.php?m

=web&n=message&c=message&a=domessage&action=add&lang=cn¶137=1¶186=1@qq.com¶138=1¶139=1¶140=1&id=42"

d65dd9e11468ecbdaf3df16a4cab1163.png

最后附上一个思维导图,更好理解逻辑

d201c33e1366150b7195efa0c4f21558.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值