ノートPCでゲームをする機会が増えたので、小型軽量のコントローラーを購入。

中身は箱とほぼ同じ


これだけコンパクトなのはありがたいのですが、

ユーティリティバッグに入らなくなりました。そこで、

母手作りのポーチに差し替えです。これなら
- ACアダプター
- マウス
- イヤホン
- ケーブル
- コントローラー
をいれてもスッキリ収まります。スリザリン要素が少なくなったのはストラップで担保。後の拡張性にも備えられるものになりました。
ノートPCでゲームをする機会が増えたので、小型軽量のコントローラーを購入。

中身は箱とほぼ同じ


これだけコンパクトなのはありがたいのですが、

ユーティリティバッグに入らなくなりました。そこで、

母手作りのポーチに差し替えです。これなら
をいれてもスッキリ収まります。スリザリン要素が少なくなったのはストラップで担保。後の拡張性にも備えられるものになりました。
こちらの記事から約一年。
8/03 : 契約、初期設定(UFW / fail2ban)
とあることから、実質丸一年が経過。その1年での振り返りを行ってみたいです。
2026年8月時点でのリソース使用量
--- 💻 サーバーのCPU状態 ---
稼働時間 (Uptime): 8 days
ロードアベレージ (Load Avg): 0.22, 0.22, 0.19
CPU名 (Model): AMD EPYC-Milan Processor
スペック (Speed): 2.00 GHz (1996.250 MHz)
コア数 (Cores): 4 threads
--- メモリとスワップ ---
[物理メモリ(Physical Memory)]
total used free shared buff/cache available
Mem: 5.8Gi 3.7Gi 447Mi 163Mi 2.1Gi 2.1Gi
Swap: 4.9Gi 1.1Gi 3.8Gi
[zRAM の展開状況]
NAME DISKSIZE DATA COMPR ALGORITHM STREAMS ZERO-PAGES TOTAL MEM-LIMIT MEM-USED MIGRATED MOUNTPOINT
/dev/zram0 2.9G 1.1G 254.4M lzo-rle 4 50834 261.6M 0B 948.3M 199K [SWAP]
--- ストレージ(Storage Status) ---
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 145G 62G 83G 43% /
/dev/vda16 881M 222M 598M 28% /boot
/dev/vda15 105M 6.2M 99M 6% /boot/efi
s3fs 4.0G 0 4.0G 0% /mnt/wasabi2
s3fs 4.0G 0 4.0G 0% /mnt/wasabi
--- CPUを利用しているプロセス: CPU Consumers (Top 10) ---
%CPU %MEM PID USER UNIT COMMAND
------------------------------------------------------------------------------------------
8.0 4.3 796409 www-data apache2.service Passenger RubyApp:
4.4 6.8 621372 mysql mysql.service /usr/sbin/mysqld
2.8 3.6 796362 www-data apache2.service Passenger AppPreloader:
1.1 2.0 789277 www-data apache2.service /usr/sbin/apache2 -k start
0.7 2.1 784299 www-data apache2.service /usr/sbin/apache2 -k start
0.6 2.0 784297 www-data apache2.service /usr/sbin/apache2 -k start
0.6 3.9 622142 root growi.service node --import
0.6 1.8 620879 mongodb mongod.service /usr/bin/mongod --config /etc/mongod.conf
0.5 0.4 784275 root apache2.service Passenger core
0.5 0.2 622750 www-data apache2.service /usr/sbin/apache2 -k start
--- メモリを利用しているプロセス: Memory Consumers (Top 10) ---
%CPU %MEM PID USER UNIT COMMAND
------------------------------------------------------------------------------------------
0.4 11.2 479114 elastic+ elasticsearch.service /usr/share/elasticsearch/jdk/bin/java -Des.network
4.4 6.8 621372 mysql mysql.service /usr/sbin/mysqld
8.0 4.3 796409 www-data apache2.service Passenger RubyApp:
0.0 4.1 786930 www-data apache2.service Passenger RubyApp:
0.6 3.9 622142 root growi.service node --import ./bin/runtime/env-preload.mjs dist/s
0.0 3.8 796066 www-data apache2.service Passenger RubyApp:
2.8 3.6 796362 www-data apache2.service Passenger AppPreloader:
0.0 3.2 990 root mnt-wasabi.mount
0.2 2.9 789814 www-data php8.3-fpm.service php-fpm: pool www
0.4 2.8 794701 www-data php8.3-fpm.service php-fpm: pool www
何というか
というメモリを食いまくるサイト(そのほかLaravel Stack)を運営していてOoM Killerが発生しなかったものだと思っています。
これが一番のポイントです。筆者は広告が嫌いなので、自分のサイトにも作っていません。そのため、SEOや広告料収入によるアクセスアップを狙っていません。
「これは俺のメモ帳だ。節度を持ってアクセスする分にはかまわないがそれ以外は容赦しない」
というスタンスを貫いています。
更に、tcpレベルでの嫌がらせをやらかす相手にはipsetで防御。
https://barrel.reisalin.com/books/one-outs/page/ipsetddos
先にあった、Swapにブロックデバイスを追加することにより、スワップアウトが更に効率化しています。
https://barrel.reisalin.com/books/linux/page/ubuntuzram
これが一番です。Mod_Securityを「偽陽性を踏んだから単にそれをRemoveしよう」という雑な運用から
「偽陽性を踏みがちなアクション(記事の投稿、ファイルのアップロード)だけを無視する」というリアルタイム外科手術的な技法へと変換。
これにより
「攻撃は防ぐ 偽陽性は排除する おまえごときに『両方』やるのは そうそう難しいことじゃあないな」
と言えるようになったのが極めて大きいです。
「4GB→6GB」にスペックアップしたとしても普通に運用したらOoM Killerやアクセス過多に陥ったであろうシステムを
AIの力を借りての運用という形でした。
筆者にとっての必須エディタ、Growi。そのv8.0.0が出たので、以下の要件に基づきアップデートを行いました。
実施日: 2026年7月29日
対象環境: Ubuntu 24.04 (非Docker環境 / systemd運用)
その他要件:
| item | version |
|---|---|
| OS | Ubuntu 24.04 |
| GROWI | 7.5.7 |
| node.js | 24.14.1 |
| npm | 11.13.0 |
| pnpm | 11.1.1 |
GROWIの最新リリースにおける変更点(ES7の完全廃止、jemalloc対応、メモリ最適化、ESM移行)に対する自環境の適合状況を確認。
ES8/ES9のみに対応しているため、以下を確認。
curl -X GET "http://localhost:9200/" |grep number
→ 9.4.4となっていたので、要件を満たすことは確認しました。
ldconfig -p | grep jemalloc
libjemalloc.so.2 (libc6,x86-64) => /lib/x86_64-linux-gnu/libjemalloc.so.2と出たのでモジュールも確認済みです。
ここまでやれば、覚悟を決めてアップデートを行います。
※筆者は
systemdに登録したサービス起動プログラムがGrowiのルートディレクトリ/home/www-data/growi配下にあるgrowi-start.shを参照して各種環境をキックしています。
※ご自身の環境に合わせ修正を行ってください※
#!/bin/bash
# nvmのdefaultエイリアスが指すディレクトリを動的に取得してPATHに追加
# これにより、nvm installでバージョンを上げてもこのスクリプトの書き換えが不要になります
DEFAULT_NODE_VER=$(cat "$NVM_DIR/alias/default")
export PATH="$NVM_DIR/versions/node/$DEFAULT_NODE_VER/bin:$PATH"
GROWI_DIR="/home/www-data/growi"
cd $GROWI_DIR
# 環境変数の設定
export NODE_ENV=production
export AUDIT_LOG_ENABLED=true
export FORCE_WIKI_MODE=private
export MONGO_URI=mongodb://localhost:27017/growi
export ELASTICSEARCH_URI=http://localhost:9200/growi
export REDIS_URI=redis://localhost:6379
export PASSWORD_SEED=(設定済みのパスワード)
# npm run app:server を使用する(npmが内部で正しいパスを見つけてくれます)
# execを使うことでsystemdとの親和性を維持します
exec npm run app:server
このファイルを修正していきますが:バックアップを確実に行います。
sudo cp -pi /home/www-data/growi/growi-start.sh /path/to/backup/directory/growi-start.sh.$(date +%Y%m%d)
diff -u /path/to/backup/directory/growi-start.sh.$(date +%Y%m%d) /home/www-data/growi/growi-start.sh
エラー(差分)がなければ両者ともファイルがあり、バックアップが取れています。
バックアップ後、/home/www-data/growi/growi-start.shの編集を行います。(自分の環境に合わせます)
export JEMALLOC_ENABLED=true を追加export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 を追加MONGO_URI に ?maxPoolSize=10 パラメータを付与具体的には以下のような差分が取れていればOKです。
diff -u /path/to/backup/directory/growi-start.sh.$(date +%Y%m%d) /home/www-data/growi/growi-start.sh
# 環境変数の設定
export NODE_ENV=production
+export JEMALLOC_ENABLED=true
+export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2
export AUDIT_LOG_ENABLED=true
export FORCE_WIKI_MODE=private
-export MONGO_URI=mongodb://localhost:27017/growi
+export MONGO_URI=mongodb://localhost:27017/growi?maxPoolSize=10
export ELASTICSEARCH_URI=http://localhost:9200/growi
export REDIS_URI=redis://localhost:6379
sudo systemctl restart growi.service
指定した環境変数および jemalloc ライブラリが GROWI プロセス(Node.js)へ正常にロードされていることを確認しました。
JEMALLOC_ENABLED=true および LD_PRELOAD が正常に適用されていることを確認。lsof および /proc/{PID}/maps コマンドにより、libjemalloc.so.2 が Node.js プロセスに読み込まれていることを確認。以下をバックアップします。
cat /etc/mongod.conf |grep dbPath
として、ここのディレクトリ一式を控えます。(筆者環境 /home/mongodb)
このディレクトリを任意の方法でバックアップします。
/growi/root/directory/apps/app/public
(筆者環境 /home/www-data/growi/apps/app/public)ここも念のためバックアップします。
※ 添付ファイルのアップロード先をAWSやAzureなどにしている場合は不要です
スナップショット機能などでシステム全体をバックアップした方が確実で安心です。
sudo systemctl stop elasticsearch.service
sudo systemctl stop growi.service
systemctl status elasticsearch.service growi.service | grep Active
inactive(dead)を確認します。
sudo cp -a /var/lib/elasticsearch/ /path/to/backup/dir/elastic_bk.$(date +%Y%m%d)
自分の環境に合わせます。
sudo ls -l /path/to/backup/dir/elastic_bk.$(date +%Y%m%d)
バックアップした内容があることを確認します。(※管理者権限でないとこのディレクトリを見ることはできません)
cd /home/www-data/growi && pwd
自分の環境に合わせます。(筆者環境/home/www-data/growi)
sudo git fetch --tags
sudo git tag -l
スペースで確認していき、上記リリースサイトと同じバージョンがあることを確認します。
sudo git stash
sudo git checkout 【バージョン】
リリースタグは再確認しましょう。今回は 2026/07/28にリリースされたv8.0.0を選択しました。
sudo pnpm i
※これができるのは、筆者のgrowi実行環境がrootだからです。このパーミッション設定は確実に確認しましょう。
NODE_OPTIONS="--max-old-space-size=4096" sudo pnpm run app:build
→ ビルド時のメモリ大量使用を抑えるため上限を抑えています。余談ですが、ここは神に祈る作業です。
sudo systemctl restart elasticsearch.service
sudo systemctl restart growi.service
systemctl status elasticsearch.service growi.service | grep Active
active(running)を確認します。
※一般権限で見られないため
sudo su -
pgrep -f "node.*growi" | xargs -I {} lsof -p {} 2>/dev/null | grep jemalloc
MainThrea 479521 root mem REG 253,1 830656 15385 /usr/lib/x86_64-linux-gnu/libjemalloc.so.2
必要に応じてバックアップしたファイル一式やスナップショットを削除します。
体温以上の暑さが続く中、これだけは外せないという暑さ対策グッズはこれに落ち着きました。

ワークマンにて購入。
直射日光を遮ることで、体感温度は数度から10℃近く下がると言われています。また、輻射熱を遮る点でも重要です。
強い紫外線、まぶしさは目から入って脳に疲労物質を出させる原因になります。
普段の眼鏡と同じ度にすることで、普段の視界のまましっかり減光できます。
血管が集まる首元、首の横、脇の下、手首などを直接冷やせます。
この対策グッズでもMVPです。ハンディファンで生暖かい風を浴びるより合理的です。

このシンデレラフィットするかのようなヒップバッグも見つけられました。これで鞄にもつけられるので満足。
この暑い夏は始まったばかりですが、なんとか死なないように抑えていきたいものです。
BookStackでは「アプリケーションロゴ」を設定できますが、そのままではアップロードした画像が高さ86pxへリサイズされてしまいます。
そのため、CSSでロゴを大きく表示すると画像がぼやけてしまいます。そもそも86pxは昨今のモダンなCMSにあるまじき解像度ではあるので、手を入れます。
そこでファイル本体を少し修正し、高解像度のロゴ画像をそのまま利用できるようにしました。
BookStackに管理者権限でログインし、管理>カスタマイズに遷移。
カスタムheadタグで
<style>
.logo-image {
height: 128px !important;
width: auto !important;
}
</style>
のような指定はできるものの、超ローレぞ加工され、表示がぼやけます。そこで、要素を調べると、保存された画像自体が86×86になっていました。
この原因を調べます。
インストールされているUbuntuサーバで
cd /path/to/BookStack/directory && pwd
として(筆者環境/home/www-data/Bookstack)BookStackのホームディレクトリに移動。
file public/uploads/images/system/20xx-xx/xxxx.jpg
で、該当のファイルを調べます。
JPEG image data
86x86
つまり、CSSではなくアップロード時に画像が縮小されていました。
いかにCSSで指定してもだめな原因はプログラムそのものにあります。なので、その上流の「ファイルのアップロードを司るファイル」にメスを入れます。
それを司るファイルをチャットAIとともに調査。
BookStackのルートディレクトリからたどれる
app/Settings/AppSettingsStore.php
にそれがありました。
protected function updateAppLogo(Request $request): void
{
if ($request->hasFile('app_logo')) {
$logoFile = $request->file('app_logo');
$this->destroyExistingSettingImage('app-logo');
$image = $this->imageRepo->saveNew(
$logoFile,
'system',
0,
null,
86
);
setting()->put('app-logo', $image->url);
}
}
null,
86
が指定されているため、高さ86pxへリサイズされた画像が保存されます。
ここまで分かれば、後は修正開始です。
cd /path/to/BookStack/directory && pwd
自分の環境に合わせます。(筆者環境/home/www-data/Bookstack)
sudo cp -pi app/Settings/AppSettingsStore.php /path/to/backup/AppSettingsStore.php.$(date +%Y%m%d)
※注意点※
diff -u /path/to/backup/AppSettingsStore.php.$(date +%Y%m%d) app/Settings/AppSettingsStore.php
任意のバックアップディレクトリを指定します。
エラーがないことを確認します。人間「バックアップはやってる」と思いながらもバイアスや手なりでスキップしがちです。この段階でそのミスやバイアスを潰します。
なぜdiffを使うのかは、ls -lで両ファイルを比べるより確実だからと言うのと、後述する修正確認でも使うからです。
app/Settings/AppSettingsStore.phpファイルを、リサイズを行わないよう変更します。(要管理者権限)
具体的には以下の差分になるように。
- $image = $this->imageRepo->saveNew($logoFile, 'system', 0, null, 86);
+ $image = $this->imageRepo->saveNew($logoFile, 'system', 0, null, null);
diff -u /path/to/backup/AppSettingsStore.php.$(date +%Y%m%d) app/Settings/AppSettingsStore.php
ここで、なぜdiffを逆にする意味が生まれます。逆にしないと直したところが-、元が+で表示されます。これは視覚的にも感覚的にもよろしくありません。「え? 正しい修正をしたのに消されるの?」となりがちです。
sudo -u www-data php artisan optimize:clear
でキャッシュをクリアします。
PHP-FPMなら
sudo systemctl restart php8.3-fpm
Mod-PHP環境なら
sudo systemctl restart apache2
で、実行環境を再起動します。
BookStackに管理者権限でログインし、管理>カスタマイズに遷移。
カスタムheadタグで
<style>
.logo-image {
height: 128px !important;
width: auto !important;
}
</style>
のように設定し、(或いは設定されていることを確認し)、保存をクリック。
管理>カスタマイズ
から、ファイルをアップロードします。
BookStack標準ではヘッダー高さが少し窮屈なので、必要に応じてヘッダーも調整します。
例
header {
min-height: 72px;
}
.logo-image {
height: 64px !important;
}
ここから先はBookStackに戻り、高解像度でロゴが表示されれば設定はOKです。

ワークマン、時々面白いものが見つかります。今回見つけたのはこちら。
モバイルバッテリー&ライト。

一見、ごついカラビナのようですが……

この付け根にUSBケーブルがついています。
つまり、モバイルバッテリーという取り回しに困るものを「ベルトや鞄に固定させる」ことで充電を可能にする仕掛け。
御丁寧に外で使うためIP66という認証までついています。それだけに留まらず

ライトつきです。動力そのものがバッテリーという、盲点のような状態。

注意点として:
と極性が固定されていることのようですのでケーブルに注意が必要でした。
いずれにしても、外出しでき、いざというときに迷わないバッテリーは重要です。
若干のアップデートがありました。
「とりあえず、これとスマートフォンがあれば大概の場所でも作業ができる」厳選道具群です。

下段左から
こちらは日記帳。2021年の1月に途切れましたが、そこからは日々欠かさず、全ての日付で書いています。
カバーは『SPY×FAMILY』コラボ。
出先での母艦です。一時期、やたらと画面がオフになり、どうすんだこれ状態に陥りかけましたが、のぞき見防止フィルターが触れた面でそうなっているだけと判明。その位置を調整して事なきを得ています。
混雑した電車の中で用いるメインウエポン。様々なタブレットを触った中で
と、忙しいときでもブログが書け、電子書籍リーダーとしても八面六臂の活躍。少しバッテリーが怪しいので次世代をどうするかが懸案中です。
スリザリン×アフターヌーンティーコラボ。
などのジャストサイズ。
母手製の大容量ペンケース。LAMYぎっしり。課題は万年筆がおざなりなってしまうこと。メンテンアンス頻度を上げていく工夫が求められます。
こちらは利用頻度が上がってきました。メモ帳だけでなく、L判縦の写真がそのまま貼り付けられるサイズ感も気に入っています。
と、それなりに量はありますが、これがないと私の一日は始まらないレベルの必須品です。
Ubuntuサーバ設定時、時々迷ってしまう
「どのファイルがどのパッケージに属しているか?」
問題。その道しるべになり得るコマンドのメモです。
dpkg -S コマンドを使うのが一番手っ取り早くて確実です。apt パッケージ管理システムの実体は、バックエンドで dpkg を使っているため、このコマンドがそのまま使えます。
基本的な使い方は以下の通りです。
dpkg -S /パス/to/ファイル名
調べたいファイルの絶対パスがわかっている場合は、そのまま指定します。
dpkg -S /etc/logrotate.d/apache2
出力例:
apache2: /etc/logrotate.d/apache2
コロン(:)の左側に表示されている apache2 がパッケージ名です。
絶対パスが思い出せない場合は、ファイル名の一部だけでも検索できます。
dpkg -S logrotate.d/apache2
注意点: ファイル名だけで検索すると、その文字列にマッチするすべてのパッケージとファイルパスが一覧で出力されます。そのため、できるだけ具体的なパスを指定した方がノイズが少なくなります。
「まだシステムに入れていないけれど、/etc/xxxx という設定ファイルを入れるには、どのパッケージをインストールすればいいか?」を知りたい場合は、apt-file というツールが便利です。
まずツールをインストールしてデータベースを更新します。(筆者の好みでaptitudeを用いています)
sudo aptitude install apt-file
コマンドインストール後、DBをアップデート。
sudo apt-file update
その後、以下のように検索します。
apt-file search /etc/logrotate.d/apache2
これを使えば、手元の環境にないファイルでも、どのパッケージに含まれているかを一発で特定できます。
なんかの都合で設定ファイルの名前を変えてしまったときに役立ちます。(やらかしました)
論争があるのは知っていますが、それでも、これを紹介する理由があります。
「複数行の選択を可能に出来た」
という今更ながらの感動があったので。
| 操作 | キー |
|---|---|
| 保存 | Ctrl + O |
| Enterで保存確定 | Enter |
| 終了 | Ctrl + X |
| 操作 | キー |
|---|---|
| 上・下・左・右 | 矢印キー |
| 行頭へ移動 | Ctrl + A |
| 行末へ移動 | Ctrl + E |
| 1ページ上 | Ctrl + Y |
| 1ページ下 | Ctrl + V |
| 操作 | キー |
|---|---|
| 検索 | Ctrl + W |
| 次を検索 | Alt + W |
| 置換 | Ctrl + \ |
| 操作 | キー |
|---|---|
| 行を切り取り(削除) | Ctrl + K |
| 貼り付け | Ctrl + U |
Esc → A(または Ctrl + ^)でマーク開始| 操作 | キー |
|---|---|
| 選択範囲を切り取り(削除) | Ctrl + K |
| 選択範囲をコピー | Alt + 6 |
| 貼り付け | Ctrl + U |
| 操作 | キー |
|---|---|
| 元に戻す | Alt + U |
| やり直し | Alt + E |
| 操作 | キー |
|---|---|
| ヘルプ | Ctrl + G |
| カーソル位置表示 | Ctrl + C |
| 指定行へジャンプ | Ctrl + _ |
| コマンド一覧表示 | Ctrl + G |
^ = Ctrl
M- = Alt(Metaキー)
Altキーが効かない端末では、
Esc を押して離し、その後キーを押す
例:
Esc → A = Alt + AEsc → U = Alt + UEsc → 6 = Alt + 6Esc → A
↓で範囲選択
Ctrl + K
Esc → A
↓で範囲選択
Alt + 6
Ctrl + U
Ctrl + W
検索文字入力
Enter
Ctrl + \
検索文字
Enter
置換文字
Enter
筆者に限らず、Webサーバを運用すると必ずと言っていいほど見かけるアクセスがあります。
GET /wp-login.php
GET /wp-admin/
GET /wp-config.php
GET /config.php
GET /.env
言わずと知れたWordpress/laravel管理画面のURLやDB情報などが飛び交う重要ファイル。
「うちはWordPressじゃないんだけど?」
と思う人も多いでしょう。実際、筆者のVPSもWordPressを詰んでいません。(公開しているWordpressは専用サービスを借りています)
それでも毎日のように飛んできます。では、攻撃者は何を考えて「見たらアクセスするのが礼儀」レベルでアクセスしてきているのでしょうか。
多くの人は、「誰かが自分のサイトを狙っている」と考えがちです。
しかし実際には逆です。攻撃者は運営元をまず見ません。彼らが見ているのは
「世界中に存在する何千万台ものWebサーバ」
です。ですから
WordPress
Laravel
Node.js
Next.js
Joomla
Drupal
といった利用者が非常に多い技術から順番に試します。
WordPressは世界中のWebサイトのかなりの割合を占めています。つまり、攻撃者は
「WordPressだけ狙う」
だけでも膨大な成果が期待できます。さらに
なども珍しくありません。攻撃者から見ると、WordPressは「狙う価値が非常に高い標的」です。
そして、Wordpressは
/wp-config.php
/wp-config-sample.php
/wp-login.php
など、「アキレス腱となるファイル」がほぼ決まっているという「やりやすい」材料です。
以下は実際に筆者のサーバへ届いたログを、IPアドレスやホスト名をダミー化したものです。
なぜ、この手の攻撃者情報を晒さないかというと「テロリストに名前を与える必要はない」という哲学と、「誰がやったかは問題ではない。私が興味があるのは何をしたかである」という考えです。
[Mon Jul 06 01:06:34.509624 2026] [security2:error] [pid 111111:tid 222222222222222] [client 192.0.2.1:40372] [client 192.0.2.1] ModSecurity: Warning. Matched phrase "config.php" at REQUEST_FILENAME. [file "/usr/share/modsecurity-crs/coreruleset/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf"] [line "150"] [id "930130"] [msg "Restricted File Access Attempt"] [data "Matched Data: config.php found within REQUEST_FILENAME: /config.php"] [severity "CRITICAL"] [ver "OWASP_CRS/4.28.0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-lfi"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "OWASP_CRS/ATTACK-LFI"] [tag "capec/1000/255/153/126"] [hostname "example.com"] [uri "/config.php"] [unique_id "DUMMY_UNIQUE_ID_000001AAAAA"]
[Mon Jul 06 01:06:34.510601 2026] [security2:error] [pid 111111:tid 222222222222222] [client 192.0.2.1:40372] [client 192.0.2.1] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:blocking_inbound_anomaly_score. [file "/usr/share/modsecurity-crs/coreruleset/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "233"] [id "949110"] [msg "Inbound Anomaly Score Exceeded (Total Score: 5)"] [ver "OWASP_CRS/4.28.0"] [tag "anomaly-evaluation"] [tag "OWASP_CRS"] [hostname "example.com"] [uri "/config.php"] [unique_id "DUMMY_UNIQUE_ID_000001AAAAA"]
[Mon Jul 06 01:06:34.511256 2026] [security2:error] [pid 111111:tid 222222222222222] [client 192.0.2.1:40372] [client 192.0.2.1] ModSecurity: Warning. Unconditional match in SecAction. [file "/usr/share/modsecurity-crs/coreruleset/rules/RESPONSE-980-CORRELATION.conf"] [line "119"] [id "980170"] [msg "Anomaly Scores: (Inbound Scores: blocking=5, detection=5, per_pl=5-0-0-0, threshold=5) - (Outbound Scores: blocking=0, detection=0, per_pl=0-0-0-0, threshold=4) - (SQLI=0, XSS=0, RFI=0, LFI=5, RCE=0, PHPI=0, HTTP=0, SESS=0, COMBINED_SCORE=5)"] [ver "OWASP_CRS/4.28.0"] [tag "reporting"] [tag "OWASP_CRS"] [hostname "example.com"] [uri "/__jailhouse_lock/topgear.html"] [unique_id "DUMMY_UNIQUE_ID_000001AAAAA"]
[Mon Jul 06 01:06:40.426322 2026] [security2:error] [pid 333333:tid 444444444444444] [client 192.0.2.1:35882] [client 192.0.2.1] ModSecurity: Warning. Matched phrase "wp-config-" at REQUEST_FILENAME. [file "/usr/share/modsecurity-crs/coreruleset/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf"] [line "150"] [id "930130"] [msg "Restricted File Access Attempt"] [data "Matched Data: wp-config- found within REQUEST_FILENAME: /wp-config-sample.php"] [severity "CRITICAL"] [ver "OWASP_CRS/4.28.0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-lfi"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "OWASP_CRS/ATTACK-LFI"] [tag "capec/1000/255/153/126"] [hostname "example.com"] [uri "/wp-config-sample.php"] [unique_id "DUMMY_UNIQUE_ID_000002BBBBB"]
[Mon Jul 06 01:06:40.427672 2026] [security2:error] [pid 333333:tid 444444444444444] [client 192.0.2.1:35882] [client 192.0.2.1] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:blocking_inbound_anomaly_score. [file "/usr/share/modsecurity-crs/coreruleset/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "233"] [id "949110"] [msg "Inbound Anomaly Score Exceeded (Total Score: 5)"] [ver "OWASP_CRS/4.28.0"] [tag "anomaly-evaluation"] [tag "OWASP_CRS"] [hostname "example.com"] [uri "/wp-config-sample.php"] [unique_id "DUMMY_UNIQUE_ID_000002BBBBB"]
[Mon Jul 06 01:06:40.428290 2026] [security2:error] [pid 333333:tid 444444444444444] [client 192.0.2.1:35882] [client 192.0.2.1] ModSecurity: Warning. Unconditional match in SecAction. [file "/usr/share/modsecurity-crs/coreruleset/rules/RESPONSE-980-CORRELATION.conf"] [line "119"] [id "980170"] [msg "Anomaly Scores: (Inbound Scores: blocking=5, detection=5, per_pl=5-0-0-0, threshold=5) - (Outbound Scores: blocking=0, detection=0, per_pl=0-0-0-0, threshold=4) - (SQLI=0, XSS=0, RFI=0, LFI=5, RCE=0, PHPI=0, HTTP=0, SESS=0, COMBINED_SCORE=5)"] [ver "OWASP_CRS/4.28.0"] [tag "reporting"] [tag "OWASP_CRS"] [hostname "example.com"] [uri "/__jailhouse_lock/topgear.html"] [unique_id "DUMMY_UNIQUE_ID_000002BBBBB"]
要約するとこんな形です。
[client 192.0.2.1]
GET /config.php
REQUEST-930
Restricted File Access Attempt
↓
REQUEST-949
Inbound Anomaly Score Exceeded
↓
HTTP 403
数秒後、
GET /wp-config-sample.php
REQUEST-930
Restricted File Access Attempt
↓
REQUEST-949
Inbound Anomaly Score Exceeded
↓
HTTP 403
となりました。
筆者がこのログに着目したのは
config.php
↓
wp-config-sample.php
という順番です。これは、
という判定ルーチンそのもの。人間ならこの順番にはなりません。典型的な自動スキャナです。
以前紹介した、ModSecurityのカスタム設定。
HostヘッダーがIPアドレスなら遮断
Hostヘッダーが存在しなければ遮断
というカスタムルール。今回は一切反応しませんでした。
つまり攻撃者は
を組み立てています。IPアドレスへ適当に投げるだけのBOTより一段階上です。
そのためにModSecurityは通常の検査を実施し、
REQUEST-930
↓
REQUEST-949
↓
403
という流れで処理しています。
このログには、
OWASP CRSの典型的な動きがそのまま残っています。
CRS:930
危険なリクエストを検知
↓
CRS:949
異常スコアが閾値を超えた
↓
処理:403アクセス拒否
つまり、「ModSecurityがどのように判断して遮断するのか」を学ぶ教材として非常に分かりやすいログです。
今回の攻撃は、筆者個人を狙ったものではありません。世界中のWordPressサイトを探す途中で、たまたま筆者のLAMPサーバへ届いただけです。(何せ、動いているのは全く別のCMSです)
しかし、その「たまたま」からでも学べることはたくさんあります。
ログには、
がすべて残っています。
サーバ管理者にとってログは「嫌なもの」ではなく、攻撃者の思考を無料で教えてくれる教材です。
Powered by WordPress & Theme by Anders Norén