我有一个服务器,它具有返回用户注册日期的功能。任何用户都可以看到任何非隐藏用户(在这个例子中只有 user2 是隐藏的)。服务器dateRequest
从客户端获取 a 并使用id
from 在用户文件中查找相应用户的日期:
package main
import (
"bytes"
"fmt"
)
const datelen = 10
//format: `name 0xfe date age 0xfd password`; each user is seperated by 0xff
var userfile = []byte("admin\xfe2014-01-0140\xfdadminpassword\xffuser1\xfe2014-03-0423\xfduser1password\xffuser2\xfe2014-09-2736\xfduser2password")
func main() {
c := clientInfo{0, 0, 0}
fmt.Println(string(getDate(dateRequest{c, user{0, "admin"}})))
fmt.Println(string(getDate(dateRequest{c, user{0, "admin______________"}})))
fmt.Println(string(getDate(dateRequest{c, user{1, "user1"}})))
//fmt.Println(string(getDate(dateRequest{c,user{2,"user2"}}))) // panic
fmt.Println(string(getDate(dateRequest{c, user{1, "user1_________________________________________________"}})))
}
func getDate(r dateRequest) []byte {
if r.id == 2 {
panic("hidden user")
}
user := bytes.Split(userfile, []byte{0xff})[r.id]
publicSection := bytes.Split(user, []byte{0xfd})[0]
return publicSection[len(r.username)+1 : len(r.username)+1+datelen]
}
type dateRequest struct {
clientInfo
user
}
type clientInfo struct {
reqTime uint64
ip uint32
ver uint32
}
type user struct {
id int
username string
}
$ go run a.go
2014-01-01
dminpasswo
2014-03-04
r2password
如您所见,它可以正常接收用户的日期,但如果请求的用户名上有额外的字节,则会返回部分用户密码。不仅如此,如果你继续添加更多字节,它会从 user2 返回数据,这应该是隐藏的。为什么?
执行main
第三行代码时,user
输publicSection
入的getData
是“admin�2014-01-0140�adminpassword”和“admin�2014-01-0140”。但随后它返回“dminpasswo”。切片publicSection
(“admin�2014-01-0140”)如何返回“dminpasswo”?这看起来像是一个缓冲区溢出问题,但这不应该发生,因为 Go 是内存安全的。publicSection
我什至尝试通过print 读取缓冲区publicSection[len(publicSection)]
,但它如预期的那样恐慌。
我也尝试用 替换所有的[]byte
,string
并且由于某种原因解决了这个问题。