脆弱性図鑑シリーズ記念すべき第1回目はパストラバーサルについてです。
最近自分的にKADOKAWAの件もあってかWebセキュリティについて関心が強いので、理解を深める為にも今後も様々な脆弱性について取り上げて行こうと思っています。
主にエンジニア向けに書いているので、実際に問題のあるソースコードもなるべく載せるようにしようと思っていて、より脆弱性を身近に感じてもらえるようになれば嬉しく思います。
目次
パストラバーサルとは
パストラバーサル(Path Traversal)またはディレクトリトラバーサル(Directory Traversal)はWebアプリケーションに対する攻撃手法の一つで、攻撃者がファイルパスを操作する事で本来アクセスできないファイルシステム内の重要なファイルやディレクトリに不正にアクセスする手法です。
攻撃の例を見てみましょう。
この例ではユーザーが指定したファイル名を直接使用してファイルシステムの情報を返却するAPIを開発しています。
この時のファイル名指定に攻撃者は`../`などの文字列を使用してディレクトリを遡り、開発者が意図しないファイルにアクセスして中身を画面に表示されてしまう可能性があります。
import * as fs from 'fs';
import * as path from 'path';
import express from 'express';
const app = express();
app.get('/file/:filename', (req, res) => {
const filename = req.params.filename;
// リクエストパラメータから取得したファイル名を直接埋め込んでいる
const filePath = path.join(__dirname, 'files', filename);
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
res.status(404).send('File not found');
} else {
res.send(data);
}
});
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Webサーバーには基本的にLinuxが使われていて、重要な情報が格納されているディレクトリやファイルは仕様によって大体決まっていたりするので攻撃者はそこを狙ってパスを指定してきます。
よく狙われるファイルなどは下記のようなものが多いです。
/var/www/html/ (Webサーバーのルートディレクトリ)
├── index.php
├── images/
│ ├── logo.png
│ └── background.jpg
├── css/
│ └── style.css
├── js/
│ └── main.js
├── includes/
│ ├── config.php (データベース接続情報など)
│ └── functions.php
└── uploads/ (ユーザーがアップロードしたファイルの保存先)
└── user_files/
/etc/ (システム設定ファイルのディレクトリ)
├── passwd (ユーザーアカウント情報)
├── shadow (暗号化されたパスワード)
└── hosts (ホスト名とIPアドレスのマッピング)
/home/ (ユーザーのホームディレクトリ)
└── webadmin/
├── .ssh/
│ └── id_rsa (SSHの秘密鍵)
└── backup/
└── database_dump.sql (データベースのバックアップ)
被害
情報漏洩
攻撃者が機密情報や個人情報を含むファイルにアクセスする事で情報漏洩が発生します。
例えば先ほどの例にあったディレクトリ構成の/etc/passwdファイルにアクセスされると管理しているユーザー名やパスワードなどの情報が簡単に抜かれてしまいます。
/etc/ (システム設定ファイルのディレクトリ)
├── passwd (ユーザーアカウント情報)
├── shadow (暗号化されたパスワード)
└── hosts (ホスト名とIPアドレスのマッピング)
データの改竄
ファイルにアクセスできると言うことはもちろん中身の改竄も可能です。
これにより、誤った情報の発信やマルウェアの拡散などが発生し、企業の信用が失墜する可能性があります。
アカウントの乗っ取り
/etc/passwdの情報にアクセスする事でシステムで有効なアカウント情報が取得できるので、それを使って不正ログインしてアカウントの乗っ取りも可能です。
アカウントが乗っ取られるとそこから二次被害として水平権限昇格や垂直権限昇格と言った別の脆弱性を突かれてしまいます。
権限昇格については別の記事で詳しく解説します
水平権限昇格
自身のユーザーと同レベルのアクセス権限を持つユーザーの情報を閲覧できてしまう脆弱性のこと
垂直権限昇格
自身のユーザーよりも高いレベルのアクセス権限を持つユーザーにアクセスして、自分に高い権限を付与すること
サービス停止
重要なファイルが削除されたり、改竄されたりする事でシステム全体が正常に動作しなくなる可能性があり、サービスが停止するリスクがあります。
データベースの接続情報などが記載されたファイル等は削除されるとデータ取得や更新ができなくなり、サービスとして成り立たなくなります。
実例
トレンドマイクロ製品の脆弱性(CVE-2019-18187、CVE-2019-9489)
2019年、トレンドマイクロの企業向け「ウイルスバスター」製品において、ディレクトリトラバーサルの脆弱性が発見されました。
この脆弱性は、攻撃者が特定のリクエストを送信することで、サーバー上の任意のファイルにアクセスできるというものでした。
トレンドマイクロは、この脆弱性を悪用した攻撃が実際に確認されたことを発表し、ユーザーに対して最新のパッチを適用するよう呼びかけました
引用:https://forest.watch.impress.co.jp/docs/news/1206392.html
Apache HTTP Serverの脆弱性(CVE-2021-41773、CVE-2021-42013)
2021年、Apache HTTP Serverのバージョン2.4.49および2.4.50にディレクトリトラバーサルの脆弱性が発見されました。
この脆弱性を悪用すると、攻撃者はサーバー上の任意のファイルにアクセスできるだけでなく、特定の条件下では任意のコードを実行することも可能でした。
これにより、多くのWebサーバーが攻撃の対象となり、情報漏洩やサービス停止などの被害が発生しました
引用:https://gigazine.net/news/20210730-cisa-fbi-vulnerabilities/
対策
- ファイル名のバリデーションを実施する
- パスが意図したディレクトリ内にあるか確認する
冒頭の問題があるソースを修正するとこんな感じになります。
import * as fs from 'fs';
import * as path from 'path';
import express from 'express';
const app = express();
app.get('/file/:filename', (req, res) => {
const filename = req.params.filename;
// ファイル名のバリデーション
if (!/^[a-zA-Z0-9_-]+\.[a-zA-Z0-9]+$/.test(filename)) {
return res.status(400).send('Invalid filename');
}
const safePath = path.normalize(path.join(__dirname, 'files', filename));
// パスが意図したディレクトリ内にあるか確認
if (!safePath.startsWith(path.join(__dirname, 'files'))) {
return res.status(403).send('Access denied');
}
fs.readFile(safePath, 'utf8', (err, data) => {
if (err) {
res.status(404).send('File not found');
} else {
res.send(data);
}
});
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
まとめ
今回はパストラバーサルについて解説しました。
- Webアプリケーションの脆弱性を悪用して不正にファイルシステムにアクセスする手法である
- 情報漏洩やデータ改ざん、アカウントの乗っ取り、サービス停止などの重大な被害が発生する可能性がある
やはりユーザーが入力した文字列はそのまま使用せず、加工したりバリデーションをしっかり実施するなどの対策が必要ですね
次回もお楽しみに!