Contenu connexe
Similaire à 文字コードの脆弱性はこの3年間でどの程度対策されたか?
Similaire à 文字コードの脆弱性はこの3年間でどの程度対策されたか? (20)
Plus de Hiroshi Tokumaru (17)
文字コードの脆弱性はこの3年間でどの程度対策されたか?
- 2. 徳丸浩の自己紹介
•
経歴
– 1985年 京セラ株式会社入社
– 1995年 京セラコミュニケーションシステム株式会社(KCCS)に出向・転籍
– 2008年 KCCS退職、HASHコンサルティング株式会社設立
•
経験したこと
– 京セラ入社当時はCAD、計算幾何学、数値シミュレーションなどを担当
– その後、企業向けパッケージソフトの企画・開発・事業化を担当
– 1999年から、携帯電話向けインフラ、プラットフォームの企画・開発を担当
Webアプリケーションのセキュリティ問題に直面、研究、社内展開、寄稿などを開始
– 2004年にKCCS社内ベンチャーとしてWebアプリケーションセキュリティ事業を立ち
上げ
•
現在
– HASHコンサルティング株式会社 代表
http://www.hash-c.co.jp/
– 独立行政法人情報処理推進機構 非常勤研究員
http://www.ipa.go.jp/security/
– 著書「体系的に学ぶ 安全なWebアプリケーションの作り方」(2011年3月)
– 技術士(情報工学部門)
Copyright © 2012-2014 HASH Consulting Corp.
2
- 5. デモ1:PHPソース
<?php
session_start();
header('Content-Type: text/html; charset=Shift_JIS');
$p1 = @$_GET['p1'];
$p2 = @$_GET['p2'];
?>
<body>
<form>
PHP Version:<?php
echo
htmlspecialchars(phpversion(), ENT_NOQUOTES, 'Shift_JIS')
; ?><BR>
<input name=p1 value="<?php echo
htmlspecialchars($p1, ENT_QUOTES, 'Shift_JIS'); ?>"><BR>
<input name=p2 value="<?php echo
htmlspecialchars($p2, ENT_QUOTES, 'Shift_JIS'); ?>"><BR>
<input type="submit" value="更新">
</form>
</body>
Copyright © 2010-2014 HASH Consulting Corp.
5
- 6. デモ1:半端な先行バイトによるXSS
閉じる引用符が食われた状態
<input name=p1 value="・><BR>
<input name=p2 value=" onmouseover=alert(document.cookie)//"><BR>
ここで最初の属性値がようやく終
了
第二の属性値がイベントハンドラ
に
• 半端な先行バイトによるXSSが発生する条件は、
以下のいずれかを満たす場合
– htmlspecialcharsの第3引数を指定していない
– PHPの5.2.11以前あるいはPHP5.3.1以前を使用
• 対策としては、以下の両方を行う
– PHPの最新版を使う
– htmlspecialcharsの第3引数を指定する
Copyright © 2010-2014 HASH Consulting Corp.
6
- 7. デモ2:UTF-8非最短形式によるパストラバー
サル
String msg = "";
String pathname = "";
try {
String path = request.getParameter("path");
File f = new File(path);
// パス名からファイル名を取り出す(PHPのbasename())
String filebody = f.getName();
// UTF-8としてデコード
filebody = new String(
filebody.getBytes("ISO-8859-1"), "UTF-8");
// ディレクトリを連結
pathname = "c:/home/data/" + filebody;
// 以下ファイル読み出し
FileReader fr = new FileReader(pathname);
BufferedReader br = new BufferedReader(fr);
・・・
Copyright © 2010-2014 HASH Consulting Corp.
7
- 10. ソースコード(要点のみ)
<?php
header('Content-Type: text/html; charset=Shift_JIS');
$key = @$_GET['name'];
if (! mb_check_encoding($key, 'Shift_JIS')) {
die('文字エンコーディングが不正です');
}
// MySQLに接続(PDO)
$dbh = new PDO('mysql:host=localhost;dbname=books', 'phpcon', 'pass1');
// Shift_JISを指定
$dbh->query("SET NAMES sjis");
// プレースホルダによるSQLインジェクション対策
$sth = $dbh->prepare("SELECT * FROM books WHERE author=?");
$sth->setFetchMode(PDO::FETCH_NUM);
// バインドとクエリ実行
$sth->execute(array($key));
?>
Copyright © 2010-2014 HASH Consulting Corp.
10
- 12. 5C問題によるSQLインジェクションの対策
• データベース接続時に文字エンコーディングを正しく設
定する
– 文字エンコーディングを設定できるライブラリを選択する
– アプリケーション上で、文字エンコーディングを設定する
• PDOは、PHP5.3.7から上記ができるようになった
<?php
$dbh = new PDO('mysql:host=xxx;dbname=xxx;charset=utf8',
USERNAME, PASSWORD);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$sth = $dbh->prepare("select * from test WHERE a=? and c=?");
$sth->bindParam(1, $a, PDO::PARAM_STR);
$sth->bindParam(2, $c, PDO::PARAM_INT);
$sth->execute();
Copyright © 2010-2014 HASH Consulting Corp.
12
- 15. デモ5:U+00A5によるSQLインジェクション
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(
"jdbc:mysql://localhost/books?user=phpcon&passwo
rd=pass1");
String sql = "SELECT * FROM books where author=?";
// プレースホルダ利用によるSQLインジェクション対策
PreparedStatement stmt =
con.prepareStatement(sql);
// ? の場所に値を埋め込む(バインド)
stmt.setString(1, key);
ResultSet rs = stmt.executeQuery(); // クエリの実行
Copyright © 2010-2014 HASH Consulting Corp.
15
- 17. U+00A5によるSQLインジェクションの条件と対
策
• 脆弱性が発生する条件
– JDBCとしてMySQL Connector/J 5.1.7以前を使用
– MySQLとの接続にShift_JISあるいはEUC-JPを使用
– 静的プレースホルダを使わず、エスケープあるいは動的プレー
スホルダ(クライアントサイドのバインド機構)を利用してい
る
• 対策(どれか一つで対策になるがすべて実施を推奨)
– MySQL Connector/Jの最新版を利用する
– MySQLとの接続に使用する文字エンコーディングとして
Unicode(UTF-8)を指定する
(接続文字列にcharacterEncoding=utf8を指定する)
– 静的プレースホルダを使用する
(接続文字列にuseServerPrepStmts=trueを指定する)
Copyright © 2010-2014 HASH Consulting Corp.
17
- 18. デモ6:U+00A5によるXSS
// PHPでもU+00A5がバックスラッシュに変換されるパターンはないか
<?php
header('Content-Type: text/html; charset=Shift_JIS');
$p = @$_GET['p'];
// JSエスケープ → '→' "→ "
$p1 = preg_replace('/(?=['"])/u' , '', $p);
$p2 = htmlspecialchars($p1, ENT_QUOTES, 'UTF-8');
?>
<html><head>
<script type="text/javascript">
function foo($a) {
document.getElementById("foo").innerText= $a;
}
</script></head>
<body onload="foo('<?php echo $p2; ?>')">
p=<span id="foo"></span>
[mbstring]
mbstring.internal_encoding = UTF-8
</body>
mbstring.http_input = auto
</html>
mbstring.http_output = cp932
mbstring.encoding_translation = On
mbstring.detect_order = SJIS-win,UTF-8,eucJP-win
Copyright © 2010-2014 HASH Consulting Corp.
18
- 20. デモ7: SQL Serverの文字集合問題
• ASP.NET + MS SQL Server + JSON
• 1行掲示板
• 問題の原因はMS SQL Serverの以下のテーブル定義
CREATE TABLE chat1 (
id int IDENTITY (1, 1) NOT NULL ,
ctime datetime NOT NULL,
body varchar (150) NOT NULL,
json varchar (200) NOT NULL
)
• json列にJSON形式に加工済みの投稿情報を格納して、閲
覧時には「そのまま」レスポンスとして返す
• 問題はどこに?
Copyright © 2010-2014 HASH Consulting Corp.
20
- 21. 投稿スクリプト
sqlUrl = "Server=labo1; database=tokumaru;user id=sa;password=xxxxx”
dbcon = New SqlConnection(sqlUrl) 'DBコネクション作成
dbcon.Open()
'DB接続
sqlStr = "insert into chat1 values(sysdatetime(), @body, @json)"
dbcmd = New SqlCommand(sqlStr, dbcon)
body = Request("body")
e_body = Regex.Replace(body, "([<>'""])", "$1")
e_body = Regex.Replace(e_body, "[rn]", "")
' JSON組み立て
json = "{""ctime"":""" _
& DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") _
& """, ""body"":""" & e_body & ""“}"
' パラメータ
dbcmd.Parameters.Add(New SqlParameter("@body", body))
dbcmd.Parameters.Add(New SqlParameter("@json", json))
dbResult = dbcmd.ExecuteNonQuery()
Copyright © 2010-2014 HASH Consulting Corp.
21
- 22. 表示(HTML)
<html><head><script src="jquery-1.4.3.min.js"></script>
<script>
function load()
{
var requester = new XMLHttpRequest();
requester.open('GET', 'json.aspx', true);
requester.onreadystatechange = function() {
if (requester.readyState == 4) {
onloaded(requester);
}
};
requester.send(null);
}
function onloaded(requester)
{
res = requester.responseText;
obj = eval("(" + res + ")");
$('#result').text(obj.ctime + ":" + obj.body);
}
</script></head><body>
<input type="button" onclick="load();" value="hoge"/>
<div id="result"></div></body>
Copyright © 2010-2014 HASH Consulting Corp.
22
- 23. 表示(JSON)
sqlUrl = "Server=labo1; database=tokumaru;user id=sa;password=xxxx"
dbcon = New SqlConnection(sqlUrl)
'DBコネクション作成
dbcon.Open() 'DB接続
sqlStr = "select top 1 * from chat1 order by id desc"
dbcmd = New SqlCommand(sqlStr, dbcon)
'SQL文実行
dataRead = dbcmd.ExecuteReader()
dataRead.Read()
Response.AddHeader("Cache-Control", "no-cache")
Response.AddHeader("Content-Type", "application/json")
'ラベルに表示
Response.write(dataRead("json")) ' エスケープ済みなのでそのまま表示
Copyright © 2010-2014 HASH Consulting Corp.
23
- 24. 脆弱性の原因
• MS SQL Serverのvarcharは、CP932(マイクロソフト標
準キャラクタセットのShift_JIS)となる
• Unicodeの列はnvarcharで宣言すること
• varchar型の列にinsertする際に、Unicode→CP932の文字
エンコーディング(文字集合)の変換が発生する
– U+00A5(円記号)は0x5Cに
Copyright © 2010-2014 HASH Consulting Corp.
24
- 25. 対策
• 以下のいずれかを実施すれば脆弱性は発生しない
– JSONの組み立てを表示(出力)の直前に行う
• DB格納前の組み立ては危険
– 英数字以外の文字は、Unicode形式でエスケープする
• uNNNNの形式
• いわゆる過剰エスケープ(個人的には嫌いだがやむなし)
– 文字集合の変更をしない(nvarcahr型の列を使う)
– JSONの解釈にevalを使わない
• jQuery使うなら、とことん使えよ
• JSONPの場合は、実質evalと同じなので他の対策で…
• 「いずれか」ではなく「すべて実施」を推奨
Copyright © 2010-2014 HASH Consulting Corp.
25
- 31. UTF-7 XSSを巡る冒険
• IEの古典的なUTF-7 XSSは、MS10-090(2010年12月)にて改修され
ている
– 文字エンコーディング推測の変更
• ただし、MS10-090のドキュメントには明記されていない
• MS10-090に含まれるIEの改修は2種類
– CVE-2010-3342とCVE-2010-3342
– どちらもキャッシュ周りの脆弱性…同じもののように見える
• 以下は、はせがわようすけさんの推測(MS確認済み)
– CVE-2010-3342は文字コード関連の脆弱性の修正である
– CVE-2010-3348はキャッシュ周りの脆弱性の修正である
– MS10-090内の記述が誤っている
• script要素で文字エンコーディングを指定する攻撃方法は依然とし
て有効なので注意
Copyright © 2010-2014 HASH Consulting Corp.
31