文字セットSQLインジェクション

3377 ワード

SQL注入
  • 以前は、一部の文字セットが変換されると注入につながることを知っていただけで、実際の例は見つかりませんでしたが、今は記録を見ています.BIG5, CP932, GB2312, GBK and SJIS are blacklisted as they may introduce a SQL injection vulnerability!
  • コード(php言語)
    mysql_query('SET NAMES gbk');
    $var = mysql_real_escape_string("\xbf\x27 OR 1=1 /*");
    mysql_query("SELECT * FROM test WHERE name = '$var' LIMIT 1");
  • 原理
  • Selecting a Character Set
    mysql_query('SET NAMES gbk');
    For this attack to work, we need the encoding that the server's expecting on the connection both to encode ' as in ASCII i.e. 0x27 and to have some character whose final byte is an ASCII\i.e. 0x5c. As it turns out, there are 5 such encodings supported in MySQL 5.6 by default: big5, cp932, gb2312, gbk and sjis. We'll select gbk here. Now, it's very important to note the use of SET NAMES here. This sets the character set ON THE SERVER. If we used the call to the C API function mysql_set_charset() , we'd be fine (on MySQL releases since 2006). But more on why in a minute...
  • The Payload The payload we're going to use for this injection starts with the byte sequence 0xbf27. In gbk, that's an invalid multibyte character; in latin1, it's the string ¿'. Note that in latin1 and gbk, 0x27 on its own is a literal ' character. We have chosen this payload because, if we called addslashes() on it, we'd insert an ASCII\i.e. 0x5c, before the ' character. So we'd wind up with 0xbf5c27, which in gbk is a two character sequence: 0xbf5c followed by 0x27. Or in other words, a valid character followed by an unescaped '. But we're not using addslashes(). So on to the next step...
  • mysqlrealescape_string() The C API call to mysql_real_escape_string() differs from addslashes() in that it knows the connection character set. So it can perform the escaping properly for the character set that the server is expecting. However, up to this point, the client thinks that we're still using latin1 for the connection, because we never told it otherwise. We did tell the server we're using gbk, but the client still thinks it's latin1.問題はlatin 1がgbkに移行する過程にある.Therefore the call to mysql_real_escape_string() inserts the backslash, and we have a free hanging ' character in our "escaped"content! In fact, if we were to look at $var in the gbk character set, we'd see:
     ' OR 1=1 /*
  • The Query This part is just a formality, but here's the rendered query:
    SELECT * FROM test WHERE name = ' ' OR 1=1 /*' LIMIT 1

  • 防犯If you:
    Use Modern Versions of MySQL (late 5.1, all 5.5, 5.6, etc) AND mysql_set_charset() / $mysqli->set_charset() / PDO's DSN charset parameter (in PHP ≥ 5.3.6)
    
    OR
    Don't use a vulnerable character set for connection encoding (you only use utf8 / latin1 / ascii / etc)
    
    You're 100%safe.
  • 原文
  • http://stackoverflow.com/questions/5741187/sql-injection-that-gets-around-mysql-real-escape-string/12118602#12118602
    http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string