2023 年度 DB 技術 : PHP + RDBMS
環境構築
PHP のインストール
PHP を Debian パッケージを利用してインストールする. PHP 関連のパッケージは大量に存在するが, 基本的な動作であれば php, php-mysql, libapache2-mod-php パッケージを指定すれば良い. libapache2-mod-php は apache2 用の PHP モジュールで,今回 Web サーバとして apache2 を使うのでインストールしている.
$ sudo apt update $ sudo apt install php libapache2-mod-php php-mysql
PHP の設定
PHP をインストール後に mods-enabled ディレクトリ以下を確認すると, PHP を使うためのファイルが存在することがわかる. このことは /var/www/html 以下で PHP を使える状態にあることを意味する.
$ sudo -s # cd /etc/apache2/ # ls mods-enabled/*php* mods-enabled/php7.4.conf mods-enabled/php7.4.load
userdir (~/public_html/) において php を使うためには, mods-enabled/php7.4.conf の設定を変更する必要がある. コメントに書かれているように, php_admin_flag engine を On にする.
# vi mods-enabled/php7.4.conf ...(前略)... # Running PHP scripts in user directories is disabled by default # # To re-enable PHP in user directories comment the following lines # (from <IfModule ...> to </IfModule>.) Do NOT set it to On as it # prevents .htaccess files from disabling it. <IfModule mod_userdir.c> <Directory /home/*/public_html> # php_admin_flag engine Off (コメントアウトする) php_admin_flag engine On </Directory> </IfModule>
設定を変更したら, apache2 を再起動する.
# /etc/init.d/apache2 restart [ ok ] Restarting apache2 (via systemctl): apache2.service. # exit $
PHP の動作確認
以下のような 時刻を表示するための php ファイルを Web サーバのドキュメントルートに置いてみて動作確認を行う. なお, <? の前や, ?> の前に「空白文字を入れない」こと!
$ cd ~/public_html $ vi hello.php <?php echo date("Y-m-d H:i:s"); ?>
作成が終わったら, 自分の PC のブラウザで http://10.176.0.XXX/~hogehoge/ (IP は自分のものに変え, hogehoge は自分のユーザ名に置き換えること) に アクセスし, hello.php を表示してみよ. さらに,再読み込みボタンを押すと表示が変化すること,を確かめて下さい.
PHP で掲示板
サンプルファイルをダウンロードして,それを利用する.
$ cd ~/ $ wget www.gfd-dennou.org/arch/iot/oss/IoTeX_2023/j4db-sample-3.tar.gz $ tar zxvf j4db-sample-3.tar.gz $ cd j4db-sample-3
データベースに掲示板に用いるテーブルを作成する. 既に j4db というデータベースが存在するはずなので, そこにテーブル keijiban を作成する. テーブル作成用・データ入力用のスクリプトが用意されているので,それを利用する. パスワードを聞かれるので,mysql にログインするための パスワードを入力すること.また,以下のコマンドの中の hogehoge は自分のユーザ名に置き換えること.
$ mysql -u hogehoge -p j4db < keijiban_create.sql Enter password: $ mysql -u hogehoge -p j4db < keijiban_insert.sql Enter password:
データベースのユーザ名・パスワード情報をファイルに 記載しておく.このファイルは公開領域には置かないこと.
$ vi db_info.php <?php $SERV="localhost"; $USER=""; <-- ここ $PASS=""; <-- ここ $DBNM="j4db"; ?>
PHP スクリプト内に埋め込まれている データベースのアクセス情報を書いたファイル (db_info.php) のパスを修正しておく.
$ vi keijiban_op.php require_once("/home/hogehoge/j4db-sample-3/db_info.php"); <-- ユーザ名を自分のものに
掲示板に使うファイルを ~/public_html (公開領域) に 設置する.
$ cd ~/public_html $ cp ~/j4db-sample-3/keijiban.html ./ $ cp ~/j4db-sample-3/keijiban_op.php ./
準備が出来たら,ブラウザから自分の VM の当該ファイルを 表示する.IP とユーザ名は自分のものに置き換えること.
http://10.176.0.1**/~<user>/keijiban.html
まずは利用してみて欲しい.データの表示・追加・削除・検索ができると思う.
セキュリティ対策
PHP プログラム (keijiban_op.php) の削除・検索部分は以下のように書かれている. では,delete, search で以下のように書かれている.見てわかる通り,ポストされた データを $b1, $c1 といった変数に代入し,それを SQL 文に文字列連結している.
case "delete": $b1 = $_POST["b1"]; print "DELETE FROM keijiban WHERE bang=$b1 \n\n"; $s->query("DELETE FROM keijiban WHERE bang=$b1"); $re=$s->query("SELECT * FROM keijiban ORDER BY bang"); break; case "search": $c1 = $_POST["c1"]; print "SELECT * FROM keijiban WHERE mess LIKE '%$c1%' ORDER BY bang \n\n"; $re=$s->query("SELECT * FROM keijiban WHERE mess LIKE '%$c1%' ORDER BY bang"); break;
この PHP プログラムは SQL インジェクションとクロスサイトスクリプティングの脆弱性をかかえている.
脆弱性の体験:SQL インジェクション
以下を実行すると,SQL インジェクションの脆弱性を抱えていることが把握できる.なお,削除したデータを復活させるためには, $ mysql -u hogehoge -p j4db < ~/j4db-sample-3/keijiban_insert.sql を再度実行すること.
- 「削除」 に 「1 OR 1=1」を入力する
(DELETE FROM keijiban WHERE bang=1 or 1=1 が実行されることになる)
→ 「表示」をクリック
→ テーブルのレコードが全部消されているので何も表示されない - 「検索」 に 「’ or 1; --」を入力する
→ 全ての項目が表示される
(SELECT * FROM keijiban WHERE mess LIKE '%' or 1; --%' ORDER BY bang が実行されることになる) - 「検索」 に 「’ ; delete from keijiban ; --」 を入力する
(SELECT * FROM keijiban WHERE mess LIKE '%’ ; delete from keijiban ; --%' ORDER BY bang が実行されることになる)
→ 「表示」をクリック → テーブルのレコードが全部消されているので何も表示されない
脆弱性の体験:クロスサイトスクリプティング
以下を実行すると,クロスサイトスクリプティングの脆弱性を抱えていることが把握できる.
- 「入力」で,名前かメッセージの欄に,「<body bgcolor=red>」を入力する
→ 画面が真っ赤になる
脆弱性の解消:SQL インジェクション
SQL インジェクション対策としてプレースホルダを使うのが良い.prepare して execute するという 2 段階となる. 以下の例では $var に入力されたデータが入力されている.
(プレースホルダを使っていない例) $re=$s->query("SELECT * FROM tbl WHERE var LIKE '$var'"); (プレースホルダを使う例) $re=$s->prepare("SELECT * FROM tbl WHERE var LIKE ':var'"); $re->execute(array(':var' => $var));
脆弱性の解消:クロスサイトスクリプティング
クロスサイトスクリプティング対策としては, 入力値を制限したり, サニタイジングを行う. サニタイジングとは, HTML タグや JavaScript スクリプトが必要とする &,<,>,”,’ の5文字の特殊文字について, そのまま画面に表示する文字列となるように置換(エスケープ)することを意味する. PHP の場合は htmlentities() 関数を使うと良い.
(htmlentities を使っていない例) $a1 = $_POST["a1"]; (htmlentities を使った例) $a1 = htmlentities($_POST["a1"]);
課題:
keijiban_op.php に対して SQL インジェクション対策とクロスサイトスクリプティング対策を実施せよ. また,掲示板の見栄えや機能など,改良してみよ.
修正した HTML ファイル, PHP ファイル,改良した画面のスナップショット (メニューバーの URL が含まれるようにすること) を提出すること.