カテゴリー: PC Page 24 of 50

Apacheで動かしているWebサイトにセキュリティヘッダーを付与。

概要

AWS Lightsailを用いて外部公開しているWebサイトのセキュリティを高めるため、セキュリティヘッダを更に付与しました。

環境

  • Ubuntu 20.04
  • Apache 2.4系
  • Headerモジュール導入済み

また、/etc/apache2/sites-availavle配下にバーチャルサイトファイルで管理しています。

さっくりとした手順

  1. 現行のバーチャルサイトのコンフィグのバックアップを取得します。
  2. コンフィグにセキュリティヘッダを付与します。
  3. Webサービスの再起動を行います。

実施した手順

バックアップ

cd /etc/apache2/sites-available &&pwd
# 自環境のバーチャルサイトの格納場所に移動します

sudo cp -pi hoge.conf /path/to/directory/hoge.conf.$(date +%Y%m%d)
# バックアップ元とバックアップ先は自分の環境に合わせます。

diff -u hoge.conf /path/to/directory/hoge.conf.$(date +%Y%m%d)
# 差分がないことでバックアップが取れていることを確認します。

セキュリティヘッダ追記

教義・進行に沿ったエディタを用いて、以下の差分になるようにセキュリティヘッダをコンフィグに付与します。

+    Header set X-Content-Type-Options "nosniff"
+    Header always append X-Frame-Options "SAMEORIGIN"
+    Header set X-XSS-Protection "1; mode=block"

以下はChantGPTによる解説です。

X-Content-Type-Options: "nosniff"

このヘッダーは、ブラウザがレスポンスのContent-Typeヘッダーと実際のコンテンツの種類が一致しない場合に、ブラウザが自動的にコンテンツのタイプを推測するのを防止します。これにより、悪意のあるコンテンツが実行されるリスクを低減することができます。

X-Frame-Options: "DENY" または "SAMEORIGIN"

このヘッダーは、クリックジャッキング攻撃を防止するために使用されます。"DENY" を指定すると、ページがフレーム内で表示されることが完全に禁止されます。"SAMEORIGIN" を指定すると、同じオリジン(ドメインとプロトコルが一致)のフレーム内でのみページが表示されます。

X-XSS-Protection: "1; mode=block"

このヘッダーは、クロスサイトスクリプティング(XSS)攻撃からの保護を目的としています。ブラウザによって検出されたXSS攻撃が検出された場合、ブラウザはページをブロックするように指示されます。

コンフィグの整合性確認と再起動

  • コンフィグ確認
sudo apache2ctl configtest
#Syntax OKを確認します
  • サービス再起動
sudo systemctl restart apache2.service

systemctl status apache2.service
#Active(running)を確認します

ヘッダ付与確認

  1. Google Chromeを開き、対象のウェブサイトにアクセスします。
  2. ウェブサイトを表示した状態で、右クリックしてコンテキストメニューを表示し、「検証」を選択します。
  3. 開発者ツールが表示されたら、上部のメニューバーの中から「Network」(ネットワーク)タブを選択します。
  4. ページをリロードするか、ウェブサイト上で任意のアクションを実行してネットワークタブにリクエストが表示されるようにします。
  5. ネットワークタブで、対象のリクエストを選択します。
  6. 右側のパネルで、"Headers"(ヘッダー)セクションを展開します。
  7. ヘッダーセクションには、レスポンスヘッダーが表示されるので、以下を確認してください。
  • X-Content-Type-Options
  • X-Frame-Options
  • X-XSS-Protection

ヘッダーが正しく設定されていれば、それぞれのヘッダーの値が表示されます。

Fail2banによる防御効果確認。

侵入防御システム、Fail2banを本格的に導入してから半年余り。その効果のフィードバックです。

導入環境

  • Ubuntu 20.04
  • Fail2ban 0.11.1
  • AWS Lightsailで運用しており、鍵交換認証を行っています。
  • Lightsailで開けているポートは22(SSH),80(http),443(https)の3つです。

設定ファイル

  • /etc/fail2ban/jail.local
[ufw]
enabled=true
filter=ufw.aggressive
action=iptables-allports
logpath=/var/log/ufw.log
maxretry=1
bantime=-1
ignoreip = 127.0.0.0/8 ::1
# 他、自環境のアクセス元

[sshd]
enabled=true
filter=sshd
mode=normal
port=22
protocol=tcp
logpath=/var/log/auth.log
maxretry=3
bantime=-1
ignoreip = 127.0.0.0/8 ::1
# 他、自環境のアクセス元

bantimeは「-1」。つまり、一度でもリストに入るような不審な兆候があれば、永久に追放します。

半年の経過

この設定で、どのぐらいのIPアドレスを弾いたのか、確認してみました。

  • 確認コマンド(ufw)
sudo fail2ban-client status ufw
  • 確認結果(ufw)
Status for the jail: ufw
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     0
|  `- File list:        /var/log/ufw.log
`- Actions
   |- Currently banned: 187
   |- Total banned:     187
   `- Banned IP list: (後略)
  • 確認コマンド(sshd)
sudo fail2ban-client status sshd
  • 確認結果(sshd)
Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     29
|  `- File list:        /var/log/auth.log
`- Actions
   |- Currently banned: 5125
   |- Total banned:     5125
   `- Banned IP list: (後略)

驚くべきはSSHのリスト数。半年で5000件を超えているので、単純計算で一月に833件超。BANされたリストをランダムに選んでabusedIP (https://www.abuseipdb.com/)で検索をかけると、いずれも

Confidence of Abuse is 100%

と表示されるものがほとんどです。

  • 鍵交換認証だろうとお構いなしに攻撃を仕掛けるアクセス元の多さ
  • これらを(ほぼ自動的に)弾いてくれるシステムのありがたさ

を改めて思い知りました。また、IPアドレス固定サービスを利用しているのであれば、アクセス許可を固定する(ポジティブリスト形式)が確実です。

Nextcloud、メンテナンスモードの解除方法。

はじめに

プライベートのオンラインストレージをWebベースで構築できるNextcloud。

ブラウザ上からもアップデートなどを行えるのは大きな利点ですが:メンテナンス中にWebブラウザが落ちてしまった場合に

このようなメンテナンスモードが出ます。(ブラウザ上で処理ができなかったことが原因です)

サーバ自体を

sudo reboot

と再起動を行ってもその状態であることが多いです。

「処理が終わるまでブラウザを落とさず待つ」が正常な手順ですが、それを怠った場合のリカバリについてです。

動作環境

  • Ubuntu 20.04
  • Nextcloud
  • Apache 2.4
  • PHP8.1

さっくりとした手順

  1. Nextcloudサーバにアクセスします。
  2. 設定ファイルを書き換えます。
  3. Apacheサービスを再起動します。
  4. メンテナンスモードの解除を確認します。

Nextcloudサーバへのアクセス

cd /home/www-data/nextcloud/config && pwd
# 自分のディレクトリを指定します

コンフィグファイルのバックアップ

sudo cp -pi config.php /path/to/backup/directory/config.php.$(date +%Y%m%d)

ファイルの内容書き換え

sudo -u www-data sed -i "s/'maintenance' => true/'maintenance' => false/" config.php
# メンテナンスモードを無効化します。

apache2サービス再起動

sudo systemctl restart apache2.service

再起動後の確認

メンテナンスモードが解除されました。「アップデートを開始」をクリックします。(今度はブラウザを閉じないようにしましょう)

その後、NextcloudのWeb画面が出てきたので問題なくアップデートされました。

サイトのSSL強化。(HSTSプリロード)

概要

サイトのセキュリティを高めるため、HSTSプリロードを設定したときのメモとなります。

環境

  • OS: Ubuntu 20.04
  • Apache 2.4系
  • Let's Encryptで取得した証明書を利用

前提条件

  1. インターネット上に公開されたサイトであること。(非ローカル環境)
  2. 公開するWebサイトドメイン全てに適切な証明書が設定されていること。
  3. Webサーバの設定で、httpアクセス全てをhttpsに変換する設定になっていること。
  4. 必要なモジュール(header、SSL等)がインストールされていること。

ここでは、hoge.example.com というサイトに対してHSTSプリロードを設定します。

注意点

  • サブドメイン全てに対して適用されます。(hoge.example.comの場合はwww.example.comはもちろん、example.comも対象となることを注意してください)
  • https化されていないサイトに対してもhttps接続を強制します。つまり、他にhttps化されていないシステムに対してもです。
  • プリロードリストに登録された場合、解除はとても難しくなります。相応の運用が試されることに注意してください。

さっくりとした手順

  1. HSTSを有効にします。
  2. httpdサービスを再起動します。
  3. HSTSサイトにドメインを登録します。

実施手順

apacheのバーチャルサイトファイルを修正します。

  • 修正後のファイル

※ドメインやDocumentRoot等は書き換えてください。また、サブドメインごとに複数のサイトがある場合、その全てを修正します。

<VirtualHost _default_:80>
servername hoge.example.com
 RewriteEngine On
        RewriteCond %{HTTPS} off
        RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>
<VirtualHost _default_:443>
    servername hoge.example.com
    ErrorLog /var/log/apache/error.log
    CustomLog /var/log/apache/access.log combined

DocumentRoot /var/www/html/hoge

    <Directory /var/www/html/hoge>
        Options -MultiViews
        AllowOverride All
        Require all granted
    </Directory>

  SSLEngine on
    Protocols h2 http/1.1
    Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

SSLCertificateFile /etc/certs/hoge.example.com.crt
SSLCertificateKeyFile /etc/private/hoge.example.com.key

</VirtualHost>

SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1 -TLSv1.2
SSLCipherSuite          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder     off
SSLSessionTickets       off
  • 主な差分
-    Header always set Strict-Transport-Security "max-age=63072000"
+    Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

-SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1
+SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1 -TLSv1.2
  • HSTSのプリロードを有効化しています。
  • ついでに弱いSSL(TLSv1.2)を無効化します。

apacheサービスを再起動します。

sudo apache2ctl configtest
# Syntax OKを確認します
sudo systemctl restart apache2.service

systemctl satus apache2.service
# active(running)を確認します。

HSTSプリロードサイトへの登録

  1. https://hstspreload.org/ にアクセスします。
  2. 上記で設定したドメイン名を入力して登録を進めていきます。(サブドメインは含みません)
  3. エラーがなければStatus: laplacemine.com is pending submission to the preload list.と表示されます。
  4. 2~3週間ほど待って正式に登録されるのを待ちます。

設定確認

  1. https://www.ssllabs.com/ssltest にアクセスします。
  2. HSTSを設定したサイトのドメイン名を入力して診断します。
  3. Strict Transport Security (HSTS) が「YEえs」となっていれば成功です。

タイムタグ、ライフログ。

Twitterの話題が元で:

英国に滞在していたときの記憶が蘇りました。なので、AWSにて管理しているPiwigoの写真を更新です。

ロンドン

https://hideout.reisalin.com/index.php?/category/7

こちらはテムズ川のクルーズに絞ったもの。

当時は晴れた日ばかりを選んで撮影したはずですが、こうしてみるとくすんだ空の色です。

コーンウォール

https://hideout.reisalin.com/index.php?/category/1

願わくば、6~7月にもう一度行きたい場所。自分にとって初めて目にする大西洋にも感動しました。

カンタベリー

https://hideout.reisalin.com/index.php?/category/12

ここも暮らしていた場所なので、感慨深いです。

改めて:写真というのは自分の思い出をタグ付けするものであり、明確な記録(ログ)であると思いました。

Mod_Securityが検知したIPアドレスの自動遮断スクリプト・修正。

以下のスクリプトを修正しました。

このスクリプトの主な動き

  1. Mod_Securityが検知したエラーログからIPアドレスのみを抜き出す。
  2. 重複を排除した上でsuscpicious_ip.YYYYMMDD形式で保存。
  3. 全てのsuscpicious_ip.YYYYMMDDを統合する。
  4. ここからnegativelist.txtを作成する。
  5. negativelist.txtの中に疑陽性(自身のアクセス元)のIPを排除する。
  6. Webサービスを再起動する。

そうして、「一度でもMod_Securityが疑わしいと検知すれば、次回以降のアクセスを許さない」という、言わば“ONE OUTS”システムを採用しています。

この可読性を高めました。

スクリプトが動く前提

  • ApacheとMod_Securityを運用している。
  • 以下のように、「negativelist.txt」に記録されたIP全てをブロックするようにしている。

apacheバーチャルサイト設定の抜粋

# Mod Security
SecRuleEngine On
## ModSecurity有効化
SecRequestBodyInMemoryLimit 524288000
SecRequestBodyLimit 524288000
## ファイルのアップロードをできるようにします。
    # ネガティブリスト
    SecRule REMOTE_ADDR "@pmFromFile negativelist.txt" "phase:1,id:2,deny,msg:'Negativelisted IP address'"

修正したスクリプト

※ 教義・信仰に沿ったエディタで記載します。

  • negativelist.sh
#!/bin/bash
# このシェルスクリプトは、変数で定義したエラーログからIPアドレスを抽出し、
# suspicious_ipディレクトリに保存し、その後、特定のIPアドレスを削除して
# /etc/apache2/sites-available/negativelist.txtに書き込むものです。

# 読み込むログのディレクトリとファイル名を変数指定
log_dir="/var/lib/redmine/log"
log_file="error.log"

# 除外するIPアドレスをファイルで指定
exclude_ips_file="/path/to/exclude_ips.txt"

# IPアドレスを抽出して重複を排除し、ファイルに保存
cd "$log_dir"
awk 'match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) { print substr($0, RSTART, RLENGTH) }' "$log_file" | sort | uniq > "$log_dir/suspicious_ip/suspicious_ip.$(date +%Y%m%d)"
chown www-data:www-data "$log_dir/suspicious_ip/suspicious_ip.$(date +%Y%m%d)"

# 過去のIPアドレスを読み込んで重複を排除し、ファイルに保存
cat "$log_dir/suspicious_ip/suspicious_ip."2* | sort | uniq > "$log_dir/suspicious_ip_all.txt"
chown www-data:www-data "$log_dir/suspicious_ip_all.txt"

# 新たにリストに書き起こす
cat "$log_dir/suspicious_ip_all.txt" > /etc/apache2/sites-available/negativelist.txt

# 除外するIPアドレスをファイルから削除
while IFS= read -r exclude_ip; do
  sed -i "/$exclude_ip/d" /etc/apache2/sites-available/negativelist.txt
done < "$exclude_ips_file"

# Apacheを再起動
systemctl restart apache2.service
  • 除外するIPアドレスリスト

※ 教義・信仰に沿ったエディタで作成します。

  • exclude_ips.txt 記載例
192.168.0.1
172.28.0.1
# 一行ずつ記載

記載後の設定

  • スクリプトの所有者変更
sudo chown root:root negativelist.sh
  • スクリプトの実行権付与
sudo chmod 744 negativelist.sh
  • cron登録
sudo crontab -e -u root
  • cron内容
0 6 * * * /home/manualmaton/bin/negativelist.sh

これによって、スクリプトを変数化。他のサーバへの転用を行いやすくしました。

Let’s Encryptの証明書をRSA方式で更新。

以前ご案内した、Let's Encryptのデフォルト暗号化形式がデフォルトでECDSA方式に変更されたという話。

ただ、サーバの環境によっては、この暗号化形式をサポートしていない事があります。(ワイルドカード証明書を様々なサーバに適用するケースでありがちです)
本来ならばサーバそのもののバージョンアップを図るべきでしょうが、運用によってはままならず。

そんなときにLet's Encryptの暗号化を従来のRSA方式に変える方法をメモしておきます。

前提

  • Let's EncryptでSSLを利用している。
  • 適用するサーバがECDSA方式の暗号化形式に対応していない。

作業手順

Let's Encrypt(Certbot)サーバで実施します。

ここでは、

  • hoge.example.com ドメインのワイルドカード証明書を取得し
  • 有効期限前にhoge@example.com宛にメールを送付する

として手順を示します。

証明書更新

sudo certbot certonly --manual -d\
*.hoge.example.com\
 -m hoge@example.com\
 --agree-tos --manual-public-ip-logging-ok\
 --key-type rsa --preferred-challenges dns-01
# ディレクトリやメールアドレスは自身の環境に合わせます。
# --key-type rsa を明示します

この後、DNSでTXTレコードを設定するよう求められるので、それに従いDNSの所有権を確認します。

確認されたら証明書は更新されます。

証明書と鍵の整合性確認

openssl x509 -pubkey -in /etc/letsencrypt/live/hoge.example.com/cert.pem -noout | openssl md5
(stdin)= ハッシュ値
# SSL証明書ファイル

openssl pkey -pubout -in /etc/letsencrypt/live/hoge.example.com/pprivkey.pem | openssl md5
(stdin)= ハッシュ値
# 秘密鍵ファイル

## Let's Encryptで指定されたディレクトリや証明書・秘密鍵を指定してください
## 2つのハッシュ値が合っていれば証明書と秘密鍵の整合性は取れています

証明書の鍵方式確認

openssl rsa -text -noout -in /etc/letsencrypt/live/hoge.example.com/pprivkey.pem
# 正常に表示されればRSA方式で暗号化されています

後は、指定したディレクトリの証明書や秘密鍵を適切に他サーバに適用します。

Redmineの不正アクセス対策。(ufwと二段階認証)

概要

AWS Lightsailに構築しているRedmine。 不審なアクセスがあったので対応を行いました。

アクセスの内容

とてもシンプルに、チケットの新規発行画面に何回もアクセスしているというもの。

正規のリクエストなのでWAFでブロックされません。(解析システム:matomoで検知した次第です)

そもそも自分しかアカウントを用意していないため、この時点で不正アクセスの兆候だと判断。以下、対処を行います。

ufwでの処理

  • ufwによるブロック
sudo ufw deny from IPアドレス
# より確実を期すためにIPアドレスのネットワークアドレスを指定しました (xxx.xxx.xxx.0/24)
  • 設定確認
sudo ufw status numbered
# Anywhere DENY IN 上記で指定したIP/ネットワークアドレスを確認します
  • 設定反映
sudo ufw reload
# ファイアウォールを再読込しましたと出れば反映完了です

これでひとまず不審なアクセス元は遮断。

Redmineログイン強化

筆者が用いているRedmine4.2は二段階認証が標準で備わっていますので、それを有効化します。

  1. Redmineに管理者権限でログインします。
  2. 万一に備えて別のブラウザでもログインしっぱなしにします。
  3. 管理>設定>認証に移動します。
  4. 二段階認証を「必須」にして保存します。

その後、(別ブラウザでログインしたまま)Redmineにログイン。

後は二段階認証プロセス(Google認証システムを用いました)で指示に従ってQRコードを読み込み、生成されたコードを読み込むだけ。

ひとまず、これでID/PWによるログインに加えて認証システムの二段階で不正アクセスの被害を抑えます。

growi v6.0.15 → v6.1.0へのバージョンアップ後の処理。

結論から始まる概要

「リリースノートはよく読んでおくこと」

です。

Growi v6.1.0の変更点

バージョンアップ後、今まで表示されていた画像がうまく表示されない問題点がありました。

どうしたものかと更新情報を読み返したら

https://docs.growi.org/ja/admin-guide/upgrading/61x.html#%E7%AE%A1%E7%90%86%E8%80%85%E5%90%91%E3%81%91

と思いっきり書かれておりました。

では、GrowiをインストールしたLinuxサーバで対処を行います。

前提

  • Growi v6.1.0にバージョンアップした
  • 添付ファイルをローカルに保存

が作業の前提です。また、

  • Ubuntu 20.04
  • ディレクトリは'/opt/growi'

となっています。

実施した手順

Growiインストールディレクトリに移動

cd /opt/growi/packages/app/public/uploads && pwd
# 上記ディレクトリにいることを確認します。

添付ファイルディレクトリを移動

sudo mv attachment /opt/growi/apps/app/public/uploads/
sudo mv user /opt/growi/apps/app/public/uploads/

移動確認

cd /opt/growi/apps/app/public/uploads/ && pwd
# 上記ディレクトリにいることを確認します。

ls -l attachment
ls -l user
# 移動したディレクトリがあることを確認します。

作業後の確認

バージョンアップ前に投稿した添付ファイルがある記事で、ファイルが表示されていることを確認しました。

Redmineによる旅の準備とフィードバック。

Redmineコメントのテンプレート

個人的に用いているRedmine。一つのチケットにコメントを連ねていくことで、準備や事前情報などを系統立てて表示させることができます。

そこで「携行品はある程度傾向があるから、テンプレートプラグインで管理できそうだ」

と、こういう風にコメントテンプレートで管理。

しかし、ここに落とし穴がありました。

想定の漏れ

これは家族に言われて気づいたことです。

  • 東京都心と山間は気温がまるで違うこと
  • 温泉の湯冷め

などを全く考慮していませんでした。思い直してリパッキング。

この状況もチケットに書き足していきます。

そうして、旅の途上での出来事も次々に書いていき、

デブリーフィング

もチケット自体に記載。

こうして、旅自体を振り返りながら

  • 何をミスっていたか
  • 次はどうすれば良いか
  • 印象に残っていたことは

なども気軽に書けるので、そこは、Redmineを運用して良かったと思ったわけで。

Page 24 of 50

Powered by WordPress & Theme by Anders Norén