インジェクション攻撃とは、不正な入力によりサーバーを誤動作させる攻撃手法である。
商用サイトを中心として、Webページには一般ユーザーからの入力を受け付けるものも多い。こういったページはユーザーからの入力をサーバーが受け取った後、入力情報を元に適切な処理が行われる仕組みになっている。
ところがサーバーに脆弱性があると、入力情報の中にコンピューターに対する命令と解釈される文字列を埋め込むこと(Code injection)によってサーバー側が意図していない動作を行わせることができる。これがインジェクション攻撃である。
文字列に「文字列の終了を表す表現」を埋め込んだ後に、実行させたい命令文につなげるというのが大まかな手口になる。もう少し具体的なイメージを掴みたい人は下記の9分40秒あたりから12分過ぎまでを参照のこと。
SQLはデータベースサーバー用言語のデファクトスタンダードに近い存在である。SQLインジェクションではSQLとして解釈される入力を用いて攻撃を行う。一般ユーザーの入力はSQL命令に組み込まれる形でデータベースサーバーに渡されることが多いので狙われやすい。
データベースサーバーには各ユーザーの個人情報や運営企業が他社との差別化のために苦労して集めたデータなど大事な情報が詰まっていることが多い。そこから任意の情報が読み出されたり、書き込まれたり、ひどい場合は全部抜き取られた上で消去されたりする危険もある。
NoSQLのデータベースサーバーを標的にした攻撃も存在するので、SQLでなければ安心ということではなく、データベースサーバーは狙われやすいと考えておいた方が良い。
SQLではなく、OS用のコマンドを入力に埋め込む方法。ユーザーの入力がOSに渡される仕様のサーバーというのは少ないはずだが、もし実行されるとOSそのものが乗っ取られ、OS上で動くサーバープログラムに過ぎないデータベースサーバーが乗っ取られたときより被害は大きい。
攻撃者が直接入力を行わないケース。不正な入力データを送信するリンクを被害者にクリックさせて、HTTPヘッダに入力内容が反映されるサイトで不正な内容を表示させる。
ヘッダーにはCookieの扱いに関する命令を含めることが出来るため、被害者のCookieを変更することも可能。他にはヘッダーに続けて本文まで偽造することも可能である。
一般ユーザーから「問い合わせ」ページなどに入力があると自動的にメールで管理者や担当者に通知する仕様になっているサーバーは多い。この際、「件名」の入力がメールの"Subject:"の行に使用されるといったように、入力がそのままメールヘッダ領域に反映される場合に攻撃対象になる。
メールヘッダインジェクションでは上記「件名」の欄に改行を入れ、その後にメールヘッダとして解釈される任意のコードを挿入する。たとえば"Bcc:"を挿入するとスパムメールの送信に用いることができる。
一般ユーザーの入力内容確認のためにユーザー入力全文を表示するサイトは多いが、ここにHTMLと解釈される文字列を埋め込むと、不正な入力確認画面を表示できる。
HTMLには<script>タグでJavaScriptを埋め込んだり<iframe>で別のサイトを表示できたりすることを考えると、様々な被害が考えられる。クロスサイトスクリプティング攻撃(XSS)などに使用される。
一般ユーザーからの入力は疑ってかかるのが基本である。クライアント側のコードは改造可能なので原則としてサーバー側で対策を行う。
入力欄に、処理系で文法上の意味を持つ文字や記号の入力を禁止する。あるいは、サーバー側で想定している文字列の入力のみを許可する。
大抵の処理系は、文法上意味のある文字(記号)を、文字列内で文法上の意味を持たないただの文字として使用するためのエスケープという記法が用意されている。
ユーザーからの入力にインジェクション攻撃を意図した文字列があったとしても、処理系に渡す前にエスケープ処理すれば、文法上の解釈を受けることなくただの文字として仕様通り処理される。サニタイズとも呼ばれる。
エスケープ処理を1回余計にやってしまって、「>」が「>」になるといったようにエスケープ処理が残ったまま表示されることがあるのはご愛嬌。
スクリプト言語処理系だからユーザーの入力が命令として解釈される。コンパイルしてバイナリにしてしまえばユーザーが入力した文字列とコンピューターへの命令が混ざることはない、というコンセプト。
SQLではプリペアドステートメントと呼ばれる。
import textwrap
f = open("init.sql", 'w')
f.write(textwrap.dedent("""\
-- -*- coding: utf-8; mode: sql; sql-product: sqlite; -*-
DROP TABLE IF EXISTS emp;
CREATE TABLE emp(eid INTEGER PRIMARY KEY, ename TEXT);
INSERT INTO emp(ename) VALUES ('のぶお');
INSERT INTO emp(ename) VALUES ('たけし');
INSERT INTO emp(ename) VALUES ('ひろゆき');
SELECT * FROM emp;
"""))
f.close()
!sudo apt-get install -y sqlite3
!sqlite3 test.db < init.sql
while True:
f = open("append.sql", 'w')
f.write(textwrap.dedent("""\
-- -*- coding: utf-8; mode: sql; sql-product: sqlite; -*-
INSERT INTO emp(ename) VALUES ('{}');
SELECT * FROM emp;
""").format(input("追加する名前: ")))
f.close()
!sqlite3 test.db < append.sql
しげたか'); DELETE FROM emp WHERE ename IN ('ひろゆきをコピペしてエンター
ニコニコ大百科:グラフ機能のダウンロード版(サポート終了済み)にはHTMLインジェクション攻撃が可能である。といってもダウンロード版なので、自分で自分にインジェクション攻撃できるだけであり、特にセキュリティ上の問題はない。ユーザーが色以外も指定できたら何か面白いことが出来ないかなと思っていたのでこれは仕様である。
3行目のred(太字)は仕様通りの色指定方法だが、その後にHTMLの<div>要素の一部として認識される不正なコード(緑字 + 赤字)が追加されている。
0.0, 0.0
170.0,0.0
300, 80.0,red; transform: rotate(44deg); margin: 54.0000px 0 0 262.0000px;"></div><div style="background: #fc9; border-radius: 40px; width: 80px; height: 80px
500.0, -110.0
記事にある使用例と比べると、本来直線しか出力する機能がないのに、塗りつぶされた円が出力されているのがわかる。
HTMLソースで見ると下記のようになっている。緑字 + 赤字が不正に追加された部分で、入力の不正部分と完全に一致している。
<div><div style="border: 1px solid green; height: 150px; width: 500px;"></div><div style="border: 1px solid green; height: 150px; width: 500px;">
<div style="height: 1px; width:170.0000px; background-color: red; transform: rotate(0deg); margin: -1.0000px 0 0 0.0000px;"></div>
<div style="height: 1px; width:153.0000px; background-color: red; transform: rotate(-32deg); margin: -41.0000px 0 0 158.5000px;"></div>
<div style="height: 1px; width:276.0000px; background-color: red; transform: rotate(44deg); margin: 54.0000px 0 0 262.0000px;"></div><div style="background: #fc9; border-radius: 40px; width: 80px; height: 80px; transform: rotate(44deg); margin: 54.0000px 0 0 262.0000px;"></div>
</div></div>
正規 | <div style="height: 1px; width:276.0000px; background-color: red; transform: rotate(44deg); margin: 54.0000px 0 0 262.0000px;"></div> |
---|---|
不正 | <div style="height: 1px; width:276.0000px; background-color: red; transform: rotate(44deg); margin: 54.0000px 0 0 262.0000px;"></div><div style="background: #fc9; border-radius: 40px; width: 80px; height: 80px; transform: rotate(44deg); margin: 54.0000px 0 0 262.0000px;"></div> |
正規の入力ではred(太字)で色指定を受けた単一のdiv要素(青字)であるが、前述の不正な入力を受けると、
という手順を踏んで、不正なdiv要素(こちらを参考にした円を出力するHTML)が追加されたのである。
ゲームアツマール版のニコニコ大百科:グラフ機能には対策が施されており、前述の入力に対しては「不正な色文字列です。」と出力される。
掲示板
15 ななしのよっしん
2021/05/25(火) 23:17:52 ID: p5xGJgNric
素晴らしい記事
16 ななしのよっしん
2021/05/26(水) 06:30:08 ID: 2/4Tu7VAH9
>>11
>>4にはおこられそうですが対応しました。
>>14
反映しました。ただし、こちらでは検証していないので利用者は自己責任でお願いいたします。
>>15
ありがとうございます。恐縮です。
17 ななしのよっしん
2021/05/26(水) 08:14:48 ID: jpnog08uda
「えー、まだキャブ車なんですかー?」
「えー、まだ旋盤削り出しなんですかー?」
急上昇ワード改
最終更新:2024/04/25(木) 17:00
最終更新:2024/04/25(木) 17:00
ウォッチリストに追加しました!
すでにウォッチリストに
入っています。
追加に失敗しました。
ほめた!
ほめるを取消しました。
ほめるに失敗しました。
ほめるの取消しに失敗しました。