Cookie の保護
次に修正するセキュリティ問題は、保護されていない Cookie による潜在的な XSS 脆弱性です。モジュール3でのXSS演習 では、攻撃者は、ブラウザのクッキーと一緒に別のウェブページにリダイレクトするようにブラウザを強制するクライアントサイドの JavaScript コードを注入することによって、ユーザのsessionIdを盗み出すことができました。

これを防ぐ方法の 1 つは、HttpOnly として設定したクッキーを選択的にマークすることです。これは、ウェブサイトが設定したクッキーが他のドメインからアクセスできないことをブラウザに指示します。これは比較的簡単な修正です。AWS Cloud9 を開いてください。
SonarQube が特定したファイルが 2 つあります。まず pages/a2.py を編集して、現在の内容を次のように置き換えましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
from flask import (
Blueprint,
request,
redirect,
render_template,
make_response
)
from models import get_user_by_password
from utils import (
generate_session,
parse_session
)
bp = Blueprint(
"a2", __name__,
template_folder='templates',
static_folder='static'
)
@bp.route("/A2")
def a2():
return render_template("a2.html")
@bp.route("/A2/auth", methods=['POST'])
def a2_auth():
username = request.form.get("username")
password = request.form.get("password")
user = get_user_by_password(username, password)
if not user:
return render_template("error.html", message="Invalid Crendentials")
# Generate SessionID
session_id = generate_session(username)
response = make_response(redirect("/owasp/A2/welcome"))
response.set_cookie("sessionId", session_id, httponly=True)
return response
@bp.route("/A2/welcome")
def a2_welcome():
if not request.cookies.get("sessionId"):
return ("<h1>Not Authorized!</h1>")
session_obj = parse_session(request.cookies.get("sessionId"))
return render_template("welcome.html", username=session_obj['username'])
|
強調表示されたコード行は、その特定のクッキーのHttpOnly フラグを有効にします。pages/a5.pyでも同様に置き換えます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
from flask import (
Blueprint,
request,
redirect,
make_response,
render_template
)
from models import (
get_user,
get_user_by_password
)
from utils import (
generate_session,
parse_session
)
bp = Blueprint(
"a5", __name__,
template_folder='templates',
static_folder='static'
)
@bp.route("/A5")
def a5():
return render_template("a5.html")
@bp.route("/A5/auth", methods=['POST'])
def a5_auth():
username = request.form.get("username")
password = request.form.get("password")
user = get_user_by_password(username, password)
if not user:
return render_template("error.html", message="Invalid Credentials")
# Generate SessionID
session_id = generate_session(username)
response = make_response(redirect("/owasp/A5/profile/{}".format(username)))
response.set_cookie("sessionId", session_id, httponly=True)
return response
@bp.route("/A5/profile/<username>")
def a5_profile(username):
if not request.cookies.get("sessionId"):
return ("<h1>Not Authorized!</h1>")
session = parse_session(request.cookies.get("sessionId"))
user = get_user(username)
if not user:
return render_template("404.html")
return render_template("profile.html", user=user)
|
また、Insecure Configuration を見ると、Cookie の セキュアフラグ も有効にする必要がある、との示唆があります。これは強く推奨されます。これにより、ブラウザは暗号化されていない HTTP リクエストでクッキーを送信できなくなります。しかし、残念ながら現在のラボ環境では独自のドメインを購入/使用できないため、ここでは AWS ACM を使用することはできません。一旦、これらの調査結果を Safe とマークします(少なくともこのワークショップのみでは)。

保存して、次のセキュリティ修正のセットに進みましょう。