ホーム > security

securityのアーカイブ

X-Content-Type-Options: nosniffのつけ方

  • 投稿者: chiba
  • 2011/1/6 木曜日 12:49:29
  • security

Apache

mod_headersでできます

Header set X-Content-Type-Options nosniff

Nginx

add_header X-Content-Type-Options nosniff;

但し、上記だとproxyなんかで既にX-Content-Type-Options: nosniff;が付いていると

X-Content-Type-Options: nosniff, nosniff

のようなヘッダになってしまう。問題ないかもしれないが気になる場合はNginxHttpHeadersMoreModuleを使って

more_set_headers 'X-Content-Type-Options: nosniff';

とすると良いのかも。

Plack

Plack::Middleware::Headerを使うと簡単です。

enable 'Header', set => ['X-Content-Type-Options' => 'nosniff'];

参考: X-Content-Type-Options: nosniff つかわないやつは死ねばいいのに!

UTF-16時代のエスケープ処理

Connector/JのSQLインジェクション脆弱性

えーと、変換後がUCS-2とかだとマズいかな?

…(実験中)…

試作パッチ以前に、Connector/Jでcharacter_set_server=ucs2のサーバに繋がらないんですけど。
Connector/J側でcharacterEncoding=UTF-8などとしておけば繋がりますが、こんな仕様あったかな…。

そもそもucs2は現在クライアントキャラクタセットとしては使えないんじゃないでしょうか。

9.1.9. Unicode Support

UCS-2 cannot be used as a client character set,
which means that SET NAMES 'ucs2' does not work.
(See Section 9.1.4, “Connection Character Sets and Collations”.)

ちなみにUCS-2とかUTF-16のようにASCIIな部分までマルチバイトなキャラクタセットが使えるとなると、Cのmysql_real_escape_stringも問題が発生しそうですね。マルチバイトはエスケープ対象外という処理でShift_JIS(やGBK)の5c問題を解決しているようなので。これは現在のサポート文字セットに依存した脆弱な実装ということになるんでしょうか。

そんな時代がくるのか分かりませんが、perl的にUTF-16時代の正しいescape処理を考えてみるとこんな感じ?

#!/usr/bin/perl
use strict;
use warnings;

use utf8;
use Encode;

# from DBD::mysqlPP::quote
my @quote_target = (
    "\\"   => '\\\\',
    "\0"   => '\\0',
    "\n"   => '\\n',
    "\r"   => '\\r',
    "'"    => q{\\'},
    '"'    => '\\"',
    "\x1a" => '\\Z',
);

my $str = "I'm sorry\nok.";

print quote($str, 'utf-16LE');

sub quote {
    my ($str, $charset) = @_;

    my %quote_target_for_charset = map { Encode::encode($charset, $_) } @quote_target;

    $str =~ s{
        (.)
    }{
        my $bytes = Encode::encode($charset, $1);
        $quote_target_for_charset{$bytes} // $bytes;
    }exmsg;

    return $str;
}

Yen markのhtmlでのエスケープもなんかへんな感じになってるのでファイルごとup
1文字ずつencodeしてるのはなんかやーなかんじですね。試してないけどRubyだと$KCODEの切り替えを使うとencode的な事は1回で済むのかも。あとで試してみよう。

useServerPrepStmtsを使うのが根本解決だとはおもう。けど…?

  • 投稿者: chiba
  • 2008/12/23 火曜日 23:15:54
  • java | security

UnicodeのU+00A5問題

JavaとMySQLの組み合わせでUnicodeのU+00A5を用いたSQLインジェクションの可能性
なるほど。この問題は初耳だったので驚いた。

しかも、PreparedStatementを使っても解決されないという。この部分に非常に驚いたのでどういうことなのか少し調べてみた。

PreparedStatementとは?

mysqlにおける話としてはPrepared Statement (訳)がとてもわかりやすい。
なかでも重要なのは以下の部分だ。

PerlとJava のユーザはかなり長い間prepared statementを使って
きました。しかし、これらはクライアント側のprepared
statementでした。
クライアント側のprepared statementは同じようなセキュリティの恩恵
をもたらしますが、性能向上には至りません。でも心配いりません。
MySQL Connector/J は3.1のリリースでサーバーサイドprepared statement
をサポートします。

そして実は現在のConnector/Jの最新版(5.1.7)ではデフォルトでは「サーバーサイドprepared statement」を使っていないのである。そしてクライアントサイドのprepared statementは結局のところエスケープ関連のセキュリティ脆弱性を潜在的に抱えてしまう存在なのである。そして実際に今回の問題があった。

Connector/JでサーバーサイドのPreparedStatementを使う

jdbcのURLにuseServerPrepStmts=trueをつけるだけである。

      Connection con = DriverManager.getConnection(
        "jdbc:mysql://localhost/tokumaru?user=xxx&password=xxxx&useUnicode=true&useServerPrepStmts=true&characterEncoding=" + charEncoding)

簡単ですね。こうすることにって、U+00A5問題は発生しません。エスケープ自体どの時点でもしないわけですから。めでだしめでたし。

しかし、useServerPrepStmtsのデフォルト変更問題が

useServerPrepStmtsのここの説明ではデフォルトがtrueになっているが、これは上述の通り嘘である。ちなみに英語マニュアルをみるときちんとfalseになっている。これにはuseServerPrepStmtsの登場時(Connector/J 3.1.0)にはデフォルトがtrueだったが、5.0.55.1.0においてfalseに変更されたという経緯があるためのようだ。そしてなぜfalseにされたかということの背景を察すると、trueにすることの弊害もありそうで、手放しでこれをtrueにすることを勧めることが少しはばかられる。これについて詳しい方がいたらぜひ説明をお願いしたいところである。

ホーム > security

検索
フィード
メタ情報

ページの上部に戻る