I wrote on Sat, 15 Mar 2008 15:10:11 +0100:
Matt Comer wrote:
I agree, but with one possible caveat: most RDBMSs allow you to configure
the quoting behavior away from the default if you want. I am not a mysql
expert, but if mysql allows the quote character (default "\" for mysql)
then authmysql should also allow this to be configurable.
Good thought! As a security enhancement, one can set an SQL_MODE of
NO_BACKSLASH_ESCAPES. Thereafter backslash escaping is not possible.
Otherwise, injections can be carried out using sequences crafted so
that after escaping they become valid multibyte characters. See
http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string
I've tried that exploit, and it apparently works on the current version.
I did the following:
echo "MYSQL_CHARACTER_SET 'gbk'" >> authlib/authmysqlrc
authdaemond start
authtest "`printf '[EMAIL PROTECTED] OR 1=1 LIMIT 1 #;'`"
Although authtest failed, the log came out as follows:
Jun 8 14:58:48 authdaemond: received userid lookup request: [EMAIL PROTECTED]'
OR 1=1 LIMIT 1 #;
Jun 8 14:58:48 authdaemond: authmysql: trying this module
Jun 8 14:58:48 authdaemond: Install of a character set for MySQL. SQL query:
SET NAMES 'gbk'
Jun 8 14:58:48 authdaemond: SQL query: SELECT addr, "", passwd, uid, gid, home, "", quota, name,
CONCAT("disableimap=",disableimap,",disablepop3=",disablepop3,",disablewebmail=",disablewebmail,",sharedgroup=",sharedgroup)
FROM user WHERE addr = '[EMAIL PROTECTED]' OR 1=1 LIMIT 1 #;'
Jun 8 14:58:48 authdaemond: mysql_query failed, reconnecting: Illegal mix of
collations (latin1_swedish_ci,IMPLICIT) and (gbk_chinese_ci,COERCIBLE) for
operation '='
Jun 8 14:58:48 authdaemond: zero rows returned
Jun 8 14:58:48 authdaemond: authmysql: REJECT - try next module
Jun 8 14:58:48 authdaemond: FAIL, all modules rejected
The above is enough for me to believe that the injection would have worked
If I had set the table in GBK. After the tentative patch attached, the log
results as follows:
Jun 8 16:09:26 authdaemond: received userid lookup request: [EMAIL PROTECTED]'
OR 1=1 LIMIT 1 #;
Jun 8 16:09:26 authdaemond: authmysql: trying this module
Jun 8 16:09:26 authdaemond: authmysqllib: connected. Versions: header 50032,
client 50032, server 50032
Jun 8 16:09:26 authdaemond: Install of a character set for MySQL: gbk
Jun 8 16:09:26 authdaemond: SQL query: SELECT addr, "", passwd, uid, gid, home, "", quota, name,
CONCAT("disableimap=",disableimap,",disablepop3=",disablepop3,",disablewebmail=",disablewebmail,",sharedgroup=",sharedgroup)
FROM user WHERE addr = '[EMAIL PROTECTED]' OR 1=1 LIMIT 1 #;'
Jun 8 16:09:26 authdaemond: mysql_query failed, reconnecting: Illegal mix of
collations (latin1_swedish_ci,IMPLICIT) and (gbk_chinese_ci,COERCIBLE) for
operation '='
Jun 8 16:09:26 authdaemond: authmysqllib: connected. Versions: header 50032,
client 50032, server 50032
Jun 8 16:09:26 authdaemond: Install of a character set for MySQL: gbk
Jun 8 16:09:26 authdaemond: mysql_query failed second time, giving up: Illegal
mix of collations (latin1_swedish_ci,IMPLICIT) and (gbk_chinese_ci,COERCIBLE)
for operation '='
Jun 8 16:09:26 authdaemond: authmysql: TEMPFAIL - no more modules will be tried
(I found no explanation for the different error reporting logic.)
Apparently, MySQL fixed this injection in Feb 2007. The function used in the
patch
is documented in
http://dev.mysql.com/doc/refman/5.0/en/mysql-set-character-set.html
However, the patch has the same kind of incompatibility as the previous patch I
sent on the same subject. Namely, the current module allows one to configure,
say,
MYSQL_CHARACTER_SET 'latin1' COLLATE 'latin1_german1_ci'
whereas the patched module would only accept an unquoted character set name.
I apologize for not having carried out this test more timely.
--- authmysqllib.original.c 2008-05-17 17:25:13.000000000 +0200
+++ authmysqllib.c 2008-06-08 16:05:24.000000000 +0200
@@ -110,6 +110,39 @@
static MYSQL *mysql=0;
+static void set_session_options(void)
+/*
+* session variables can be set once for the whole session
+*/
+{
+/* Anton Dobkin <[EMAIL PROTECTED]>, VIAN, Ltd. */
+#if MYSQL_VERSION_ID >= 41000
+ const char *character_set=read_env("MYSQL_CHARACTER_SET"), *check;
+
+ if(character_set){
+
+ /*
+ * This function works like the SET NAMES statement, but also sets
+ * the value of mysql->charset, and thus affects the character set
+ * used by mysql_real_escape_string()
+ *
+ * (return value apparently work the opposite of what is documented)
+ */
+ mysql_set_character_set(mysql, character_set);
+ check = mysql_character_set_name(mysql);
+ if (strcmp(character_set, check) != 0)
+ {
+ err("Cannot set MySQL character set \"%s\", working with
\"%s\"\n",
+ character_set, check);
+ }
+ else
+ {
+ DPRINTF("Install of a character set for MySQL: %s",
character_set);
+ }
+ }
+#endif /* 41000 */
+}
+
static int do_connect()
{
const char *server;
@@ -236,6 +269,16 @@
mysql=0;
return (-1);
}
+
+ DPRINTF("authmysqllib: connected. Versions: "
+ "header %lu, "
+ "client %lu, "
+ "server %lu",
+ (long)MYSQL_VERSION_ID,
+ mysql_get_client_version(),
+ mysql_get_server_version(mysql));
+
+ set_session_options();
return (0);
}
@@ -751,45 +794,6 @@
}
}
-/* Anton Dobkin <[EMAIL PROTECTED]>, VIAN, Ltd. */
-#if MYSQL_VERSION_ID >= 41000
- const char *character_set=read_env("MYSQL_CHARACTER_SET");
-
- if(character_set){
-
- char *character_set_buf;
-
- character_set_buf=malloc(strlen(character_set)+11);
-
- if (!character_set_buf)
- {
- perror("malloc");
- free(querybuf);
- return (0);
- }
-
- strcpy(character_set_buf, "SET NAMES ");
- strcat(character_set_buf, character_set);
-
- DPRINTF("Install of a character set for MySQL. SQL query: SET
NAMES %s", character_set);
-
- if(mysql_query (mysql, character_set_buf))
- {
- err("Install of a character set for MySQL is failed: %s
MYSQL_CHARACTER_SET: may be invalid character set", mysql_error(mysql));
- auth_mysql_cleanup();
-
- if (do_connect())
- {
- free(querybuf);
- free(character_set_buf);
- return (0);
- }
- }
-
- free(character_set_buf);
- }
-#endif
-
DPRINTF("SQL query: %s", querybuf);
if (mysql_query (mysql, querybuf))
{
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
courier-users mailing list
[email protected]
Unsubscribe: https://lists.sourceforge.net/lists/listinfo/courier-users