#6.4 Prevent hijack of session Session hijack is a broader exist serious security threaten. Clients use session id to communicate with server, and we can easily to find out which is the session id when we track the communications, and used by attackers.
In the section, we are going to show you how to hijack session in order to help you understand more about session.
##Session hijack process
The following code is a counter for count
variable:
func count(w http.ResponseWriter, r *http.Request) {
sess := globalSessions.SessionStart(w, r)
ct := sess.Get("countnum")
if ct == nil {
sess.Set("countnum", 1)
} else {
sess.Set("countnum", (ct.(int) + 1))
}
t, _ := template.ParseFiles("count.gtpl")
w.Header().Set("Content-Type", "text/html")
t.Execute(w, sess.Get("countnum"))
}
The content of count.gtpl
as follows:
Hi. Now count:{{.}}
Then we can see following content in the browser:
Figure 6.4 count in browser.
Keep refreshing until the number becomes 6, and we open the cookies manager (I use chrome here), you should see following information:
Figure 6.5 cookies that saved in browser.
This step is very important: open another browser (I use firefox here), copy URL to new browser, and open cookie simulator to crate a new cookie, input exactly the same value of cookie we saw.
Figure 6.6 Simulate cookie.
Refresh page, and you'll see:
Figure 6.7 hijack session succeed.
Here we see that we can hijack session between different browsers, and same thing will happen in different computers. If you click firefox and chrome in turn, you'll see they actually modify the same counter. Because HTTP is stateless, so there is no way to know the session id from firefox is simulated, and chrome is not able to know its session id has been hijacked.
##prevent session hijack ###cookie only and token Through the simple example of session hijack, you should know that it's very dangerous because attackers can do whatever they want. So how can we prevent session hijack?
The first step is to set session id only in cookie, instead of in URL rewrite, and set httponly property of cookie to true to restrict client script to access the session id. So the cookie cannot be accessed by XSS and it's not as easy as we showed to get session id in cookie manager.
The second step is to add token in every request, like we deal with repeat form in previous sections, we add a hidden field that contains token, and verify this token to prove that the request is unique.
h := md5.New()
salt:="astaxie%^7&8888"
io.WriteString(h,salt+time.Now().String())
token:=fmt.Sprintf("%x",h.Sum(nil))
if r.Form["token"]!=token{
// ask to log in
}
sess.Set("token",token)
###Session id timeout Another solution is to add a create time for every session, and we delete the session id when it's expired and create a new one. This can prevent session hijack at some point.
createtime := sess.Get("createtime")
if createtime == nil {
sess.Set("createtime", time.Now().Unix())
} else if (createtime.(int64) + 60) < (time.Now().Unix()) {
globalSessions.SessionDestroy(w, r)
sess = globalSessions.SessionStart(w, r)
}
We set a value to save the create time and check if it's expired(I set 60 seconds here), this step can avoid many of session hijack.
Combine those two solutions, you can avoid most of session hijack in your web applications. In the one hand, session id changes frequently and attacker always get expired and useless session id; in the other hand, we set session id can only be passed through cookie and the cookies is httponly, so all attacks based on URL are not working. Finally, we set MaxAge=0 which means session id will not be saved in history in browsers.
##Links
- Directory
- Previous section: Session storage
- Next section: Summary