onethink漏洞【通过】

1. 搭建好onethink平台

2. 通过phpstorm查看下源码

可以发现使用的是thinkphp3.2,由此可见thinkphp版本相对比较老,所以可以直接审计thinkphp核心代码。

3. 函数追踪审计

直接查看下后台登陆功能,burp抓包如下:

image

根据路由s=/admin/public/login.html,可以看到调用了admin目录下的public控制器。

注释掉验证码,直接burp跟进$uid = $User->login($username, $password);

注意到调用了UcenterMemberModel.class.php中的login方法,看到截图断点,跟进断点where方法。

查看上面注意到如果$where是数组,将会被直接赋值给$this->option[‘where’]。继续跟进find方法。

image

断点处有对$options进行赋值和验证操作,方法如下,这里可以注意到表达式过滤的方法默认为空。

image

所以之前的$where的值可以没有过滤的赋值给$options。

如上继续跟进$this->db->select($options)方法。

跟进buildSelectSql方法,此时的获取到的$sql就是我们最终要执行的sql语句。

具体可以跟进$this->query方法如下所示:

不存在任何过滤。也就是说我们能够成功构造$sql语句就能够最终获取到我们想要的数据。回到buildSelectSql,重点关注蓝圈中的方法。

继续跟进。

也就是说将$sql中的值进行了替换,换成options数组中对应的数据。重点关注parseWhere函数,这个是我们这次传参可以控制的,跟进。

可以看到会进入到foreach循环,看下foreach中的代码,发现对key进行安全检测,根据传过来的参数可以知道key为username。根据逻辑如果key正常,将会进入parseWhereItem(460行),跟进。

如上代码可以看到,其中btween和in的正则处理方式,并不存在^$,所以我们此处可以构造payload来实现注入。

如果想要登录后台,我们可以根据上面的分析构造指定的用户名密码来实现登录。

这里查看下登录代码。

通过用户名查询获取用户密码,判断密码加密后是否等于数据库获取到的密码,成功则登录成功,不过因为salt是随机生成的,我们无法解密,所以不好注入构造密码。

查看加密算法。

image

发现当str为空的时候,返回空。故可以用union select来达到指定password为’’。

  1. payload构造。
username[]=like 1)and 1 in (2) union select 1,2,'',4,5,6,7,8,9,10,11%23&username[]=0&password=&verify=yzm

成功绕过登录管理员用户。

  • 通过
  • 未通过

0 投票者

1 个赞