🏢
Billion hashes attackについて
はじめに
はじめまして、株式会社バニッシュ・スタンダードでエンジニアをしているchanponといいます。
go-joseというJWEのライブラリを使用する機会があり、バージョン3からバージョン4へのアップグレードのきっかけの一つとなった「Billion hashes attack」について調べました。この記事ではその内容について詳しく述べていきたいと思います。
Billion hashes attackとは何か?
「Billion hashes attack」とは、セキュリティー強化のために高い反復処理回数(イテレーションカウント)を設定したパスワードベースの鍵導出関数を利用することで、意図的にサービスの処理を遅らせる攻撃手法です。この攻撃は、システムに対して過剰な計算を要求し、サービスを実質的に停止させる可能性があります。
go-joseライブラリとBillion hashes attack
PBES2では、パスワードから安全なキーを生成するためにイテレーションカウントを用いており、これによりパスワードの推測を困難にしています。go-joseのバージョン3までは、JWEを復号する際に暗号化方式をJWEヘッダーから読み取っており、攻撃者が意図的に高いイテレーションカウントを設定することでサーバーへの負荷を大きくする「Billion hashes attack」を可能にしていました。この問題に対処するため、バージョン4では暗号化方式やパラメータの設定をユーザーが任意に行えるように改善され、サーバーへの不正な負荷を防ぐ措置が講じられています。
JWEの発行とgo-joseライブラリの使用例
package main
import (
"log"
"time"
"github.com/go-jose/go-jose/v4"
"github.com/go-jose/go-jose/v4/jwt"
)
var key = []byte("01234567890123456789012345678901")
var alg = jose.HS256
func main() {
now := time.Now()
claims := jwt.Claims{
Issuer: "issuer",
Subject: "subject",
IssuedAt: jwt.NewNumericDate(now),
Expiry: jwt.NewNumericDate(now.Add(10 * time.Minute)),
}
signer, err := jose.NewSigner(jose.SigningKey{Algorithm: alg, Key: key}, nil)
if err != nil {
log.Fatalf("Failed to create signer: %v", err)
}
token, err := jwt.Signed(signer).Claims(claims).Serialize()
if err != nil {
log.Fatalf("Failed to serialize token: %v", err)
}
log.Printf("Serialized Token: %s", token)
}
バージョン3の場合
func parseTokenV3(token string) {
parsedToken, err := jwt.ParseSigned(token)
if err != nil {
log.Fatalf("Failed to parse token: %v", err)
}
log.Printf("Parsed Token: %v", parsedToken)
}
バージョン4の場合
func parseTokenV4(token string) {
// アルゴリズムの指定が必要
parsedToken, err := jwt.ParseSigned(token, []jose.SignatureAlgorithm{jose.HS256})
if err != nil {
log.Fatalf("Failed to parse token: %v", err)
}
log.Printf("Parsed Token: %v", parsedToken)
}
終わりに
go-joseをバージョンアップさせる中で出会ったBillion hashes attackについて書かせていただきました。この経験を通して、これからもセキュリティにもっと気を配りながら開発を進めていきたいと思います。
参考文献
Discussion