Dog*_*Dog 1 security buffer-overrun go
我有一个服务器,它具有返回用户注册日期的功能.任何用户都可以看到任何非隐藏用户(在此示例中,只隐藏了user2).服务器dateRequest从客户端获取a 并使用id它来在用户文件中查找相应用户的日期:
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
}
Run Code Online (Sandbox Code Playgroud)
$ go run a.go
2014-01-01
dminpasswo
2014-03-04
r2password
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它可以正常接收用户的日期,但如果请求在用户名上有额外的字节,则会返回部分用户密码.不仅如此,如果你继续添加更多字节,它将从user2返回数据,这应该是隐藏的.为什么?
当执行main的代码第三行,user并且publicSection在getData是'admin2014-01-0140adminpassword’和'admin2014-01-0140’.但后来它返回"dminpasswo".切片publicSection("admin 2014-01-0140")如何返回"dminpasswo"?它看起来像是一个缓冲区溢出问题,但这不应该发生,因为Go是内存安全的.我甚至尝试publicSection通过打印读取缓冲区publicSection[len(publicSection)],但它像预期的那样恐慌.
我也试过更换所有的[]byte用string,而修复该问题的某些原因.
切片表达式检查上部索引的边界与切片容量,而不仅仅是切片的长度.实际上,您可以切片超过切片的长度.但是,您不能在基础数组的边界之外切片以访问未初始化的内存.
http://play.golang.org/p/oIxXLG-YEV
s := make([]int, 5, 10)
copy(s, []int{1, 2, 3, 4, 5})
fmt.Printf("len:%d cap:%d\n", len(s), cap(s))
// > len:5 cap:10
fmt.Printf("raw slice: %+v\n", s)
// > raw slice: [1 2 3 4 5]
fmt.Printf("sliced past length: %+v\n", s[:10])
// > sliced past length: [1 2 3 4 5 0 0 0 0 0]
// panics
_ = s[:11]
// > panic: runtime error: slice bounds out of range
Run Code Online (Sandbox Code Playgroud)
如果你真的想要防止切片超过数组的长度,在go1.3或更高版本中你可以在切片时将容量设置为第三个参数.
// set the capacity to 5
s := s[:5:5]
// now this will panic
_ = s[:6]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
310 次 |
| 最近记录: |