[ja] Translate 06.4.md into Japanese.

This commit is contained in:
Shin Kojima
2013-06-13 23:50:11 +09:00
parent ef10e3613f
commit d896d073da

90
ja/ebook/06.4.md Normal file
View File

@@ -0,0 +1,90 @@
# 6.4 sessionハイジャックの予防
sessionハイジャックは広範囲に存在する比較的重大な脆弱性です。session技術において、クライアントサイドとサーバサイドはsessionのIDによってセッションを維持します。しかしこのIDは簡単にスニッフィングされ、第三者に利用されてしまいます。これは中間者攻撃の一種です。
本章ではセッションハイジャックの実例をお見せします。この実例を通して、読者がよりsessionの本質への理解を深めていただけることを願っています。
## sessionハイジャックの過程
下のようなcountカウンターを書きます
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"))
}
count.gtplのコードは以下の通り
Hi. Now count:{{.}}
ブラウザ上でリロードを行うと以下のような内容が確認できます:
![](images/6.4.hijack.png?raw=true)
図6.4 ブラウザでcount数を表示
リロードによって、数字は際限なく増加します。数字が6を示した時ブラウザここではchromeを例にとりますのcookieマネージャを開くと、以下のような情報を見ることができます
![](images/6.4.cookie.png?raw=true)
図6.5 ブラウザが保存しているcookieを取得
次のステップが重要です:別のブラウザ(ここではfirefoxブラウザを開きました)を開き、chromeのアドレスバーのアドレスを新たに開いたブラウザのアドレスバーにコピーします。その後firefoxのcookieエミュレートプラグインを開き、新規にcookieを作成します。上の図のcookieの内容をそのままfirefoxの中に再設定します
![](images/6.4.setcookie.png?raw=true)
図6.6 cookieをエミュレート
エンターキーを押すと、下のような内容が現れます:
![](images/6.4.hijacksuccess.png?raw=true)
図6.7 sessionのハイジャックに成功
可以看到虽然换了浏览器但是我们却获得了sessionID然后模拟了cookie存储的过程。这个例子是在同一台计算机上做的不过即使换用两台来做其结果仍然一样。此时如果交替点击两个浏览器里的链接你会发现它们其实操纵的是同一个计数器。不必惊讶此处firefox盗用了chrome和goserver之间的维持会话的钥匙即gosessionid这是一种类型的"会话劫持"。在goserver看来它从http请求中得到了一个gosessionid由于HTTP协议的无状态性它无法得知这个gosessionid是从chrome那里"劫持"来的它依然会去查找对应的session并执行相关计算。与此同时 chrome也无法得知自己保持的会话已经被"劫持"。
ブラウザを変えても、sessionIDを取得することができました。この後cookieの保存過程をエミュレートします。この例は一台のコンピュータの上で行ったものです。たとえ二台によって行ったとしても結果は同じです。この時もし交代でつのブラウザのリンクをクリックした場合、操作しているカウンターが実は同じものであるということに気づくでしょう。驚くことはありません。
## session劫持防范
### cookieonly和token
通过上面session劫持的简单演示可以了解到session一旦被其他人劫持就非常危险劫持者可以假装成被劫持者进行很多非法操作。那么如何有效的防止session劫持呢
其中一个解决方案就是sessionID的值只允许cookie设置而不是通过URL重置方式设置同时设置cookie的httponly为true,这个属性是设置是否可通过客户端脚本访问这个设置的cookie第一这个可以防止这个cookie被XSS读取从而引起session劫持第二cookie设置不会像URL重置方式那么容易获取sessionID。
第二步就是在每个请求里面加上token实现类似前面章节里面讲的防止form重复递交类似的功能我们在每个请求里面加上一个隐藏的token然后每次验证这个token从而保证用户的请求都是唯一性。
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{
//提示登录
}
sess.Set("token",token)
### 间隔生成新的SID
还有一个解决方案就是我们给session额外设置一个创建时间的值一旦过了一定的时间我们销毁这个sessionID重新生成新的session这样可以一定程度上防止session劫持的问题。
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)
}
session启动后我们设置了一个值用于记录生成sessionID的时间。通过判断每次请求是否过期(这里设置了60秒)定期生成新的ID这样使得攻击者获取有效sessionID的机会大大降低。
上面两个手段的组合可以在实践中消除session劫持的风险一方面 由于sessionID频繁改变使攻击者难有机会获取有效的sessionID另一方面因为sessionID只能在cookie中传递然后设置了httponly所以基于URL攻击的可能性为零同时被XSS获取sessionID也不可能。最后由于我们还设置了MaxAge=0这样就相当于session cookie不会留在浏览器的历史记录里面。
## links
* [目录](<preface.md>)
* 上一节: [session存储](<06.3.md>)
* 下一节: [小结](<06.5.md>)