🐥

オタクくん「ギャル先輩、バックエンドのセキュリティ対策って何したらいいんですか?」

2024/05/21に公開

オタクくん「うーん、バックエンドのコードはだいたい書けるようになったけど、セキュリティってどうすればいいんだろう…。何から始めればいいのか全然わからないや。」

ギャル先輩「あれ?オタクくん、また悩んでんの?今度は何?」

オタクくん「あ、ギャル先輩!実はバックエンドのセキュリティについて調べてたんですけど、どんな対策をすればいいのかわからなくて…。何か基本的なことから教えてもらえますか?」

ギャル先輩「ふーん、セキュリティね。あーしが教えてあげるよ。まず、セキュリティ対策って言っても色々あるから、基本的なところから始めようか。」

セキュリティ対策の基本

オタクくん「基本的なところから…ですか?」

ギャル先輩「そうそう。まずは入力のバリデーションだね。これはどんなデータが入力されても問題がないようにチェックすることだよ。」

オタクくん「具体的にはどうするんですか?」

ギャル先輩「例えば、ユーザーが入力するデータが期待される形式かどうかを確認するんだ。こんな感じで。」

from flask import Flask, request
app = Flask(__name__)

@app.route('/submit', methods=['POST'])
def submit():
    data = request.json
    if 'username' not in data or not isinstance(data['username'], str):
        return 'Invalid input', 400
    return 'Success', 200

if __name__ == '__main__':
    app.run()

オタクくん「なるほど、入力データを検証して問題があればエラーメッセージを返すんですね。」

SQLインジェクション対策

ギャル先輩「次に大事なのはSQLインジェクション対策だね。これはユーザーが入力するデータを使って直接SQLクエリを実行するときに問題になるよ。」

オタクくん「SQLインジェクションって具体的にはどういうものですか?」

ギャル先輩「例えば、こんな感じのコードがあるとするよ。」

def get_user(username):
    query = f"SELECT * FROM users WHERE username = '{username}'"
    # 実際にはデータベースでクエリを実行する

オタクくん「ふむふむ…。」

ギャル先輩「ここで、もしユーザーが username' OR '1'='1 みたいな入力をしたら、全てのユーザー情報が取得されちゃうんだ。」

オタクくん「それは危ないですね!」

ギャル先輩「うん。だから、プレースホルダを使ってクエリを安全に実行するんだ。例えば、こんな感じに。」

import sqlite3

def get_user(username):
    connection = sqlite3.connect('example.db')
    cursor = connection.cursor()
    query = "SELECT * FROM users WHERE username = ?"
    cursor.execute(query, (username,))
    return cursor.fetchone()

オタクくん「なるほど、これならユーザーの入力を安全に扱えますね。」

クロスサイトスクリプティング(XSS)対策

ギャル先輩「次に**クロスサイトスクリプティング(XSS)**の対策も重要だよ。これはユーザーが入力したスクリプトが他のユーザーに対して実行される攻撃だね。」

オタクくん「どうやって防ぐんですか?」

ギャル先輩「まず、ユーザーからの入力をエスケープすることが大事だね。例えば、HTMLに表示する前に特殊文字をエスケープするんだ。」

from flask import Flask, request, escape
app = Flask(__name__)

@app.route('/show', methods=['GET'])
def show():
    user_input = request.args.get('user_input', '')
    safe_input = escape(user_input)
    return f'<p>{safe_input}</p>'

if __name__ == '__main__':
    app.run()

オタクくん「なるほど、これで悪意のあるスクリプトが実行されるのを防げるんですね。」

認証と認可

ギャル先輩「それから、認証認可も大事だよ。認証はユーザーが誰であるかを確認することで、認可はそのユーザーが何をする権限があるかを確認することだね。」

オタクくん「具体的にはどうするんですか?」

ギャル先輩「例えば、トークンベースの認証を使ってセッションを管理する方法があるよ。JSON Web Token(JWT)を使った認証の例を見てみようか。」

import jwt
from datetime import datetime, timedelta

SECRET_KEY = 'your_secret_key'

def create_token(user_id):
    expiration = datetime.utcnow() + timedelta(hours=1)
    token = jwt.encode({'user_id': user_id, 'exp': expiration}, SECRET_KEY, algorithm='HS256')
    return token

def verify_token(token):
    try:
        decoded = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
        return decoded['user_id']
    except jwt.ExpiredSignatureError:
        return None
    except jwt.InvalidTokenError:
        return None

オタクくん「これでユーザーを認証して、トークンを使ってセッション管理ができるんですね。」

ログと監視

ギャル先輩「最後に、ログ監視も忘れちゃダメだよ。何か問題が起きたときにすぐに気づいて対処できるようにするためには、ログをしっかりとって監視することが重要なんだ。」

オタクくん「具体的にはどうすればいいですか?」

ギャル先輩「例えば、ログをファイルに書き出すだけでもいいんだ。こんな感じでね。」

import logging

logging.basicConfig(filename='app.log', level=logging.INFO)

def log_message(message):
    logging.info(message)

オタクくん「なるほど、これでアプリケーションの動作を監視できるんですね。」

ギャル先輩「そうだよ。問題が発生したときにすぐに気づけるし、後から原因を特定するのにも役立つんだ。」

オタクくん「わかりました。ありがとうございます、ギャル先輩!」

ギャル先輩「オタクくん、意外と飲み込み早いじゃん。てーか、ちょっと感心したかも。」

オタクくん「え?ありがとうございます。でも、ギャル先輩がわかりやすく教えてくれたおかげですよ。」

ギャル先輩「そ、そんなの当たり前じゃん!ば、バカにしないでよね!」

オタクくん「いや、本当に感謝してます。これからもいろいろ教えてください!」

ギャル先輩「う、うん…。まぁ、また困ったら聞いてよね。あーしが教えてあげるからさ。」

オタクくん「はい!ギャル先輩、ありがとうございます!」

Discussion