WithCodeMedia-1-pc
previous arrowprevious arrow
next arrownext arrow

WithCodeMedia-1-sp
previous arrowprevious arrow
next arrownext arrow

【完全保存版】Web制作セキュアコーディングチェックリスト!脆弱性対策から品質管理まで実装例を踏まえて詳しく解説

生徒

Web制作でセキュリティって本当に重要なんですか?個人サイトでも対策が必要でしょうか?

ペン博士

非常に重要じゃ!セキュリティの甘いサイトは、個人情報漏洩や改ざん、マルウェア配布の踏み台にされる危険があるんじゃよ。今日は実務で必須のセキュアコーディングチェックリストを詳しく解説するぞい!

目次

この記事でわかること

  • セキュアコーディングの定義と、なぜすべてのWebサイトで必須なのか
  • HTTPS・セキュリティヘッダー・インジェクション攻撃対策の具体的な実装方法
  • 認証・セッション管理の安全な実装パターン(PHP・Node.js・Next.js)
  • WordPressサイト固有のセキュリティ設定チェックリスト
  • 自動化ツールを使った定期的なセキュリティ監査のやり方

現代のWeb制作において、セキュリティ対策は避けて通れない重要課題です。小規模サイトから大企業まで、あらゆるWebサイトが攻撃の標的となっており、サイバー攻撃件数は年々増加しています。

本記事では、Web制作における必須のセキュアコーディングチェックリストを、実装例と共に徹底的に解説します。初心者の方でも理解できるよう、各項目の重要性と具体的な対策方法を丁寧に説明します。


セキュアコーディングとは?定義と重要性

セキュアコーディング(Secure Coding)とは、セキュリティ上の脆弱性を作り込まないようにコードを書く開発手法のことです。単にバグを減らすだけでなく、悪意のある攻撃者に悪用される可能性のある脆弱性を事前に防ぐことを目的としています。

Web制作においてセキュアコーディングが重要な理由は以下の通りです。

  • 個人情報の保護:ユーザーの個人情報やクレジットカード情報を守る
  • 信頼性の維持:セキュリティ事故は企業やサービスの信頼を大きく損なう
  • 法的責任の回避:個人情報保護法やGDPRなどの法規制への対応
  • ビジネス継続性:攻撃によるサービス停止は大きな損失につながる
  • SEOへの影響:Googleはセキュアでないサイトの評価を下げる

代表的なWeb脆弱性(OWASP Top 10)

OWASP(The Open Web Application Security Project)が公開している「OWASP Top 10」は、Webアプリケーションにおける最も深刻なセキュリティリスクをまとめたものです。2021年版の主要な脆弱性は以下の通りです。

順位脆弱性の種類説明
1アクセス制御の不備認証・認可の実装ミスによる不正アクセス
2暗号化の失敗データ転送・保存時の暗号化不足
3インジェクションSQLi、XSSなどの不正な入力
4安全でない設計セキュリティを考慮しない設計
5セキュリティ設定ミスデフォルト設定のまま使用など
6脆弱なコンポーネント古いライブラリやフレームワークの使用
7識別と認証の失敗脆弱なパスワードポリシーなど
8ソフトウェアとデータの整合性検証なしのアップデートなど
9ログと監視の不足攻撃の検知・対応ができない
10サーバーサイドリクエストフォージェリSSRF攻撃への脆弱性

本記事では、これらの脆弱性に対する具体的な対策をチェックリスト形式で紹介します。


【必須】基本セキュリティチェックリスト

生徒

まずは何から始めれば良いですか?

ペン博士

まずは基本中の基本から押さえるんじゃ!これらは全てのWebサイトで必須の対策じゃぞ

1. HTTPS/SSL対応

最も基本的かつ重要なセキュリティ対策です。Googleは2014年以降HTTPSをランキングシグナルとして使用しており、HTTPサイトには警告が表示されます。また、HTTP/2の高速化機能もHTTPS必須です。

チェック項目

  • ☐ SSL/TLS証明書が正しくインストールされているか
  • ☐ HTTPからHTTPSへの自動リダイレクトが設定されているか
  • ☐ 全てのリソース(画像、CSS、JS)がHTTPSで読み込まれているか
  • ☐ HSTSヘッダーが設定されているか
  • ☐ 証明書の有効期限管理体制があるか

実装例:.htaccessでのHTTPSリダイレクト

# .htaccess
# HTTPからHTTPSへのリダイレクト
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# HSTSヘッダーの設定(1年間)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

実装例:HTMLでの混在コンテンツ対策

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">

  <!-- Content Security Policyで混在コンテンツをブロック -->
  <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">

  <!-- 相対URLまたはプロトコル相対URLを使用 -->
  <link rel="stylesheet" href="/css/style.css">
  <script src="//example.com/script.js"></script>
</head>

2. セキュリティヘッダーの設定

HTTPレスポンスヘッダーにセキュリティ関連の設定を追加することで、多くの攻撃を防げます。セキュリティヘッダーは「深層防御(Defense in Depth)」の一環として、複数の層でセキュリティを強化する重要な手段です。

チェック項目

  • ☐ X-Frame-Options ヘッダーでクリックジャッキング対策
  • ☐ X-Content-Type-Options ヘッダーでMIMEタイプスニッフィング防止
  • ☐ X-XSS-Protection ヘッダーでXSS対策
  • ☐ Content-Security-Policy ヘッダーでコンテンツ制御
  • ☐ Referrer-Policy ヘッダーでリファラー情報制御
  • ☐ Permissions-Policy ヘッダーでブラウザAPI制御

実装例:.htaccessでのセキュリティヘッダー設定

# .htaccess
<IfModule mod_headers.c>
  # クリックジャッキング対策
  Header always set X-Frame-Options "SAMEORIGIN"

  # MIMEタイプスニッフィング防止
  Header always set X-Content-Type-Options "nosniff"

  # XSS対策(古いブラウザ用)
  Header always set X-XSS-Protection "1; mode=block"

  # Content Security Policy(厳格な設定例)
  Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://trusted-cdn.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'self';"

  # リファラーポリシー
  Header always set Referrer-Policy "strict-origin-when-cross-origin"

  # 機能ポリシー
  Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>

実装例:Node.js(Express)での設定

// helmet.jsを使った簡単な設定
const helmet = require('helmet')
const express = require('express')
const app = express()

// デフォルトのセキュリティヘッダーを設定
app.use(helmet())

// カスタマイズした設定
app.use(
  helmet({
    contentSecurityPolicy: {
      directives: {
        defaultSrc: ["'self'"],
        scriptSrc: ["'self'", "'unsafe-inline'", "https://trusted-cdn.com"],
        styleSrc: ["'self'", "'unsafe-inline'"],
        imgSrc: ["'self'", "data:", "https:"],
        connectSrc: ["'self'"],
        fontSrc: ["'self'"],
        objectSrc: ["'none'"],
        mediaSrc: ["'self'"],
        frameSrc: ["'none'"],
      },
    },
    hsts: {
      maxAge: 31536000,
      includeSubDomains: true,
      preload: true
    }
  })
)

【重要】インジェクション攻撃対策チェックリスト

インジェクション攻撃は、OWASP Top 10で常に上位にランクインする深刻な脆弱性です。ユーザーからの入力を直接クエリや命令に使うコードは必ず見直してください。

3. SQLインジェクション対策

データベースへの不正な命令を実行される攻撃を防ぎます。プリペアドステートメント(パラメータ化クエリ)の使用が最も確実な対策です。

チェック項目

  • ☐ プリペアドステートメント(パラメータ化クエリ)を使用しているか
  • ☐ ORMを適切に使用しているか
  • ☐ 動的にSQL文を生成していないか
  • ☐ エラーメッセージでデータベース情報を漏らしていないか
  • ☐ データベースユーザーの権限が最小限に制限されているか

❌ 脆弱なコード例(PHP)

<?php
// 危険!ユーザー入力を直接SQLに埋め込んでいる
$username = $_POST['username'];
$password = $_POST['password'];

$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysqli_query($conn, $query);

// 攻撃例: username に "admin' --" を入力すると
// SELECT * FROM users WHERE username = 'admin' --' AND password = ''
// パスワードチェックが無効化される
?>

✅ 安全なコード例(PHP – プリペアドステートメント)

<?php
// 安全:プリペアドステートメントを使用
$username = $_POST['username'];
$password = $_POST['password'];

// パスワードはハッシュ化して保存されている前提
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ? AND password_hash = ?");
$stmt->bind_param("ss", $username, password_hash($password, PASSWORD_BCRYPT));
$stmt->execute();
$result = $stmt->get_result();

if ($result->num_rows === 1) {
    $user = $result->fetch_assoc();
    // パスワード検証
    if (password_verify($password, $user['password_hash'])) {
        // ログイン成功
        echo "ログイン成功";
    } else {
        echo "認証失敗";
    }
} else {
    echo "認証失敗";
}

$stmt->close();
?>

✅ 安全なコード例(Node.js – Prisma ORM)

// Prisma ORMを使った安全な実装
import { PrismaClient } from '@prisma/client'
import bcrypt from 'bcrypt'

const prisma = new PrismaClient()

async function login(username: string, password: string) {
  // Prismaは自動的にパラメータ化される
  const user = await prisma.user.findUnique({
    where: { username: username }
  })

  if (!user) {
    throw new Error('認証失敗')
  }

  // パスワード検証
  const isValid = await bcrypt.compare(password, user.passwordHash)

  if (!isValid) {
    throw new Error('認証失敗')
  }

  return user
}

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

悪意のあるスクリプトがWebページに埋め込まれる攻撃を防ぎます。ユーザー入力を出力する全ての箇所でエスケープ処理が必須です。

チェック項目

  • ☐ ユーザー入力を出力する際にエスケープ処理をしているか
  • ☐ innerHTML、dangerouslySetInnerHTMLを不用意に使っていないか
  • ☐ Content-Security-Policyヘッダーを設定しているか
  • ☐ 信頼できないHTMLをサニタイズしているか
  • ☐ JavaScriptのevalや同等の関数を使用していないか

❌ 脆弱なコード例(JavaScript)

// 危険!ユーザー入力をそのままHTMLに挿入
const userName = new URLSearchParams(window.location.search).get('name')
document.getElementById('greeting').innerHTML = `こんにちは、${userName}さん`

// 攻撃例: ?name=<script>alert('XSS')</script>
// スクリプトが実行されてしまう

✅ 安全なコード例(JavaScript – エスケープ処理)

// 安全:textContentを使用(自動的にエスケープされる)
const userName = new URLSearchParams(window.location.search).get('name')
document.getElementById('greeting').textContent = `こんにちは、${userName}さん`

// または、手動でエスケープ
function escapeHTML(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;')
}

const userName = new URLSearchParams(window.location.search).get('name')
document.getElementById('greeting').innerHTML = `こんにちは、${escapeHTML(userName)}さん`

✅ 安全なコード例(React)

// React は自動的にエスケープする
function Greeting({ userName }: { userName: string }) {
  // 安全:JSX構文は自動的にエスケープされる
  return <div>こんにちは、{userName}さん</div>
}

// HTMLを挿入する必要がある場合はDOMPurifyでサニタイズ
import DOMPurify from 'dompurify'

function RichContent({ html }: { html: string }) {
  const sanitizedHTML = DOMPurify.sanitize(html)

  return (
    <div dangerouslySetInnerHTML={{ __html: sanitizedHTML }} />
  )
}

✅ 安全なコード例(PHP)

<?php
// 安全:htmlspecialcharsでエスケープ
$userName = $_GET['name'] ?? 'ゲスト';
$escapedName = htmlspecialchars($userName, ENT_QUOTES, 'UTF-8');

echo "こんにちは、" . $escapedName . "さん";

// またはテンプレートエンジンを使用(Twigの例)
// {{ userName }} は自動的にエスケープされる
?>

5. CSRF(クロスサイトリクエストフォージェリ)対策

ユーザーの意図しないリクエストが実行される攻撃を防ぎます。フォーム送信・状態変更操作には必ずCSRFトークンを実装してください。

チェック項目

  • ☐ フォーム送信時にCSRFトークンを使用しているか
  • ☐ SameSite属性付きCookieを使用しているか
  • ☐ 重要な操作で再認証を求めているか
  • ☐ RefererヘッダーやOriginヘッダーを検証しているか
  • ☐ GETリクエストで状態を変更していないか

✅ 安全なコード例(PHP – CSRFトークン)

<?php
session_start();

// トークン生成(フォーム表示時)
function generateCSRFToken() {
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf_token'];
}

// トークン検証(フォーム送信時)
function verifyCSRFToken($token) {
    if (!isset($_SESSION['csrf_token']) || $token !== $_SESSION['csrf_token']) {
        die('CSRF検証に失敗しました');
    }
    return true;
}

// フォーム表示
$csrfToken = generateCSRFToken();
?>

<form method="POST" action="update_profile.php">
    <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrfToken); ?>">
    <input type="text" name="username">
    <button type="submit">更新</button>
</form>

<?php
// フォーム処理
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    verifyCSRFToken($_POST['csrf_token']);

    // 処理を続行
    $username = $_POST['username'];
    // データベース更新など
}
?>

✅ 安全なコード例(Node.js + Express)

const express = require('express')
const csrf = require('csurf')
const cookieParser = require('cookie-parser')

const app = express()

// Cookieパーサーとセッションミドルウェア
app.use(cookieParser())
app.use(express.urlencoded({ extended: false }))

// CSRF保護ミドルウェア
const csrfProtection = csrf({ cookie: true })

// フォーム表示
app.get('/profile', csrfProtection, (req, res) => {
  res.render('profile', { csrfToken: req.csrfToken() })
})

// フォーム送信処理
app.post('/profile', csrfProtection, (req, res) => {
  // CSRFトークンが自動的に検証される
  const { username } = req.body

  // 処理を続行
  res.send('プロフィールを更新しました')
})

✅ 安全なコード例(React + Next.js)

// Server Action(Next.js 13+)
'use server'

import { cookies } from 'next/headers'

export async function updateProfile(formData: FormData) {
  // Next.js Server Actionsは自動的にCSRF保護される

  const username = formData.get('username') as string

  // データベース更新など

  return { success: true }
}

// クライアントコンポーネント
'use client'

import { updateProfile } from '@/app/actions'

export default function ProfileForm() {
  return (
    <form action={updateProfile}>
      <input type="text" name="username" />
      <button type="submit">更新</button>
    </form>
  )
}

【必須】認証・認可のセキュリティチェックリスト

6. パスワード管理

平文でパスワードを保存することは絶対に避けてください。bcryptやArgon2などのハッシュ関数を使い、必ずソルトを付与して保存します。

チェック項目

  • ☐ パスワードをハッシュ化して保存しているか(bcrypt、Argon2等)
  • ☐ ソルトを使用しているか
  • ☐ 平文パスワードをログに出力していないか
  • ☐ パスワード強度のポリシーがあるか(最低8文字、複雑性要求など)
  • ☐ パスワードリセット機能は安全か
  • ☐ ブルートフォース攻撃対策があるか(レート制限、アカウントロック)

✅ 安全なコード例(Node.js – bcrypt)

import bcrypt from 'bcrypt'

// ユーザー登録時
async function registerUser(username: string, password: string) {
  // パスワード強度チェック
  if (password.length < 8) {
    throw new Error('パスワードは8文字以上である必要があります')
  }

  // パスワードをハッシュ化(saltRounds=10)
  const saltRounds = 10
  const passwordHash = await bcrypt.hash(password, saltRounds)

  // データベースに保存
  await db.user.create({
    data: {
      username,
      passwordHash, // ハッシュ化されたパスワードを保存
    }
  })

  // 平文パスワードはメモリから削除される
}

// ログイン時
async function login(username: string, password: string) {
  const user = await db.user.findUnique({
    where: { username }
  })

  if (!user) {
    // タイミング攻撃対策のため、同じエラーメッセージ
    throw new Error('ユーザー名またはパスワードが正しくありません')
  }

  // パスワード検証
  const isValid = await bcrypt.compare(password, user.passwordHash)

  if (!isValid) {
    throw new Error('ユーザー名またはパスワードが正しくありません')
  }

  return user
}

7. セッション管理

セッションIDの安全な生成・管理が、セッションハイジャック攻撃を防ぐ鍵です。ログイン前後でセッションを再生成し、タイムアウトを設定してください。

チェック項目

  • ☐ セッションIDは予測不可能なランダム値か
  • ☐ Cookie属性が適切に設定されているか(HttpOnly、Secure、SameSite)
  • ☐ セッションタイムアウトが設定されているか
  • ☐ ログアウト時にセッションが破棄されているか
  • ☐ 重要な操作前にセッションを再生成しているか

✅ 安全なコード例(Express Session)

const express = require('express')
const session = require('express-session')

const app = express()

app.use(
  session({
    secret: process.env.SESSION_SECRET, // 環境変数から読み込む
    resave: false,
    saveUninitialized: false,
    cookie: {
      httpOnly: true, // JavaScriptからアクセス不可
      secure: true, // HTTPS必須
      sameSite: 'strict', // CSRF対策
      maxAge: 1000 * 60 * 60, // 1時間
    },
    name: 'sessionId', // デフォルトの名前を変更
  })
)

// ログイン処理
app.post('/login', async (req, res) => {
  const { username, password } = req.body

  const user = await authenticateUser(username, password)

  if (user) {
    // セッション再生成(セッション固定攻撃対策)
    req.session.regenerate((err) => {
      if (err) {
        return res.status(500).send('セッションエラー')
      }

      req.session.userId = user.id
      req.session.username = user.username

      res.send('ログイン成功')
    })
  } else {
    res.status(401).send('認証失敗')
  }
})

// ログアウト処理
app.post('/logout', (req, res) => {
  req.session.destroy((err) => {
    if (err) {
      return res.status(500).send('ログアウトエラー')
    }

    res.clearCookie('sessionId')
    res.send('ログアウト成功')
  })
})

【重要】WordPressセキュリティチェックリスト

生徒

WordPressサイトを運営しているんですが、特に気をつけることはありますか?

ペン博士

WordPressは世界中で使われているから、攻撃の標的になりやすいんじゃ。しっかり対策するんじゃぞ!

8. WordPress基本セキュリティ

WordPressはCMS市場シェアが高いため、攻撃スクリプトが自動化されやすい環境です。本体・テーマ・プラグインのアップデートを怠ると、既知の脆弱性を突かれるリスクが高まります。

チェック項目

  • ☐ WordPress本体を最新バージョンに更新しているか
  • ☐ テーマを最新バージョンに更新しているか
  • ☐ プラグインを最新バージョンに更新しているか
  • ☐ 使用していないテーマ・プラグインを削除しているか
  • ☐ 管理者ユーザー名が「admin」ではないか
  • ☐ データベーステーブルの接頭辞が「wp_」以外に変更されているか
  • ☐ ファイルの編集機能を無効化しているか
  • ☐ xmlrpc.phpを無効化しているか
  • ☐ wp-config.phpが適切に保護されているか
  • ☐ デバッグモードが本番環境で無効化されているか

実装例:wp-config.phpのセキュリティ設定

<?php
// wp-config.php

// セキュリティキーの設定(https://api.wordpress.org/secret-key/1.1/salt/ で生成)
define('AUTH_KEY',         'ランダムな文字列');
define('SECURE_AUTH_KEY',  'ランダムな文字列');
define('LOGGED_IN_KEY',    'ランダムな文字列');
define('NONCE_KEY',        'ランダムな文字列');
define('AUTH_SALT',        'ランダムな文字列');
define('SECURE_AUTH_SALT', 'ランダムな文字列');
define('LOGGED_IN_SALT',   'ランダムな文字列');
define('NONCE_SALT',       'ランダムな文字列');

// デバッグモードを無効化
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);
define('WP_DEBUG_DISPLAY', false);

// ファイル編集を無効化
define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', true);

// データベーステーブル接頭辞を変更
$table_prefix = 'wpsec_'; // デフォルトの「wp_」から変更

// SSL強制
define('FORCE_SSL_ADMIN', true);

// セキュリティヘッダー
@ini_set('display_errors', 0);
?>

実装例:.htaccessでの保護

# .htaccess

# wp-config.phpへのアクセスを拒否
<files wp-config.php>
  order allow,deny
  deny from all
</files>

# xmlrpc.phpへのアクセスを拒否(使用しない場合)
<files xmlrpc.php>
  order allow,deny
  deny from all
</files>

# wp-includes/へのアクセスを制限
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^wp-admin/includes/ - [F,L]
  RewriteRule !^wp-includes/ - [S=3]
  RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
  RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
  RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>

# ディレクトリリスティングを無効化
Options -Indexes

# 管理画面へのIPアドレス制限(オプション)
<Files wp-login.php>
  order deny,allow
  deny from all
  # 許可するIPアドレスを指定
  allow from 123.456.789.0
</Files>

9. WordPress ログインセキュリティ

チェック項目

  • ☐ 二要素認証(2FA)を実装しているか
  • ☐ ログイン試行回数を制限しているか
  • ☐ CAPTCHA を設置しているか
  • ☐ ログインURLを変更しているか(オプション)
  • ☐ 管理者以外の投稿者ページへのアクセスを制限しているか

推奨プラグイン

  • Wordfence Security:総合セキュリティプラグイン
  • iThemes Security:30以上のセキュリティ対策
  • Login LockDown:ログイン試行回数制限
  • Google Authenticator:二要素認証
  • WPS Hide Login:ログインURL変更

【推奨】コーディング品質チェックリスト

10. HTML/CSS/JavaScriptの品質

チェック項目

  • ☐ HTMLが適切にバリデーションされているか
  • ☐ セマンティックHTMLを使用しているか
  • ☐ 画像にalt属性が設定されているか
  • ☐ フォームにlabel要素が適切に設定されているか
  • ☐ ARIA属性が必要な箇所に設定されているか
  • ☐ CSSにベンダープレフィックスが適切に設定されているか
  • ☐ JavaScriptのコンソールエラーがないか
  • ☐ 依存ライブラリが最新で脆弱性がないか

検証ツール

  • W3C Markup Validation Service:HTML検証
  • W3C CSS Validation Service:CSS検証
  • ESLint:JavaScript静的解析
  • npm audit / yarn audit:依存関係の脆弱性チェック
  • Snyk:セキュリティ脆弱性検出

11. パフォーマンスとSEO

チェック項目

  • ☐ ページ読み込み速度が3秒以内か
  • ☐ 画像が最適化されているか(WebP、適切なサイズ)
  • ☐ CSS/JavaScriptが最小化されているか
  • ☐ Gzip/Brotli圧縮が有効か
  • ☐ ブラウザキャッシュが設定されているか
  • ☐ モバイルフレンドリーか
  • ☐ Core Web Vitals の基準を満たしているか
  • ☐ リンク切れがないか
  • ☐ robots.txt、sitemap.xmlが適切に設定されているか

【実践】セキュリティ監査の実施方法

自動化ツールの活用

1. OWASP ZAP(Zed Attack Proxy)

無料のWebアプリケーション脆弱性スキャナーです。Dockerで手軽に実行できます。

# Docker で OWASP ZAP を実行
docker run -t owasp/zap2docker-stable zap-baseline.py -t https://your-website.com

# レポートが生成される

2. Mozilla Observatory

Webサイトのセキュリティヘッダーを診断するツールです。

URL: https://observatory.mozilla.org/

3. SSL Labs SSL Test

SSL/TLS設定を詳細に診断し、評価グレードを表示します。

URL: https://www.ssllabs.com/ssltest/

4. npm audit / yarn audit

# Node.jsプロジェクトの脆弱性チェック
npm audit

# 自動修正
npm audit fix

# または yarn
yarn audit

定期的な監視体制の構築

  1. 週次チェック
    • CMSやプラグインのアップデート確認
    • アクセスログの異常検知
    • バックアップの確認
  2. 月次チェック
    • 脆弱性スキャンの実施
    • SSL証明書の有効期限確認
    • リンク切れチェック
  3. 四半期チェック
    • 全体的なセキュリティ監査
    • ペネトレーションテスト(可能であれば)
    • セキュリティポリシーの見直し

生徒

チェック項目がたくさんありますね!全部一度にやるのは大変そう…

ペン博士

その通りじゃ!まずは重要度の高い項目から順番に対策していくのが良いぞ。HTTPS対応、パスワードのハッシュ化、XSS/SQLi対策あたりから始めるんじゃ!

生徒

わかりました!このチェックリストを使って、安全なWebサイトを作ります!


よくある質問

個人ブログや小規模サイトでもセキュリティ対策は必要ですか?

はい、必要です。規模にかかわらず、HTTPS化・セキュリティヘッダー設定・CMSの最新化は必須です。小規模サイトは対策が手薄なケースが多く、自動化された攻撃スクリプトの標的になりやすい傾向があります。マルウェア配布の踏み台にされるとSEO評価にも深刻な影響を及ぼします。

SQLインジェクションとXSSはどちらが危険ですか?

どちらも深刻ですが、性質が異なります。SQLインジェクションはデータベースの情報漏洩・改ざん・削除に直結し、サービス全体に影響します。XSSはユーザーのブラウザ上でスクリプトを実行させ、セッション盗用や意図しない操作を引き起こします。OWASP Top 10では両方が上位に位置づけられており、どちらも同等に対策が必要です。

CSRFトークンとSameSite Cookieはどちらを使えばよいですか?

可能であれば両方を組み合わせるのがベストです。SameSite=Strict または Lax の Cookie 設定はモダンブラウザで有効ですが、古いブラウザや一部の状況では機能しないことがあります。CSRFトークンはより確実な対策であり、特に重要な操作(支払い・パスワード変更など)には必ず実装してください。

WordPressのxmlrpc.phpは必ず無効化すべきですか?

Jetpackなどxmlrpcを必要とするプラグインを使用していなければ、無効化することを強く推奨します。xmlrpc.phpはブルートフォース攻撃やDDoS攻撃に悪用されることが多く、使用しないなら.htaccessでアクセスをブロックするのが安全です。

セキュリティツールは無料のものでも十分ですか?

基本的な監査はOWASP ZAP・Mozilla Observatory・SSL Labs SSL Testなどの無料ツールで十分対応できます。ただし、本番環境での本格的なペネトレーションテストや継続的な脆弱性監視が必要な場合は、有料の専門サービスやSnykなどの商用ツールを検討してください。


まとめ

本記事では、Web制作におけるセキュアコーディングの完全チェックリストを、実装例と共に詳しく解説しました。

  • 基本セキュリティ:HTTPS対応とセキュリティヘッダーの設定は全サイトで必須
  • インジェクション対策:SQLインジェクション・XSS・CSRFへの対策を徹底する
  • 認証・認可:パスワードのハッシュ化(bcrypt/Argon2)とセッション管理を適切に実装する
  • WordPress:本体・テーマ・プラグインの更新を継続し、不要なものは削除する
  • コーディング品質:HTML/CSS/JavaScriptの検証ツールを活用して品質を担保する
  • 継続的監視:週次・月次・四半期のチェック体制を構築し、定期的に監査する
  • 自動化ツール活用:OWASP ZAP・Mozilla Observatory・npm auditで効率的に脆弱性を検出する

このセキュアコーディングチェックリストを活用し、安全で信頼性の高いWebサイトを構築してください。セキュリティは一度対策すれば終わりではなく、継続的に維持・改善していく必要があります。定期的にチェックリストを見直し、常に最新のセキュリティ対策を実施することで、ユーザーに安心して使ってもらえるWebサイトを提供できます。


関連記事


参考リンク(公式・一次情報)


WithCodeを体験できる初級コース公開中!

WithCode初級コース

初級コース(¥49,800)が完全無料に!

  • 期間:1週間
  • 学習内容:ロードマップ/基礎知識/環境構築/HTML/CSS/LP・ポートフォリオ作成
    → 正しい学習方法で「確かな成長」を実感できるカリキュラム

副業・フリーランスが主流になっている今こそ、自らのスキルで稼げる人材を目指してみませんか?

未経験でも心配することはありません。初級コースを受講される方の大多数はプログラミング未経験です。まずは無料カウンセリングで、悩みや不安をお聞かせください!

この記事を書いた人

WithCode(ウィズコード)は「目指すなら稼げる人材」をビジョンに、累計400名以上のフリーランスを輩出してきた超実践型プログラミングスクールです。150社以上の実案件支援を特徴にWeb制作・Webデザインなどの役立つ情報を現場のノウハウに基づいて発信していきます。

– service –WithGroupの運営サービス

  • WithCode
    - ウィズコード -

    スクール

    「未経験」から
    現場で通用する
    スキルを身に付けよう!

    詳細はこちら
  • WithFree
    - ウィズフリ -

    実案件サポート

    制作会社のサポート下で
    実務経験を積んでいこう!

    詳細はこちら

公式サイト より
今すぐ
無料カウンセリング
予約!

目次