主な脆弱性
(脆弱性への対処法①)
・OSコマンド・インジェクション
・SQLインジェクション
・ディレクトリ・トラバーサル
・セッションハイジャック
(脆弱性への対処法②)
・クロスサイト・スクリプティング(XSS)
・クロスサイト・リクエストフォージェリー(CSRF)
・HTTPヘッダインジェクション
・クリックジャギング
脆弱性の具体例と対策
OSコマンド・インジェクション
OSコマンド・インジェクションは、ユーザーからデータや数値の入力を受け付けるようなWebサイトなどにおいて、プログラムに与えるパラメータにOSへの命令文を紛れ込ませて不正に操作する攻撃です。
引用:OSコマンドインジェクションの仕組みとその対策
具体的には、以下のような例です。
'use strict';consthttp=require('http');//他のプログラムを実行することができるモジュール。constcp=require('child_process');constserver=http.createServer((req,res)=>{constpath=req.url;//同期的にシェルコマンドを実行するexecSync関数res.end(cp.execSync('echo '+path));});constport=8000;server.listen(port,()=>{console.info('Listening on '+port);});
以上のファイルができたら、サーバーを起動します。
$ node index.js
サーバーを起動したら、以下のURLにアクセスしてください。
http://localhost:8000/taroimo;ls
Image may be NSFW.
Clik here to view.
URLに紛れた、lsというコマンドが実行され、ディレクトリ内のファイルが見えてしまっています。
このようにコマンドが実行できる状態は、メールを送られたり、個人情報が見られたりするなど危険な状態です。
OSコマンド・インジェクションの対処法は、クライアントから受け取ったデータを使ってOSコマンドを実行する処理を含めないことや、コマンドが実行されないようなエスケープ処理をすることです。
SQLインジェクション
SQLインジェクションは、ユーザーが入力したSQLの命令(クエリ)により、データベースが操作されてしまうことです。
例えば、データベースのbooksというテーブルのidが〇〇番から、title, authorのデータを取り出したいときにSQLで以下のように記述します。
id=@idの@idはユーザーが入力する〇〇番を指します。
SELECTtitle,authorFROMbooksWHEREid=@id
この場合@idに、0 OR 1=1を入力したとしたら、
SELECTtitle,authorFROMbooksWHEREid=0OR1=1
となりますが、「WHERE 1=1」とは必ず正(true)であるという意味なので、全てのidに当てはまるデータが取り出されてしまいます。
SQL をアプリケーションから利用する場合、SQL 文のリテラル部分をパラメータ化することが一般的である。パラメータ化された部分を実際の値に展開するとき、リテラルとして文法的に正しく文を生成しないと、パラメータに与えられた値がリテラルの外にはみ出した状態になり、リテラルの後ろに続く文として解釈されることになる。この現象が SQL インジェクションである。
参考:安全なSQLの呼び出し方
これを防ぐためには、パラメータ化する必要があります。
node-postgresモジュールを使った
パラメータ化は以下のようにします。
※ $1には、client.queryの第二引数'3'が入ります。
//node-postgresモジュールの導入const{Client}=require('pg');//データベースの設定constclient=newClient({//データベースの設定を記述する});//データベースへの接続 client.connect();//ここからパラメータ化constquery='SELECT title, author FROM books WHERE id = $1';client.query(query,['3'],(err,result)=>{if(err){console.log(err.stack)}else{console.log(res.rows[0])// {'3'}}})
ディレクトリ・トラバーサル
ディレクトリ・トラバーサルは、意図していないディレクトリ/ファイルの閲覧、操作をされてしまうことです。
これは、ユーザーにファイルを渡すときに、選択的や自動的なファイルの送信を行うことで防ぐことができます。つまり、ユーザーにファイル渡す場合に、条件以外のものを指定できないようにすれば良いのです。
セッションハイジャック
セッションとは、システムにログインしてからログアウトするまでの通信のこと、または通信が確立してから切断されるまでの流れのことを意味します。
セッションハイジャックとは、他人の識別用のID(セッションID)を乗っ取り、なりすましをすることです。
セッションIDとは、WebサーバとWebブラウザで情報を共有する仕組みであるCookieなどを応用し、サーバが初回アクセス時に発行してクライアントが保存するID。以降は通信のたびにクライアント側からセッションIDを申告することで、同時にアクセス中の利用者の識別を行う。利用者自体を継続的に識別するユーザー名などの識別子とは異なり、機械的に生成されて一時的に利用されるもので、一連の通信が終了すると破棄される。同じ利用者が次に通信を開始すると新しいセッションIDが与えられる。
参考:セッションID【SID】
セッションハイジャックをされないようにするためには、セッションIDをハッシュ関数でハッシュ値とします。
ハッシュ関数とは、入力した値から、長さの決まったまったく別の値(ハッシュ値)を生成する関数です。入力した値が1文字でも100文字でも決まった長さのハッシュ値が出力されます。ハッシュ値から元の値を探し出すのは難しいため、会員情報を取り扱うサイトは一般的にパスワードをハッシュ値にしています。会員制度でなくセッションIDで投稿者を判断する2chのような掲示板でも、ハッシュ関数が使われています。
ハッシュ関数のアルゴリズムには次のような種類があります。
・MD5
・bcrypt
・SHA
・RIPEMD
<MD5>
$ echo -n 文字 | md5sum
> 96f5a0cfa940f3a41a2ed3cbd9c55119 -
となります。出力された文字がハッシュ値となります。
htpasswdモジュールを使えば、md5、bcrypt、shaなどのアルゴリズムを使いパスワードをハッシュ値にすることができます。
$ yarn global add htpasswd@2.4.0
> success Installed "htpasswd@2.4.0" with binaries:
- htpasswd
htpasswdは以下のような文法で使います。
$ htpasswd [options] [passwordfile] username [password]
htpasswd [オプションの指定] [パスワードの保存ファイル] [セッションIDなど] [パスワード]
という意味です。
オプションにはどのアルゴリズムを使うかなどの設定ができます。
ハッシュ化し、指定したファイルの中身をみると、以下のようになっているはずです。
username:$2aUHuh8uUG33jHUBUuHijofoBVUDE3aAQ98B1QNt3RC
このようにセッションIDを使う際は、セッションハイジャックされないように、ハッシュ値にして保存しておくと良いです。