File: security.xml

package info (click to toggle)
phpdoc 20020310-1
  • links: PTS
  • area: main
  • in suites: woody
  • size: 35,272 kB
  • ctags: 354
  • sloc: xml: 799,767; php: 1,395; cpp: 500; makefile: 200; sh: 140; awk: 51
file content (1247 lines) | stat: -rw-r--r-- 62,837 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision: 1.20 $ -->
 <chapter id="security">
  <title>セキュリティ</title>

  <simpara>
   PHP は強力な言語そしてインタプリタであり、モジュールとして Web サー
   バーに組み込んだ場合でも、独立した <acronym>CGI</acronym> バイナリ
   として実行される場合でも、ファイルをアクセスしたり、コマンドを実行
   したり、サーバーへのネットワーク接続を開くことができます。デフォル
   トでは、これらの機能を実行した場合、Webサーバー上でセキュリティ上の
   問題を生じる可能性があります。PHP は、特に CGI プログラムを書く場合、
   Perl や C より安全な言語となるように設計されています。コンパイル時
   または実行時の設定オプションを正しく選び、適切なコードを書くことに
   より、必要な自由度とセキュリティの組み合わせを確実に提供することが
   できます。
  </simpara>
  <simpara>
   PHP の使用法に多くの異なった手段があるように、PHP の動作を制御する
   多くの設定オプションがあります。オプションの選択肢が広いため、PHP
   を様々な用途に使用することができます。しかし、このことは、これらの
   オプションとサーバー設定の組み合わせによっては、安全でない設定とな
   ることを意味します。
  </simpara>
  <simpara>
   PHPの設定の自由度はそのコードの柔軟さにほぼ匹敵します。PHPは、シェ
   ルユーザコマンドを全て実行可能な完全なサーバーアプリケーションや
   厳しく制御された環境で低リスクの簡単なサーバーサイドインクルードを
   使用できるようなアプリケーションを構築する場合に使用することが可能
   です。そうした環境の構築方法、セキュリティのレベルはPHPの開発者に大
   きく依存しています。
  </simpara>
  <simpara>
   本章は、安全に使用可能な異なった設定と条件の組み合わせについての説
   明から始めます。続いて、複数のセキュリティレベルのコーディングにお
   ける複数の考慮事項について説明し、最後にいくつかの一般的なセキュリ
   ティ上のアドバイスを行います。
  </simpara>

  <sect1 id="security.general">
   <title>一般的な考慮事項</title>
   <simpara>
    完全に安全なシステムは理想の産物でしかないため、セキュリティ業界で
    しばしば使用される手法は、リスクと利便性のバランスのとれた手法です。
    変数がユーザから投稿される度に(網膜スキャンと指紋のような)2種類の
    生体認証が必要だとしたら、極端に高いレベルの説明義務を生じます。ま
    た、かなり複雑なフォームを埋めるために30分もかかるとすれば、ユーザ
    がセキュリティをバイパスする手段を探す気分にさせる傾向があります。
   </simpara>
   <simpara>
    最善のセキュリティは、通常、ユーザによる業務の達成を防たげずに要求
    を十分に達成できる程度にさしでがましくないものです。むしろ、いくつ
    かのセキュリティ攻撃は、単純にこの種の多げさに構築され、時間を浪費
    しがちなセキュリティ機構を狙うものです。
   </simpara>
   <simpara>
    記憶するに値する言葉として次のようなものがあります。「システムは鎖
    の最も弱い輪と同程度に優れている」全てのトランザクションが時間、場
    所、トランザクションの型等に基づき大量に記録されているが、ユーザは
    一つのクッキーのみにより認証されている場合、ユーザとそのトランザク
    ションログの結び付きの確実性はかなり弱くなります。
   </simpara>
   <simpara>
    テストの際に、最も簡単なページに関してでさえ、全ての可能性をテスト
    することは不可能であるということを頭に入れておいて下さい。期待する
    入力は、不機嫌な社員、経験のあるクラッカー、キーボードの上を歩く家
    の猫による入力とは全く無関係でしょう。これが、想定外のデータが入力
    される可能性がある場所を見分けるために論理的な視点からコードを見て、
    その後、修正、減少、または詳細に調べるというのが、最善であるという
    理由です。
   </simpara>
   <simpara>
    インターネットにはあなたのコードを壊したり、システムを破壊したり、
    不適切な内容を投稿したり、その他あなたの一日を不快にするようなこと
    により自分の名を馳せたいと思う人がたくさんいます。サイトの規模の大
    小によらず、単にオンラインであり、接続できるサーバを有しているだけ
    で攻撃目標となりえます。多くのクラック用プログラムはサイトの大きさ
    を考慮せず、犠牲者を探しつつ大きなIPブロックで網を張っています。
   </simpara>
  </sect1>

  <sect1 id="security.cgi-bin">
   <title>CGI バイナリとしてインストール</title>
   
   <sect2 id="security.cgi-bin.attacks">
    <title>有りうる攻撃</title>

    <simpara>
     PHP を <acronym>CGI</acronym> バイナリとして使用するのは、PHP を
     モジュールとして(Apache のような)サーバーソフトウエアに組み込み
      たくない何らかの理由がある場合や安全な chroot と setuid 環境をス
     クリプトに提供する他の CGI ラッパーと組み合わせて PHP を使用する
     場合の設定オプションです。セットアップ時には、通常、PHP 実行バイ
     ナリを Web サーバーの cgi-bin ディレクトリにインストールします。
     CERT 勧告 <ulink url="&url.cert;">CA-96.11</ulink>は、いかなるイ
     ンタプリタを cgi-bin に置くことにも反対しています。
     PHP バイナリをスタンドアロンのインタプリタとして使用することが
     できる場合でも、PHP は、セットアップにより生じる可能性がある
     次のような攻撃を防ぐように設計されています。
    </simpara>
    <itemizedlist>
     <listitem>
      <simpara>
       システムファイルへのアクセス: <filename
       role="url">http://my.host/cgi-bin/php?/etc/passwd</filename>
      </simpara>
      <simpara>
       URL において疑問符 (?) の後のクエリー情報は、CGI インターフェー
       スにより、インタプリタにコマンドライン引数として渡されます。通
       常、インタプリタは、コマンドライン上の最初の引数に指定されたファ
       イルを開き、実行します。
      </simpara>
      <simpara>
       CGI バイナリとして実行された場合、PHP は、コマンドライン引数の
       解釈を拒否します。
      </simpara>
     </listitem>
     <listitem>
      <simpara>
       サーバー上の Web ドキュメントへのアクセス: <filename
       role="url">http://my.host/cgi-bin/php/secret/doc.html</filename>
      </simpara>
      <simpara>
       URL の PHP バイナリ名の後のパス情報の部分、つまり<filename
       role="uri">/secret/doc.html</filename> は、
       <acronym>CGI</acronym> プログラムによりオープンされて実行される
       ファイルの名前を指定するために従来より使用されています。
       <filename role="url">http://my.host/secret/script.php</filename>
       のようなドキュメントへの要求を PHP インタプリタにリダイレクト
       するために、通常、何らかの Web サーバー設定用命令(Apache では Action)
       が使用されます。この設定により、Web サーバーは、まずディレクトリ 
       <filename role="uri">/secret</filename> へのアクセス権をチェックし、
       リダイレクト要求 <filename
       role="url">http://my.host/cgi-bin/php/secret/script.php</filename>
       を生成します。残念なことに、リクエストが最初からこの形式で与え
       られた場合、Web サーバーによるアクセスチェックは、
       <filename role="uri">/secret/script.php</filename> ファイル
       ではなく、<filename role="uri">/cgi-bin/php</filename> ファイル
       に対して行われます。この手法により、<filename
       role="uri">/cgi-bin/php</filename> にアクセス可能なユーザーは、
       Web サーバー上の全ての保護されたドキュメントにアクセスできてし
       まいます。
      </simpara>
      <simpara>
       PHP では、サーバードキュメントツリーにアクセス制限付きのディレ
       クトリがある場合、コンパイル時の設定オプション <link
       linkend="install.configure.enable-force-cgi-redirect">
       --enable-force-cgi-redirect</link> および実行時の設定命令
       <link linkend="ini.doc-root">doc_root</link> と
       <link linkend="ini.user-dir">user_dir</link> をこの攻撃を防止す
       るために使用することができます。  これらを組み合わせたいくつか
       の手法について以下に詳細な説明を示します。
      </simpara>
     </listitem>
    </itemizedlist>
   </sect2>

   <sect2 id="security.cgi-bin.default">
    <title>ケース 1: 公開ファイルのみを配布</title>
    <simpara>
     サーバー上にパスワードまたは IP アドレスを元にしたアクセス制限に
     よる制約を受けるコンテンツがない場合、この設定オプションを使用す
     る必要はありません。使用する Web サーバーがリダイレクトを許可しな
     い場合やサーバーがリダイレクト要求を安全に処理しつつPHP バイナリ
     と通信できる手段を有していない場合、オプション <link
     linkend="install.configure.enable-force-cgi-redirect">
      --enable-force-cgi-redirect</link>を
     configure スクリプトに指定することができます。この場合でも、直接
     的な方法 <filename
     role="php">http://my.host/cgi-bin/php/dir/script.php</filename>
     でもなくリダイレクション <filename
     role="php">http://my.host/dir/script.php</filename>でもない他の
     やり方で PHP スクリプトを呼び出せるようになっていないかどうか確認
     する必要があります。
    </simpara>
    <simpara>
     リダイレクションは、例えば Apache では命令 AddHandler および
     Action で設定することができます。(以下を参照してください。)
    </simpara>
   </sect2>

   <sect2 id="security.cgi-bin.force-redirect">
    <title>ケース 2: --enable-force-cgi-redirect を使用</title>
    <simpara>
     このコンパイル時のオプションは、
     <filename role="php">http://my.host/cgi-bin/php/secretdir/script.php
     </filename> のように URL から直接 PHP を呼び出すことを禁止します。
     代わりに、
     Web サーバーのリダイレクションにより処理された場合は、
     PHP はこのモードでのみ処理を行います。
    </simpara>
    <simpara>
     通常、Apache 用設定でのリダイレクションは、
     次の命令を使用して行います。</simpara>
    <programlisting role="apache-conf">
<![CDATA[
Action php-script /cgi-bin/php
AddHandler php-script .php
]]>
    </programlisting>
    <simpara>
     このオプションは、Apache Web サーバーでのみテストされており、リク
     エストのリダイレクト時に Apache が標準ではないCGI 環境変数
     <envar>REDIRECT_STATUS</envar> をセットすることを前提にしています。
     リクエストが直接のものであるか間接のものであるかを示す手段をWeb
     サーバーが全くサポートしていない場合は、このオプションを使用する
     ことはできません。この場合、ここで記した CGI 版を実行する他の方法
     の内の一つを使用する必要があります。
    </simpara>
   </sect2>

   <sect2 id="security.cgi-bin.doc-root">
    <title>ケース 3: doc_root または user_dir を設定</title>
    <simpara>
     Web サーバー上のドキュメントディレクトリに
     スクリプトや実行ファイルのようなアクティブな内容を読み込むのは、
     往々にして危険な行為であるとみなされることがあります。
     何らかの設定ミスによりスクリプトが実行されず、通常の HTML ドキュメント
     として表示されてしまう場合には、知的著作物またはパスワードのような
     セキュリティ情報が漏洩する可能性があります。
     このため、多くのシステム管理者は、スクリプトを PHP CGI を通じてのみ
     アクセス可能な他のディレクトリ構造にセットアップしたいと思うこと
     でしょう。
     この場合、常にインタープリタに処理されるため、上記のように表示されること
     はありません。
    </simpara>
    <simpara>
     前節で記したようなリクエストがリダイレクトされたものでないことを
     確かめる方法が利用可能でない場合、
     スクリプト用の doc_root を Web ドキュメント用ルートとは別に
     セットアップする必要があります。
    </simpara>
    <simpara>
     設定用命令 <link linkend="ini.doc-root">doc_root</link> により
     <link linkend="configuration.file">設定ファイル</link> ファイル中で
     PHP スクリプト用ドキュメントルートを設定することができます。
     または、環境変数 <envar>PHP_DOCUMENT_ROOT</envar> でも設定する
     ことができます。
     これを設定した場合、CGI 版の PHP は、     
     常に開くファイルの名前をこの <parameter>doc_root</parameter> 
     リクエストのパス情報を用いて作成し、
     (以下の <parameter>user_dir</parameter> を除き、)確実に
     このディレクトリの外側でスクリプトが実行されないようにします。
    </simpara>
    <simpara>
     ここで利用可能な別のオプションは、<link linkend="ini.user-dir">
      user_dir</link> です。user_dir が設定されていない場合、
     開かれるファイル名を制御するのは、<parameter>doc_root</parameter>
     のみです。
     <filename role="url">http://my.host/~user/doc.php</filename> のような
     URL は、ユーザーホームディレクトリ以下のファイルを開かず、
     doc_root 以下の <filename role="uri">~user/doc.php</filename> 
     というファイルを開くことになります。
     (ディレクトリ名がチルダ [<literal>~</literal>] で始まっている
     ということになります)
    </simpara>
    <simpara>
     user_dir が例えば、<filename role="dir">public_php</filename>に
     設定されていた場合、
     <filename role="url">http://my.host/~user/doc.php</filename> の
     ようなリクエストは、そのユーザー user のホームディレクトリにある
     <filename role="dir">public_php</filename> 以下の
     <filename>doc.php</filename> という名前のファイルをオープンしま
     す。ユーザーのホームディレクトリが、
     <filename role="dir">/home/user</filename> である場合、
     実行されるファイルは、
     <filename>/home/user/public_php/doc.php</filename>
     となります。
    </simpara>
    <simpara>
     <parameter>user_dir</parameter> の展開は、
     <parameter>doc_root</parameter> の設定によらず行われます。
     このため、ドキュメントルートおよびユーザーディレクトリへの
     アクセスを別々に制御することができます。
    </simpara>
   </sect2>
   
   <sect2 id="security.cgi-bin.shell">
    <title>ケース 4: web ツリーの外に PHP パーサを置く</title>
    <para>
     非常に安全性の高いオプションとしてPHP パーサのバイナリをファイル
     用 Web ツリーの外側、例えば <filename
     role="dir">/usr/local/bin</filename>に置くことが考えられます。こ
     のオプションの唯一の欠点は、PHP タグを有する全てのファイルの先頭
     行に次のような一行を加える必要があることです。
     <informalexample>
      <programlisting>
<![CDATA[
#!/usr/local/bin/php
]]>
      </programlisting>
     </informalexample>
     また、ファイルを実行可能にしておく必要があります。この場合、実行
     時にシェルエスケープ機能 <literal>&num;!</literal> を使用する Perl や
     sh や他のスクリプト言語で書かれた CGI スクリプトを処理するのと全
     く同様に処理を行います。
    </para>
    <para>
     この設定で <envar>PATH_INFO</envar> および
     <envar>PATH_TRANSLATED</envar> 情報を正しく処理するためには、
     PHP パーサを設定オプション
     <link linkend="install.configure.enable-discard-path">
      --enable-discard-path</link> を付けてコンパイルする必要があります。
    </para>
   </sect2>
  </sect1>
  
  <sect1 id="security.apache">
   <title>Apache モジュールとしてインストール</title>
   <simpara>
    PHP が Apache モジュールとして使用された場合、PHP は、Apache ユー
    ザーの許可属性(通常はユーザー "nobody" の許可属性)を継承します。
    これは、セキュリティと認証に数々の影響を与えます。例えば、データベー
    スと接続するためにPHPを使用している場合、データベースが組込みのア
    クセス制御機能を有していない限り、そのデータベースを "nobody"ユー
    ザからアクセス可能とする必要が生じます。これは、悪意のあるスクリプ
    トが、ユーザ名とパスワードなしにデータベースにアクセスし、修正する
    ことができることを意味します。Webスパイダがデータベース管理用Webペー
    ジを回って、データベースを全て削除することも可能です。Apache認証に
    よりこの攻撃に対して防衛することが可能であり、また、LDAPや
    .htaccessファイル等を使用して固有のアクセスモデルを設計し、PHPスク
    リプトの一部としてそのコードを読み込むことも可能です。
   </simpara>
   <simpara>
    しばしば、PHPユーザ(この場合はApacheユーザ)が非常に小さなリスクを
    有する場所に一度セキュリティが確立されると、PHPはユーザディレクト
    リにウイルスファイルを書き込んだりすることができなくなります。もし
    くは、データベースにアクセスしたり変更したりといったことが出来なく
    なります。この場合、良いファイルおよび悪いファイルの書き込み、また
    は、良いデータベーストランザクションと悪いデータベーストランザクシ
    ョンに関して等しく安全性が確保されていると言えます。
   </simpara>
   <simpara>
    この観点からしばしば行われるセキュリティ上の失敗としてApacheにルー
    ト権限を与えたり、他の何らかの手段でApacheの権限を昇格させるという
    ものがあります。
   </simpara>
   <simpara>
    Apacheユーザの権限をルートに昇格させることは非常に危険であり、シ
    ステム全体を危険にさらす可能性があります。よって、sudoやchrootの実
    行、ルート権限で実行を行う他の手段は、セキュリティに精通した人以外
    は、考慮するべきではありません。
   </simpara>
   <simpara>
    いくつかのより簡単な解決策があります。
    <function>open_basedir()</function> を使用することにより、PHPに使用
    を許可するディレクトリを制御したり制限したりすることが可能です。
    また、全てのWebベースの作業をユーザファイル、システムファイル以外の
    ファイルに制限するために、Apache専用エリアを設定することも可能です。
   </simpara>
  </sect1>

  <sect1 id="security.filesystem">
   <title>ファイルシステムのセキュリティ</title>
   <simpara>
    PHP は、ファイルおよびディレクトリ毎に権限を設定する多くのサーバシ
    ステム上に組み込まれたセキュリティを提供します。これにより、ファイ
    ルシステム内のファイルを読み込み可能に制御することが可能になります。
    全てのファイルは世界中から読み込み可能であり、このファイルシステム
    にアクセスした全てのユーザから読み込まれても安全であることを確認す
    る必要があります。
   </simpara>
   <simpara>
    PHPは、ファイルシステムにユーザレベルのアクセスを許可するように設
    計されているため、PHPスクリプトから/etc/password のようなシステム
    ファイルを読み込み可能としたり、イーサネット接続を修正したり、巨大
    なプリンタジョブを出力したりすることができます。これから明らかにわ
    かることですが、読み書きするファイルを適切に設定する必要があります。
   </simpara>
   <simpara>
    各自のホームディレクトリにあるファイルを削除する次のスクリプトを見
    てみましょう。これは、ファイル管理用にWebインターフェースを使用す
    る場合に通常生じるような設定を仮定しています。この場合、Apacheユー
    ザはそのユーザのホームディレクトリにあるファイルを削除可能です。
   </simpara>
   <para>
    <example>
     <title>甘い変数の確認から生じるリスク</title>
     <programlisting role="php">
<![CDATA[
<?php
// ユーザのホームディレクトリからファイルを削除する
$username = $HTTP_POST_VARS['user_submitted_name'];
$homedir = "/home/$username";
$file_to_delete = "$userfile";
unlink ($homedir/$userfile);
echo "$file_to_delete は削除されました!";
?>
]]>
     </programlisting>
    </example>
    usernameはユーザフォームから投稿可能であるため、usernameを投稿し、
    他の誰かが所有するファイルを指定、削除することが可能です。この場合、
    他の何らかの形式の認証を使用するべきです。投稿された変数が、
    "../etc/" と "passwd " であった場合について考えてみましょう。簡単
    なコードを以下に示します。
    <example>
     <title>... ファイルシステムへの攻撃</title>
     <programlisting role="php">
<![CDATA[
<?php
// 外部からPHPユーザがアクセス可能なハードドライブを削除します。PHPが
// ルートのアクセス権限を有している場合、
$username = "../etc/";
$homedir = "/home/../etc/";
$file_to_delete = "passwd";
unlink ("/home/../etc/passwd");
echo "/home/../etc/passwd は削除されました!";
?>
]]>
     </programlisting>
    </example>   
    こうした問題を防止するために必要な重要なチェック手段として以下の2
    種類のものがあります。
    <itemizedlist>
     <listitem>
      <simpara>
       PHP Webユーザバイナリに制限された権限のみを許可する。
      </simpara>
     </listitem>
     <listitem>
      <simpara>
       投稿された全ての変数を確認する。
      </simpara>
     </listitem>
    </itemizedlist>
    以下に改良されたスクリプトを示します。
    <example>
     <title>より安全なファイル名の確認</title>
     <programlisting role="php">
<![CDATA[
<?php
// PHPユーザがアクセス可能なハードドライブからファイルを削除する。
$username = $HTTP_SERVER_VARS['REMOTE_USER']; // 認証機構を使用する

$homedir = "/home/$username";

$file_to_delete = basename("$userfile"); // パスを取り除く
unlink ($homedir/$file_to_delete);

$fp = fopen("/home/logging/filedelete.log","+a"); // 削除の記録
$logstring = "$username $homedir $file_to_delete";
fputs ($fp, $logstring);
fclose($fp);

echo "$file_to_delete は削除されました!";
?>
]]>
     </programlisting>
    </example>
    しかし、これでも、傷口を塞いだことにはなりません。
    ユーザが自分用のユーザログインを作成することをあなたの認証システムが
    許可しており、ユーザが"../etc/"へのログインを選択した場合、システム
    はまたも公開されてしまいます。このため、よりカスタマイズされたチェッ
    クを行なう方がよいでしょう。
    <example>
     <title>より安全なファイル名の確認</title>
     <programlisting role="php">
<![CDATA[
<?php
$username = $HTTP_SERVER_VARS['REMOTE_USER'];  // 認証機構を使用する

$homedir = "/home/$username";

if (!ereg('^[^./][^/]*$', $userfile))
    die('bad filename'); // 処理せず、終了。

if (!ereg('^[^./][^/]*$', $username))
     die('bad username'); // 処理せず、終了。

//etc...
?>
]]>
     </programlisting>
    </example>
   </para>
   <para>
    オペレーティングシステムにより、注意するべきファイルは大きく変化し
    ます。これらには、デバイスエントリ(/dev/ または COM1)、設定ファイ
    ル(/etc/ ファイルおよび .ini ファイル)、よく知られたファイル保存領
    域 (/home/、 My Documents)等が含まれます。このため、明示的に許可す
    るもの以外の全てを禁止する方針とする方が通常はより簡単です。
   </para>   
  </sect1>

  <sect1 id="security.database">
   <title>データベースのセキュリティ</title>

   <simpara>
    今日、ダイナミックなコンテンツを提供するウェブアプリケーションに
    おいてはデータベースは欠く事のできなコンポーネントとなっています。
    そういったデータベースには重要な、そして秘密にすべき情報が格納
    されることになるので、それらをいかにして保護するかについて十分に
    考慮する必要があります。
   </simpara>
   <simpara>
    情報を取り出したり格納するためにはデータベースに接続する必要があります。
    そして適切なクエリを送信し、結果を受け取り、切断します。クエリに
    使用される言語はStructured Query Language (SQL)が一般的です。アタッカー
    がどのように<link linkend="security.database.sql-injection">SQLに
    干渉する</link>かについて参照してください。
   </simpara>
   <simpara>
    皆さんがお気づきの様に、PHPそれ自体は貴方のデータベースを保護することは
    ありません。以下のセクションはPHPスクリプトからどのようにデータベースに
    アクセスし操作すればいいのか、とういことに関する非常に基本的な導入です。
   </simpara>
   <simpara>
   このシンプルなルールを覚えて置いてください:それは「多重防衛」です。
   より多くの箇所で、より多くの保護を行うことにより、アタッカーが攻撃に
   成功して機密情報が漏洩する可能性は減っていきます。データベースと
   アプリケーションを正しくデザインすることで貴方の心配を取り除くことが
   できます。
   </simpara>

   <sect2 id="security.database.design">
    <title>データベースのデザイン</title>
     <simpara>
      他人が用意した既存のものを使用するのでない限り、最初に行うのはデータベースの作成です。
      データベースが作成されると、そのデータベースのオーナーは作成コマンドを
      実行したユーザになります。通常、オーナー(とスーパーユーザー)のみが
      そのデータベースに対して操作を行うことが出来ます。他のユーザがデータベースを
      使用するには適切な権利が与えられている必要があります。
     </simpara>
     <simpara>
      アプリケーションはデータベースにオーナー、もしくはスーパーユーザーとして
      接続しては絶対にいけません。なぜならこれらのユーザは
      例えばスキーマの変更(テーブルの削除等)や全コンテンツの削除、といった
      あらゆるクエリーを実行することが出来るからです。
     </simpara>
     <simpara>
      貴方が作成するアプリケーションがデータベースに対して行う操作の各方面ごとに、
      捜査対象となるオブジェクトに対して、出来る限り少ない権限を持った複数の
      ユーザを作成した方が良いでしょう。ユーザに対しては、最低限必要な権限のみを
      与え、関係の無いデータへのアクセスを許可しないようにします。これは、
      万が一侵入者がそのユーザの権限を以ってデータベースにアクセスした際に、
      アプリケーションと関係の無いデータにまでアクセスされることを防ぐためです。
     </simpara>
     <simpara>
      全てのビジネスロジックをウェブアプリケーション(つまり貴方のスクリプト)
      で実装することは推奨されません。代わりに、ビュー、トリガー、ルールといった
      データベースの機能を活用した方が良いでしょう。システムが更新され、
      新しい機能がデータベースへのアクセスすることになった場合、個々のデータベース
      クライアントごとに再度同様のロジックを実装しなければならなくなります。
      さらに、トリガーは透過的に、そして自動的にフィールドを扱うことが出来るので、
      デバッグ時や、トランザクションのロールバック時に役立ちます。
     </simpara>
   </sect2>

   <sect2 id="security.database.connection">
    <title>データベースへの接続</title>
    <simpara>
     更なるセキュリティのために、クライアント/サーバ間の通信においてSSLを用いた
     暗号化を行った方が良いでしょう。もしくはsshを使用することも出来ます。
     どちらかの手段を講じた後、トラフィックをモニタリングしてみれば
     ここから何らかの情報を得ることが困難だという事が分かると思います。
    </simpara>
    <!--simpara>
     If your database server native SSL support, consider to use <link
     linkend="ref.openssl">OpenSSL functions</link> in communication between
     PHP and database via SSL.
    </simpara-->
   </sect2>

   <sect2 id="security.database.storage">
    <title>暗号化記憶モデル</title>
    <simpara>
     SSL/SSHによってクライアント/サーバ間で通信されるデータは保護されますが、
     データベースに保存されたデータは保護されません。SSLはあくまで通信上の
     プロトコルなのです。
    </simpara>
    <simpara>
     一旦アタッカーがデータベースへ(ウェブサーバを通さずに)アクセスできてしまうと、
     そこに格納されているデータ自体が暗号化されていない限り、自由に閲覧され、
     使用されてしまいます。データを暗号化することによって、この脅威を減らすことが
     できますが、この機能をサポートしているデータベースは僅かです。
    </simpara>
    <simpara>
     この問題への最も簡単な対応策は、まず自分専用の暗号化パッケージを作成し、
     それをあなたのPHPスクリプトから使用することです。PHPの<link 
     linkend="ref.mcrypt">Mcrypt</link>, <link linkend="ref.mhash">Mhash</link>
     といった幾つかの拡張モジュールは、様々な暗号化アルゴリズムをサポート
     しているので役に立つでしょう。データ格納時に暗号化を行い、取得時に
     復号化します。この方法についてはリファレンスを参照してください。
    </simpara>
    <simpara>
     もし完全にデータを隠したい場合や、元のデータ自体は必要ない場合(つまり
     表示されない場合)は、ハッシュも考慮に入れたほうが良いでしょう。
     ハッシュの良く知られた使用方法は、パスワードをそのまま格納せずに、
     そのMD5ハッシュ値を格納する方法です。<function>crypt</function>や
     <function>md5</function>も参照してください。
    </simpara>
    <example>
     <title>ハッシュパスワードフィールドを使う</title>
     <programlisting role="php">
<![CDATA[
// ハッシュされたパスワードを格納する
$query  = sprintf("INSERT INTO users(name,pwd) VALUES('%s','%s');",
            addslashes($username), md5($password));
$result = pg_exec($connection, $query);

// パスワードが正しいかどうか問い合わせる
$query = sprintf("SELECT 1 FROM users WHERE name='%s' AND pwd='%s';",
            addslashes($username), md5($password));
$result = pg_exec($connection, $query);

if (pg_numrows($result) > 0) {
    echo "Welcome, $username!";
}
else {
    echo "Authentication failed for $username.";
}
]]>
     </programlisting>
    </example>
   </sect2>

   <sect2 id="security.database.sql-injection">
    <title>SQL Injection</title>
    <simpara>
     Many web developers are unaware of how SQL queries can be tampered with,
     and assume that an SQL query is a trusted command. It means that SQL
     queries are able to circumvent access controls, thereby bypassing standard
     authentication and authorization checks, and sometimes SQL queries even
     may allow access to host operating system level commands.
    </simpara>
    <simpara>
     Direct SQL Command Injection is a technique where an attacker creates or
     alters existing SQL commands to expose hidden data, or to override valuable
     ones, or even to execute dangerous system level commands on the database
     host. This is accomplished by the application taking user input and
     combining it with static parameters to build a SQL query. The following
     examples are based on true stories, unfortunately.
    </simpara>
    <para>
     Owing to the lack of input validation and connecting to the database on
     behalf of a superuser or the one who can create users, the attacker
     may create a superuser in your database.
     <example>
      <title>
       Splitting the result set into pages ... and making superusers
       (PostgreSQL and MySQL)
      </title>
      <programlisting role="php">
<![CDATA[
$offset = argv[0]; // beware, no input validation!
$query  = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
// with PostgreSQL 
$result = pg_exec($conn, $query);
// with MySQL
$result = mysql_query($query);
]]>
      </programlisting>
     </example>
      Normal users click on the 'next', 'prev' links where the <varname>$offset</varname>
      is encoded into the URL. The script expects that the incoming
      <varname>$offset</varname> is decimal number. However, someone tries to
      break in with appending <function>urlencode</function>'d form of the
      following to the URL 
      <informalexample>
       <programlisting>
<![CDATA[
// in case of PostgreSQL
0;
insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
    select 'crack', usesysid, 't','t','crack'
    from pg_shadow where usename='postgres';
--

// in case of MySQL
0;
UPDATE user SET Password=PASSWORD('crack') WHERE user='root';
FLUSH PRIVILEGES;
]]>
       </programlisting>
      </informalexample>
      If it happened, then the script would present a superuser access to him.
      Note that <literal>0;</literal> is to supply a valid offset to the
      original query and to terminate it.
    </para>
    <note>
     <para>
      It is common technique to force the SQL parser to ignore the rest of the
      query written by the developer with <literal>--</literal> which is the
      comment sign in SQL.
     </para>
    </note>
    <para>
     A feasible way to gain passwords is to circumvent your search result pages.
     What the attacker needs only is to try if there is any submitted variable
     used in SQL statement which is not handled properly. These filters can be set 
     commonly in a preceding form to customize <literal>WHERE, ORDER BY, 
     LIMIT</literal> and <literal>OFFSET</literal> clauses in <literal>SELECT</literal>
     statements. If your database supports the <literal>UNION</literal> construct, 
     the attacker may try to append an entire query to the original one to list 
     passwords from an arbitrary table. Using encrypted password fields is 
     strongly encouraged.
     <example>
      <title>
       Listing out articles ... and some passwords (any database server)
      </title>
      <programlisting role="php">
<![CDATA[
$query  = "SELECT id, name, inserted, size FROM products
                  WHERE size = '$size'
                  ORDER BY $order LIMIT $limit, $offset;";
$result = odbc_exec($conn, $query);
]]>
      </programlisting>
     </example>
     The static part of the query can be combined with another
     <literal>SELECT</literal> statement which reveals all passwords:
     <informalexample>
      <programlisting>
<![CDATA[
'
union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from usertable;
--
]]>
      </programlisting>
     </informalexample>
     If this query (playing with the <literal>'</literal> and
     <literal>--</literal>) were assigned to one of the variables used in
     <varname>$query</varname>, the query beast awakened.
    </para>
    <para>
     SQL UPDATEs are also subject to attacking your database. These queries are
     also threatened by chopping and appending an entirely new query to it. But
     the attacker might fiddle with the <literal>SET</literal> clause. In this
     case some schema information must be possessed to manipulate the query
     successfully. This can be acquired by examing the form variable names, or
     just simply brute forcing. There are not so many naming convention for
     fields storing passwords or usernames.
     <example>
     <title>
      From resetting a password ... to gaining more privileges (any database server)
     </title>
      <programlisting role="php">
<![CDATA[
$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";
]]>
      </programlisting>
     </example>
     But a malicious user sumbits the value
     <literal>' or uid like'%admin%'; --</literal> to <varname>$uid</varname> to
     change the admin's password, or simply sets <varname>$pwd</varname> to
     <literal>"hehehe', admin='yes', trusted=100 "</literal> (with a trailing
     space) to gain more privileges. Then, the query will be twisted:
     <informalexample>
      <programlisting role="php">
<![CDATA[
// $uid == ' or uid like'%admin%'; --
$query = "UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%'; --";

// $pwd == "hehehe', admin='yes', trusted=100 "
$query = "UPDATE usertable SET pwd='hehehe', admin='yes', trusted=100 WHERE ...;"
]]>
      </programlisting>
     </informalexample>
    </para>
    <para>
     A frightening example how operating system level commands can be accessed
     on some database hosts.
     <example>
     <title>Attacking the database host's operating system (MSSQL Server)</title>
      <programlisting role="php">
<![CDATA[
$query  = "SELECT * FROM products WHERE id LIKE '%$prod%'";
$result = mssql_query($query);
]]>
      </programlisting>
     </example>
     If attacker submits the value
     <literal>a%' exec master..xp_cmdshell 'net user test testpass /ADD' --</literal>
     to <varname>$prod</varname>, then the <varname>$query</varname> will be:
     <informalexample>
      <programlisting role="php">
<![CDATA[
$query  = "SELECT * FROM products WHERE id LIKE '%a%' exec master..xp_cmdshell 'net user test testpass /ADD'--";
$result = mssql_query($query);
]]>
      </programlisting>
     </informalexample>
     MSSQL Server executes the SQL statements in the batch including a command
     to add a new user to the local accounts database. If this application
     were running as <literal>sa</literal> and the MSSQLSERVER service is
     running with sufficient privileges, the attacker would now have an
     account with which to access this machine.
    </para>
    <note>
     <para>
      Some of the examples above is tied to a specific database server. This
      does not mean that a similar attack is impossible against other products.
      Your database server may be so vulnerable in other manner.
     </para>
    </note>

    <sect3 id="security.database.avoiding">
     <title>Avoiding techniques</title>
     <simpara>
      You may plead that the attacker must possess a piece of information
      about the database schema in most examples. You are right, but you
      never know when and how it can be taken out, and if it happens,
      your database may be exposed. If you are using an open source, or
      publicly available database handling package, which may belong to a
      content management system or forum, the intruders easily produce
      a copy of a piece of your code. It may be also a security risk if it
      is a poorly designed one.
     </simpara>
     <simpara>
      These attacks are mainly based on exploiting the code not being written
      with security in mind. Never trust on any kind of input, especially
      which comes from the client side, even though it comes from a select box,
      a hidden input field or a cookie. The first example shows that such a
      blameless query can cause disasters.
     </simpara>

     <itemizedlist>
      <listitem>
       <simpara>
        Never connect to the database as a superuser or as the database owner.
        Use always customized users with very limited privileges.
       </simpara>
      </listitem>
      <listitem>
       <simpara>
        Check if the given input has the expected data type. PHP has
        a wide range of input validating functions, from the simplest ones
        found in <link linkend="ref.variables">Variable Functions</link> and
        in <link linkend="ref.ctype">Character Type Functions</link>
        (e.g. <function>is_numeric</function>, <function>ctype_digit</function>
        respectively) onwards the
        <link linkend="ref.pcre">Perl compatible Regular Expressions</link>
        support.
       </simpara>
      </listitem>
      <listitem>
       <para>
        If the application waits for numerical input, consider to verify data
        with <function>is_numeric</function>, or silently change its type
        using <function>settype</function>, or use its numeric representation
        by <function>sprintf</function>.
        <example>
         <title>A more secure way to compose a query for paging</title>
         <programlisting role="php">
<![CDATA[
settype($order, 'integer');
$query  = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";

// please note %d in the format string, using %s would be meaningless
$query  = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;", $offset);
]]>
         </programlisting>
        </example>
       </para>
      </listitem>
      <listitem>
       <simpara>
        Quote each non numeric user input which is passed to the database with
        <function>addslashes</function> or <function>addcslashes</function>.
        See <link linkend="security.database.storage">the first example</link>.
        As the examples shows, quotes burnt into the static part of the query
        is not enough, and can be easily hacked.
       </simpara>
      </listitem>
      <listitem>
       <simpara>
        Do not print out any database specific information, especially
        about the schema, by fair means or foul. See also <link
        linkend="security.errors">Error Reporting</link> and <link
        linkend="ref.errorfunc">Error Handling and Logging Functions</link>.
       </simpara>
      </listitem>
      <listitem>
       <simpara>
        You may use stored procedures and previously defined cursors to abstract
        data access so that users do not directly access tables or views, but
        this solution has another impacts.
       </simpara>
      </listitem>
     </itemizedlist>

     <simpara>
      Besides these, you benefit from logging queries either within your script
      or by the database itself, if it supports. Obviously, the logging is unable
      to prevent any harmful attempt, but it can be helpful to trace back which
      application has been circumvented. The log is not useful by itself, but
      through the information it contains. The more detail is generally better.
     </simpara>
    </sect3>
   </sect2>
  </sect1>
  
  <sect1 id="security.errors">
   <title>エラーのレポート</title>
   <para>
    PHPのセキュリティに関して、2種類のエラー出力があります。一つは、セ
    キュリティ向上に役立つものであり、もう一つは、セキュリティ上有害な
    ものです。
   </para>
   <para>
    標準的な攻撃手法の中に不完全なデータをシステムに送信し、返されるエ
    ラーの種類と内容を調べることにより、システムを調べるというものがあ
    ります。これにより、システムのクラッカーがありうる弱点を調査するた
    めにそのサーバに関する情報を調べることが可能になります。
    例えば、ある攻撃者が事前のフォーム投稿の際にあるページに関して収集
    した情報を持っている場合、変数を上書きしたり、修正したりしようとす
    るかもしれません。
    <example>
     <title>カスタムHTMLページにより変数を攻撃する</title>
     <programlisting role="php">
<![CDATA[
<form method="post" action="attacktarget?username=badfoo&password=badfoo">
<input type="hidden" name="username" value="badfoo">
<input type="hidden" name="password" value="badfoo">
</form>
]]>
     </programlisting>
    </example> 
   </para>
   <para>
    通常返されるPHPのエラーは、エラーを生じた関数やファイル、エラーを
    発生したPHPファイル、エラーを発生した行番号のような情報が含まれて
    おり、スクリプトをデバッグする開発者に非常に有用です。これらが調べ
    ることができる情報の全てです。デバッグ目的でPHPの開発者が
    <function>show_source</function>,
    <function>highlight_string</function>,
    <function>highlight_file</function> を使用することはまれではありま
    せん。しかし、実用サイトでは、これは秘密の変数、未確認の構文、その
    他の危険な情報を公開することになってしまいます。特に危険なのは、
    組み込みのデバッグハンドラを有する既知のソースからのコードを実行して
    いるか、一般的なデバッグ技法を使用している場合です。攻撃者が、使用し
    ている一般的な技法を特定できた場合、次のようにあるページに様々な一般
    的なデバッグ用文字列を送信することによりしらみつぶしに攻撃しようとす
    るかもしれません。
    <example>
     <title>一般的なデバッグ変数を探す</title>
     <programlisting role="php">
<![CDATA[
<form method="post" action="attacktarget?errors=Y&showerrors=1"&debug=1">
<input type="hidden" name="errors" value="Y">
<input type="hidden" name="showerrors" value="1">
<input type="hidden" name="debug" value="1">
</form>
]]>
     </programlisting>
    </example>     
   </para>
   <para>
    エラー処理の方法の方法のいかんによらず、エラーを調べる機能は、攻撃
    者により多くの情報を与えることにつながります。
   </para>
   <para>
    例えば、多くの一般的なエラー形式では、システムはPHPを実行している
    ことを示します。攻撃者が .html ページを調べ、(システムの既知の弱点
    を探すために)誤ったデータを送信することによりバックエンドを調べた
    いと思った場合、システムをPHPと共に構築されていることを知ることが
    可能となる可能性があります。
   </para>
   <para>
    関数エラーは、システムが特定のデータベースエンジンが実行しているこ
    と、または、Webページのプログラム内容や設計に関する鍵を示すことが
    あります。これにより、データベースポートをオープンしたり、Webペー
    ジに固有のバグや弱点を調べるといったより詳細な調査を行うことが可能
    となります。例えば、異なった不正なデータを送信することにより、攻撃
    者は、(エラー行番号から)そのスクリプトの異なる場所を調べることと同
    時にそのスクリプトの認証の順番を定義することが可能です。
   </para>
   <para>
    ファイルシステムまたは一般的なPHPエラーは、Webサーバが有する許可属
    性やWebサーバのファイル構造を示すことがあります。エラーコードを書
    く開発者は、元は秘密の情報を容易に公開することにより、この問題を悪
    化させる可能性があります。
   </para>
   <para>
    この問題に対しては3種類の対策があります。最初の対策は、全ての関数
    をよく調べ、大部分のエラーの修正を試みることです。2番目は、実行す
    るコードのエラーリポートを完全に無効にすることです。3番目は、
    PHPのカスタムエラー処理関数を使用して独自のエラーハンドラを作成す
    ることです。システムのセキュリティポリシーに基づき、これらの3種類
    の対策が適用可能かどうかを判定します。
   </para>
   <para>
    この問題を事前に防止する手段の一つは、PHPの
    <function>error_reporting</function>を使用することです。これにより、
    コードを安全にするための手がかりが得られ、危険と思われる変数が使用
    されている部分をみつけることが可能です。実使用の前にE_ALLを指定して
    コードをテストすることにより、変数が他の手段で汚染されたり、修正さ
    れたりする可能性がある部分を簡単に見つけることが可能です。
    実使用の準備ができた際には、E_NONEを使用することにより、コードを外
    部から調べられることを防止することが可能です。
    <example>
     <title>E_ALLで危険な変数を見つける</title>
     <programlisting role="php">
<![CDATA[
<?php
if ($username) {  // 使用前に初期化または確認されていない変数
    $good_login = 1; 
}
if ($good_login == 1) { // 上のテストが失敗した場合、使用前に初期化または確認されていない
    fpassthru ("/highly/sensitive/data/index.html");
}
?>
]]>
     </programlisting>
    </example>
   </para>
  </sect1>

  <sect1 id="security.registerglobals">
   <title>グローバル変数への登録を使用</title>
   <para>
    セキュリティを向上させるために使用可能なPHPの機能の一つは、
    PHPでregister_globals = offを指定して設定を行なうことです。
    ユーザが投稿した変数が全てPHPコードに導入されるこの機能を
    オフにすることにより、潜在的な攻撃者が攻撃できる変数の数を
    減らすことが可能となります。これにより、投稿を作成するため
    により多くの時間を要し、内部変数はユーザにより投稿されたデ
    ータから効率的に隔離することが可能となります。
   </para>
   <para>
    この場合、PHPで動作させるために必要なコードの量は若干増加
    しますが、その利益は努力を上回ると議論されています。
    <example>
     <title>register_globals=offを指定しない場合の動作</title>
     <programlisting role="php">
<![CDATA[
<?php
if ($username) {  // get/post/cookiesで上書きされる可能性がある
    $good_login = 1; 
}

if ($good_login == 1) { // get/post/cookiesで上書きされる可能性がある
    fpassthru ("/highly/sensitive/data/index.html");
}
?>
]]>
     </programlisting>
    </example>
    <example>
     <title>register_globals = offを指定した場合の動作</title>
     <programlisting role="php">
<![CDATA[
<?php
if($HTTP_COOKIE_VARS['username']){ 
    // クッキーから来るもののみ
    $good_login = 1;
    fpassthru ("/highly/sensitive/data/index.html");
}
?>
]]>
     </programlisting>
    </example>
    これを賢く使用することにより、偽の入力が試みされた際に警告を
    発生する防止策をとることさえ可能になります。変数が入力される
    場所を事前に正しく知っている場合、投稿されたデータが適当な場
    所からのものであるかを調べることが可能です。これは、データが
    偽造されていないことを保証するものではありませんが、攻撃者に
    正しい偽造の方法を推定することを強いることになります。
    <example>
     <title>簡単な変数の汚染の有無の検出</title>
     <programlisting role="php">
<![CDATA[
<?php
if ($HTTP_COOKIE_VARS['username'] &&
    !$HTTP_POST_VARS['username'] &&
    !$HTTP_GET_VARS['username'] ) { 
    // ユーザ名を認証する他の手段を実行する
    $good_login = 1;
    fpassthru ("/highly/sensitive/data/index.html");
} else {
   mail("admin@example.com", "侵入が試みられました", $HTTP_SERVER_VARS['REMOTE_ADDR']);
   echo "管理者による警告:セキュリティ違反です。";
   exit;
}
?>
]]>
     </programlisting>
    </example>
    もちろん、register_globalsをoffに変えただけでは、コードが安全である
    ことを意味しません。投稿されたデータのあらゆる部分について、他の
    手段でも確認する必要がありません。
   </para>
  </sect1>

  <sect1 id="security.variables">
   <title>ユーザが送信したデータ</title>
   <para>
    多くのPHPで最も脆弱な部分は、言語自体に起因するものではなく、単に
    セキュリティを考慮して書かれていないコードの問題です。この原因につ
    いて、指定したコードの部分の意味を常に時間をかけて吟味し、予想外の
    変数が投稿された場合に有り得る損害を確かめる必要があります。
    <example>
     <title>危険な変数の使用</title>
     <programlisting role="php">
<![CDATA[
<?php
// ユーザのホームディレクトリからファイルを削除します... または他の誰
// かのディレクトリかも?
unlink ($evil_var);

// 彼らのアクセスのログを書き込む.. または違うかも?
fputs ($fp, $evil_var);

// 何かちょっとしたことを実行.. または rm -rf *?
system ($evil_var);
exec ($evil_var);

?>
]]>
     </programlisting>
    </example>
    常に注意してコードをテストし、Webブラウザから投稿された全ての変数
    について次のような点を確認して下さい。
    <itemizedlist>
     <listitem>
      <simpara>
       このスクリプトは、意図したファイルのみを受け付けるか?
      </simpara>
     </listitem>
     <listitem>
      <simpara>
       例外的なまたは意図したもの以外のデータにより実行することが可能
       か?
      </simpara>
     </listitem>
     <listitem>
      <simpara>
       このスクリプトは意図した以外の方法で使用することが可能か?
      </simpara>
     </listitem>
     <listitem>
      <simpara>
       このスクリプトは、悪い意味で他のスクリプトと組み合わせて使用す
       ることが可能か?
      </simpara>
     </listitem> 
     <listitem>
      <simpara>
       トランザクションは適切に記録されているか?
      </simpara>
     </listitem>
    </itemizedlist>
    スクリプトを書いた後ではなく、書いている時にこれらの質問を適宜行う
    ことにより、セキュリティ改善のために不幸にして書き直しが必要になる
    ということを避けることができます。こうした考慮をまず行うことにより、
    システムのセキュリティを保証できるわけではありませんが、改善の一助
    にはなりえます。
   </para>
   <para>
    register_globals,magic_quotes, または他の便利な設定は、有効性、発
    信元、指定した変数の値について混乱を生じる可能性があるため、設定を
    オフにしたいと思うかもしれません。error_reporting(E_ALL) モードで
    PHPを動作させた場合、確認または初期化する前に使用された変数に関し
    て警告を発生させることも可能です。(これにより、処理時に通常とは異
    なるデータを防止することが可能です)
   </para>
  </sect1>
  
  <sect1 id="security.hiding">
   <title>PHPの隠蔽</title>
   <para>
    一般に隠蔽という手段はセキュリティとしては弱いものだと言われています。
    しかしこうした手法が望ましい場合もあります。
   </para>
   <para>
    PHPを隠すための簡単な技法がいくつかあり、システムの弱点を見つけよ
    うとする攻撃を遅延させることができる可能性があります。php.iniファ
    イルでexpose_php = offと設定することにより、攻撃者が利用可能な情
    報を減らすことが可能です。
   </para>
   <para>
    他の手段は、ApacheのようなWebサーバをPHPに異なるファイル形式をパー
    スさせるように設定することです。これは、.htaccessディレクティブま
    たはApacheの設定ファイル自体で指定します。これにより、紛らわしい
    ファイル拡張子を使用可能です。
    <example>
     <title>PHPを他の言語として隠す</title>
     <programlisting role="apache-conf">
<![CDATA[
# PHPコードを他のコード型のようにする
AddType application/x-httpd-php .asp .py .pl
]]>
     </programlisting>
    </example>
    または、次のように完全に隠すことも可能です。
    <example>
     <title>PHP拡張子用に未知の型を使用する</title>
     <programlisting role="apache-conf">
<![CDATA[
# Make PHP code look like unknown types
AddType application/x-httpd-php .bop .foo .133t
]]>
     </programlisting>
    </example>
    または、HTMLコードとして隠すことも可能です。この場合、全てのHTMLファ
    イルがPHPエンジンを通じてパースされることになるため、若干の性能上の
    問題があります。
    <example>
     <title>PHP拡張子としてHTML型を使用する</title>
     <programlisting role="apache-conf">
<![CDATA[
# 全てのPHPコードをHTMLのように作成する
AddType application/x-httpd-php .htm .html
]]>
     </programlisting>
    </example>
    効率的にこれを使用するには、全てのPHPファイルの名前を上の拡張子に変更
    する必要があります。これは、あいまいさに基づく形式のセキュリティですが、
    欠点の少ない簡単な防衛策です。
   </para>
  </sect1>

  <sect1 id="security.current">
   <title>最新版を維持する</title>
   <simpara>
    PHPは、他の大規模なシステムと同様に、常に調査、改良されています。
    各新バージョンにはしばしばセキュリティ上の問題や設定上の問題、そし
    て、システム全体のセキュリティや安定性に影響するその他の問題を修正
    するためのメジャーまたはマイナーな変更が含まれています。
   </simpara>
   <simpara>
    他のシステムレベルのスクリプト言語やプログラムと同様に、最善のアプ
    ローチは、頻繁に更新し、最新のバージョンとその変更を注視し続けるこ
    とです。
   </simpara>
  </sect1>
 </chapter>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"../../manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->