The best prevention is to deactivate master..xp_cmdshell.
Run in isql the command `sp_configure 'xp_cmdshell''
If the value for "config value" is 1 then make in the isql
`sp_configure 'xp_cmdshell',0'.
If you want see the options from your mssql-Server make
`sp_configure 'show advanced options',1'
and then `sp_configure'
SQLインジェクション
多くの開発者はSQLクエリがどのように改竄されるかということを余り 気にかけておらず、またSQLクエリは信用できるものと考えているようです。 実際にはSQLクエリはアクセス制限を回避することが可能で、従って 通常の認証や権限のチェックを無視することができます。時には、 OSレベルのコマンドを実行できてしまうこともあります。
ダイレクトSQLコマンドインジェクション(SQLコマンドの直接実行)という手法は、 攻撃者がSQLコマンドを生成もしくは既存のコマンドを変更することで 隠蔽すべきデータを公開したり、重要なデータを書き換えたり、データベース ホストで危険なシステムレベルのコマンドを実行したりするものの事です。 この手法は、ユーザからの入力をスタティックなパラメータと組み合わせて SQLクエリを生成するアプリケーションにおいて使用されます。以下の例は 不幸なことに実際の事例に基づいたものです。
入力のチェックを怠っており、スーパーユーザもしくはデータベース作成権限を 持つユーザ以外のユーザでデータベースに接続していない ために、攻撃者はデータベースにスーパーユーザを作成することが出来ます。
例1 表示するデータを分割し ... そしてスーパーユーザを作成します。 (PostgreSQLの例)
$offset = $argv[0]; // 入力チェックが行われていません!
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
$result = pg_query($conn, $query);
0;
insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
select 'crack', usesysid, 't','t','crack'
from pg_shadow where usename='postgres';
--
注意: SQLパーサにクエリの残りの部分を無視させるために開発者によく使わ れる技法として、SQLのコメント記号である--があ ります。
パスワードを取得する恐るべき手段に、サイトの検索結果のページを欺く というものがあります。攻撃する者が必要とするものは、投稿された変数 の中でSQL命令で使用される際に正しく扱われていないものがあるかどう かを確かめるだけです。これらのフィルタは、通常、 SELECT文のWHERE, ORDER BY, LIMIT及びOFFSET句をカスタマイズするた めに前に置かれる形で設定されます。使用するデータベースが UNION構造をサポートしている場合、 攻撃者は元のクエリに任意のテーブルからパスワードのリストを取得する クエリを追加しようとするかもしれません。 暗号化されたパスワードフィールドを使用することが強く推奨されます。
例2 記事...そして(全てのデータベースサーバーの)いくつかのパスワード のリストを表示する
$query = "SELECT id, name, inserted, size FROM products
WHERE size = '$size'
ORDER BY $order LIMIT $limit, $offset;";
$result = odbc_exec($conn, $query);
' union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from usertable; --
SQL UPDATE もデータベースを攻撃するために使用されます。これらのク エリも切捨てたり新しいクエリを元のクエリに追加することによる攻撃 を受けます。しかし、攻撃者はSET句を使用する可 能性があります。この場合、クエリを成功させるためにいくつかのスキー マ情報を保有する必要があります。これは、フォームの変数名や総当た り法により調べることができます。パスワードまたはユーザ名を保存す るフィールド用の命名記法はそう多くはありません。
例3 パスワードのリセットから ... (全てのデータベースサーバーで)より多 くの権限を得るまで
$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";
// $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 ...;"
恐ろしい例として、いくつかのデータベースホストのオペレーティン グシステムレベルのコマンドがアクセス可能となる方法を示します。
例4 データベースホストのオペレーティングシステムを攻撃する (MSSQLサーバー)
$query = "SELECT * FROM products WHERE id LIKE '%$prod%'";
$result = mssql_query($query);
$query = "SELECT * FROM products
WHERE id LIKE '%a%'
exec master..xp_cmdshell 'net user test testpass /ADD'--";
$result = mssql_query($query);
注意: 上記のいくつかの例は、データベースサーバの種類に依存しています。 これは、他の製品に対して同様な攻撃ができないことを意味するもので はありません。使用しているデータベースが他の手段で攻撃可能である 可能性もあります。
回避する方法
ほとんどの例では攻撃する者は特定のデータベースのスキーマに関して 若干の情報を保有している必要があると弁解されるかもしれません。 これは正しいですが、いつ何時これが外部にもれうるかを知ることはで きませんし、いったんこの情報がもれると、データベースが外部に開示 される可能性があります。オープンソースまたは一般的に入手可能なデー タベース処理パッケージを使用している場合(これはコンテンツ監理シス テムまたはフォーラムに含まれている可能性があります)、侵入者は簡単 に使用されているコードの一部を入手することができます。そのコード の設計が悪い場合にもセキュリティリスクを生じる可能性があります。
これらの攻撃は、セキュリティを考慮して書かれていないコードを攻撃 する方法です。特にクライアント側から入力されるあらゆる種類の入力 を決して信用しないでください。これは、selectボックスやhidden input フィールド、Cookieの場合も同様です。最初の例は、このような欠点の ないクエリが破滅をもたらしうることを示すものです。
- データベースにスーパーユーザーまたはデータベースの所有者として 接続しないでください。 非常に制限された権限を有するカスタマイズ されたユーザを常に使用してください。
- 指定された入力が期待するデータ型であることを確認してください。 PHPは、多くの種類の入力検証用関数を有しており、 変数関連の関数や 文字型関数にある簡単な関数 (例: それぞれ、is_numeric(), ctype_digit()) や、 Perl互換の正規表現のサポートま であります。
-
アプリケーションが、数値入力を期待している場合、データを is_numeric()で検証するか、 settype()により暗黙の型変換を行うか、 sprintf()により数値表現を使用することを検討 してみてください。
例5 ページング用のクエリを構築するためのより安全な方法
settype($order, 'integer');
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
// フォーマット文字列の%dに注意してください。%sを使用しても意味がありません。
$query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;",
$offset); - データベースに渡される数値以外のユーザ入力を データベース固有の文字列エスケープ関数 (mysql_real_escape_string(), sql_escape_string(), など) でクオートしてください。 データベース固有の文字列エスケープ機能が利用できない場合、 addslashes() および str_replace()関数が利用できるでしょう。 (データベースの型に依存) 最初の例を参照 してください。前期の例が示すように、クエリの静的な部分をクオート するだけでは充分ではなく、簡単にクラックされてしまう可能性があ ります。
- データベース固有の情報、特にスキーマに関する情報は出力してはい きません。エラー出力およ びエラー処理およびログ関数 も参照ください。
- ユーザがテーブルまたはビューに直接アクセスできないように、 データアクセスを抽象化することを目的としてストアドプロシージャ 及び事前に定義したカーソルを使用することもできますが、このソリュー ションには、副作用があります。
これらのケースにおいて、スクリプトまたはサポートされている場合は データベース自体でクエリのログをとることが有益です。 明らかにログは破壊的な行為を防止することはできませんが、攻撃され たアプリケーションを追跡する際には有効です。ログ自体は有益ではあ りませんが、含まれている情報は有益です。通常、より詳細なログをと る方が良いでしょう。
SQLインジェクション
12-Nov-2008 01:53
13-Oct-2008 11:32
dark dot avenger at email dot cz wrote:
"I think that easy way to protect against SQL injection is to convert inputted data into binary format, so that whatever input is, in sql query it will consist only of 1s and 0s."
Unless there is a 1-to-1 correspondence between your inputted data and the characters in your 'binary' format, a SELECT query wouldn't work anymore. Not a binary format, but it makes my point: MIME encoding the text 'Dark Avenger' results in 'RGFyayBBdmVuZ2Vy'. If I wanted to look up anyone with 'Avenger' in his/her name, then 'Avenger' would be encoded as 'QXZlbmdlcg==' which clearly wouldn't result in a hit on 'RGFyayBBdmVuZ2Vy'.
If there IS a 1-to-1 correspondence, then EITHER your solution only makes it a bit harder to perform a SQL injection (a hacker would have to figure out what mapping was used between the text and the 'binary' format), OR you've come up with simply another way to escaping your data. Either isn't a terribly good solution to the SQL injection problem.
14-Aug-2008 10:09
I think that easy way to protect against SQL injection is to convert inputted data into binary format, so that whatever input is, in sql query it will consist only of 1s and 0s.
15-Apr-2008 09:23
Note that PHP 5 introduced filters that you can use for untrusted user input:
http://us.php.net/manual/en/intro.filter.php
01-Aug-2006 05:39
This is a very helpful document from the MySQL site (in .pdf format) :
http://dev.mysql.com/tech-resources/articles/
guide-to-php-security-ch3.pdf
If you use the PEAR package and prepare() / execute() your queries,
you will hardly have to worry about any of this. Of course, it's still
a good idea to make sure you're putting valid data in your database...
25-Jan-2005 09:42
Here is a useful class that deals with SQL injection:
http://www.phpinsider.com/php/code/SafeSQL/
