本文由红日安全成员: licong 编写,如有不当,还望斧正。
前言优客365网站分类导航系统是个跨平台的开源软件,基于php+mysql开发构建的开源网站分类目录管理系统,具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大、专业的分类目录或网址导航网站。
目录结构│ .htaccess
│ AdminYouke365.php 后台管理页面
│ config.php 全局配置文件
│ index.php 网站主页
├─app 应用目录
├─data 应用运行时目录
├─install 应用安装目录
├─mobile 手机模块
├─public WEB资源目录
├─theme 应用皮肤资源目录
├─themes 应用皮肤资源目录
├─uploads 文件上传存放目录
├─vendor 第三方类库目录
代码执行流程分析对程序目录结构确定以后,便于我们更好的定位代码,接下来看一下代码的执行流程,在index.php代码26行下断点,点击搜索,程序成功断下,F7跟进:
进入到\core\start.php文件中,在代码85行出现 $_module 和 $_controller 变量,跟进一下Router类的init方法,用传入的 $config 变量中的值对类中变量进行了初始化,该值不可控。无法利用。
接下来调用了Router类的url方法,未跟进函数执行, $param 返回值如下:
通过$param变量中的值发现,该方法将url中的参数进行了处理,数组$param中module,controller不为空,则赋值到 $_module , $_controller 变量中,然后定义成了常量 __MODULE__ , __CONTROLLER__ ,在程序217行,进行字符串拼接并包含该文件。继续跟踪被包含文件:
得到文件路径: app\home\controller\search.php
url: http://127.0.0.1/home/search.html?mod=search&type=name&query=sdfd
对比一下两个地址,猜测,第一个/后的位置代表了app文件夹中的子目录,第二个/后地址代表所要请求的php文件,将html更换成php。mod参数在该文件没有体现。由此我们确定了程序如何传参,在我们找到漏洞存在页面以后,便知道如果构造相应的参数才能到达该页面。
代码审计 SQL注入 漏洞分析app\home\controller\feedback.php
猜测I函数对用户输入进行处理,跟进一下:
函数参数$filters未设置的情况,默认使用htmlspecialchars函数对传入参数进行了处理。接下来我们看一下W3Cschool对该函数的说明:
以下是PHP手册中对预定义字符的说明:
对该函数的详细说明可参考PHP手册:
http://php.net/manual/zh/function.htmlspecialchars.phpI函数在调用htmlspecialchars函数对传入参数进行处理时,并未设置flags参数,单引号未进行编码,猜想可能存在SQL注入。
在代码32行,判断 $fb_nick 是否为空, $fb_email 进行了邮箱验证,可跟进一下验证部分,看看是否存在绕过,代码44行,判断 $fb_content 是否为空然后进行长度判断,不能小于20字符,然后将数据进行了insert操作,猜测存在sql注入漏洞。
漏洞验证在传入参数位置下断点,跟进$Db->insert方法:
从执行的sql语句观察到单引号未过滤,证明SQL注入存在。
漏洞利用:该cms屏蔽了报错信息,且插入的内容需要管理员才能查看,利用有限,大佬们有啥思路可交流一下。
数据库执行语句如下:
INSERT INTO yk365_feedback ( fb_nick , fb_email , fb_content , fb_date ) VALUES ('123','123@qq.com','1231231231223123123123123123122222222222222222222222222222222222222222222222222222','1534056939')
如未屏蔽数据库报错信息,可采用以下payload进行报错注入:
fb_nick = 123','123','123' or extractvalue(1,concat(0x7e,database()))) #
在数据库执行语句后,可报错得到数据内容。
INSERT INTO yk365_feedback (fb_nick,fb_email,fb_content,fb_date) VALUES ('123','123','123' or extractvalue(1,concat(0x7e,database())))#,'123@qq.com','1231231231223123123123123123122222222222222222222222222222222222222222222222222222','1534056939')
SQL注入2 漏洞分析
\member\controller\article.php
感觉他少打了一个post,$art_content使用addslashes函数过滤,cate_id参数转换为int,无法利用,可利用参数 $art_title , $copy_from , $copy_url ,继续往下跟踪代码:
代码105行,对 $art_title 进行了过滤,跟进censor_words函数:
先判断 $keywords 和 $content 是否为空,如果为空,直接返回true,不为空,则将 $keywords 中的内容以','作为分割符,存储到变量$wordarr中,然后在$content中进行正则匹配,如果存在关键字中的内容,则返回false。发现keywords部分内容与安全过滤无关,所以 $art_title 变量也可以利用。继续往下跟代码:
这 $copy_from , $copy_url 没任何处理,然后直接进行了insert操作,猜测存在SQL注入漏洞,该测试需要注册账号。
漏洞验证在会员中心进行文章添加时,一直报错,动态调试发现在代码96行,对$cate_id进行了判断,采用burp抓包发现,该参数为出现在请求参数中,于是在burp中添加了该参数。然后发送请求。
在标题字段输入 art_title=121' or sleep(5)# 后页面 延迟返回,证明SQL注入存在。下面insert也存在注入,不测试了。
漏洞利用将burp抓包内容放入txt文档,执行 sqlmap.py -r 6.txt --dbms=mysql
SQL注入3 漏洞分析/member/controller/login.php
$nick_name 转义无法利用, $pass , $open_id 可利用,接下来,通过用户名查询到密码,并与输入密码的MD5值进行比较。由此 $pass 变量我们也无法利用。继续往下:
程序一直未对 $open_id 变量进行处理,直接传入到了update函数,猜测存在SQL注入漏洞。
漏洞验证使用burp抓包并手动加上open_id参数,进入update函数,发现执行的SQL语句中,单引号未过滤,证明SQL注入存在。
漏洞利用 $strSql = "UPDATE `$table` SET $strSql WHERE $where";
$strSql = login_time ='1534054455', login_ip ='2130706433', login_count ='11', open_id ='123''
在yk365_users表 user_type 字段中,标识了该用户的身份,如果能够更改该值,则可获取到管理员权限。
于是尝试构造 open_id = 123',user_type='admin'# , user_type字段更改成功,并能通过该账户进入管理员后台。
结语
在seebug上看到该cms 1.0.7版本存在SQL注入,抱着玩的心态下载了最新版。如果该CMS全局默认使用addslashes函数进行转义,就没SQL注入了。开发人员对htmlspecialchars函数的使用不正确,导致了众多SQL注入点出现,还有可以利用的地方。感兴趣的可以下载玩玩。审计新手,有问题大家多交流。后面还有一篇getshell,中间踩了很多坑,想单独写一篇。