Funny_go
2023-07-23 04:20:36

源码自行下载

回过头再看一下代码

有用的地方就是 SubmitMoveHandler

直接去 move 打

其他都是废话

gorm 和 gin 框架

5 个路由

1
2
3
4
5
router.GET("/user", UserHandler)		//用户登录信息
router.POST("/login", LoginHandler) //对比数据库用户信息登录
router.POST("/upload", cookieCheckMiddleware(), UploadHandler) //文件上传(需登录)
router.POST("/move", IpSecurityCheck(), SubmitMoveHandler) //移动文件(判断IP)
router.POST("/download", cookieCheckMiddleware(), DownloadHandler) //下载文件(需登录)

首先从代码上两个比较明显的点

1、IpSecurityCheck

1
2
3
4
5
6
7
8
9
func IpSecurityCheck() gin.HandlerFunc {
return func(c *gin.Context) {
if c.Request.RemoteAddr[:9] != "127.0.0.1" && c.Request.RemoteAddr[:9] != "localhost" {
c.JSON(403, gin.H{"msg": "No you'are not allowed"})
return
}
c.Next()
}
}

2、SubmitMoveHandler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func SubmitMoveHandler(c *gin.Context) {
var filename Filename
if err := c.ShouldBindJSON(&filename); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

cmd := exec.Command("/bin/bash", "-c", "mv ./upload/pdf/"+filename.Filename+" ./assert/pdf/")
if err := cmd.Run(); err != nil {
fmt.Println(err)
return
}
c.JSON(http.StatusOK, gin.H{"message": filename.Filename})
}

很明显的 SSRF 和命令注入

那么再来看下前置步骤

首先是 struct 进行查询时,gorm 只会查询非零字段,若值为 0,false,’' 或其他零值

gorm 会忽略 where 条件

image-20230723033803704

image-20230723033823276

得到 username 和 password

进行登录

image-20230723033947090

image-20230723040521720

image-20230723034517349

--------------------------9a28df6f0f9a180f Content-Disposition: form-data; name=“xx”; filename=“flag” Content-Type: application/octet-stream flag{ki10Moc_W0nt_31eep} --------------------------9a28df6f0f9a180f–

但其实这题代码写的有问题

5 个路由只需要 move 即可

因为 move 没有身份验证

可以直接打

单纯的命令注入

突然看到有命令执行!

攻击队上班了?

乐,复现题目被态势感知记录了

image-20230723012127208