From 93721fdd94f90d48b290749398a26cef277ad129 Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Tue, 24 Jun 2014 16:56:21 +0200 Subject: Added SQL injection protection for Mysqli and several test cases --- tests/sql/connect.inc | 14 ++++++++++++++ tests/sql/mysqli_comment_conditional.phpt | 25 +++++++++++++++++++++++++ tests/sql/mysqli_comment_cstyle_fail.phpt | 25 +++++++++++++++++++++++++ tests/sql/mysqli_comment_hashstyle_fail.phpt | 25 +++++++++++++++++++++++++ tests/sql/mysqli_comment_sqlstyle.phpt | 25 +++++++++++++++++++++++++ tests/sql/mysqli_comment_sqlstyle_fail.phpt | 25 +++++++++++++++++++++++++ tests/sql/mysqli_multiselect.phpt | 25 +++++++++++++++++++++++++ tests/sql/mysqli_multiselect_fail.phpt | 25 +++++++++++++++++++++++++ tests/sql/mysqli_multiselect_subselect.phpt | 25 +++++++++++++++++++++++++ tests/sql/mysqli_no_constraints.phpt | 26 ++++++++++++++++++++++++++ tests/sql/mysqli_open_comment.phpt | 25 +++++++++++++++++++++++++ tests/sql/mysqli_open_comment_fail.phpt | 25 +++++++++++++++++++++++++ tests/sql/mysqli_union.phpt | 26 ++++++++++++++++++++++++++ tests/sql/mysqli_union_fail.phpt | 25 +++++++++++++++++++++++++ tests/sql/skipifmysqli.inc | 5 +++++ 15 files changed, 346 insertions(+) create mode 100644 tests/sql/connect.inc create mode 100644 tests/sql/mysqli_comment_conditional.phpt create mode 100644 tests/sql/mysqli_comment_cstyle_fail.phpt create mode 100644 tests/sql/mysqli_comment_hashstyle_fail.phpt create mode 100644 tests/sql/mysqli_comment_sqlstyle.phpt create mode 100644 tests/sql/mysqli_comment_sqlstyle_fail.phpt create mode 100644 tests/sql/mysqli_multiselect.phpt create mode 100644 tests/sql/mysqli_multiselect_fail.phpt create mode 100644 tests/sql/mysqli_multiselect_subselect.phpt create mode 100644 tests/sql/mysqli_no_constraints.phpt create mode 100644 tests/sql/mysqli_open_comment.phpt create mode 100644 tests/sql/mysqli_open_comment_fail.phpt create mode 100644 tests/sql/mysqli_union.phpt create mode 100644 tests/sql/mysqli_union_fail.phpt create mode 100644 tests/sql/skipifmysqli.inc (limited to 'tests/sql') diff --git a/tests/sql/connect.inc b/tests/sql/connect.inc new file mode 100644 index 0000000..367d63d --- /dev/null +++ b/tests/sql/connect.inc @@ -0,0 +1,14 @@ + \ No newline at end of file diff --git a/tests/sql/mysqli_comment_conditional.phpt b/tests/sql/mysqli_comment_conditional.phpt new file mode 100644 index 0000000..0436c64 --- /dev/null +++ b/tests/sql/mysqli_comment_conditional.phpt @@ -0,0 +1,25 @@ +--TEST-- +Mysqli query with SQL comment protection and MySQL condition (/*!...*/) +--INI-- +extension=mysqli.so +suhosin.sql.bailout_on_error=0 +suhosin.sql.comment=2 +suhosin.sql.opencomment=0 +suhosin.sql.multiselect=0 +suhosin.sql.union=0 +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- +query("SELECT 1 /*! ... */"); +flush(); +echo "mark."; +?> +--EXPECTF-- +mark. \ No newline at end of file diff --git a/tests/sql/mysqli_comment_cstyle_fail.phpt b/tests/sql/mysqli_comment_cstyle_fail.phpt new file mode 100644 index 0000000..56a8ccb --- /dev/null +++ b/tests/sql/mysqli_comment_cstyle_fail.phpt @@ -0,0 +1,25 @@ +--TEST-- +Mysqli query with SQL comment (/*...*/) protection set to fail +--INI-- +extension=mysqli.so +suhosin.sql.bailout_on_error=0 +suhosin.sql.comment=2 +suhosin.sql.opencomment=0 +suhosin.sql.multiselect=0 +suhosin.sql.union=0 +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- +query("SELECT 1 /* injection */"); +flush(); +echo "mark."; +?> +--EXPECTREGEX-- +ALERT - Comment in SQL query.*\) \ No newline at end of file diff --git a/tests/sql/mysqli_comment_hashstyle_fail.phpt b/tests/sql/mysqli_comment_hashstyle_fail.phpt new file mode 100644 index 0000000..6f5b517 --- /dev/null +++ b/tests/sql/mysqli_comment_hashstyle_fail.phpt @@ -0,0 +1,25 @@ +--TEST-- +Mysqli query with SQL comment (#) protection set to fail +--INI-- +extension=mysqli.so +suhosin.sql.bailout_on_error=0 +suhosin.sql.comment=2 +suhosin.sql.opencomment=0 +suhosin.sql.multiselect=0 +suhosin.sql.union=0 +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- +query("SELECT 1 # injection"); +flush(); +echo "mark."; +?> +--EXPECTREGEX-- +ALERT - Comment in SQL query.*\) \ No newline at end of file diff --git a/tests/sql/mysqli_comment_sqlstyle.phpt b/tests/sql/mysqli_comment_sqlstyle.phpt new file mode 100644 index 0000000..c32c76a --- /dev/null +++ b/tests/sql/mysqli_comment_sqlstyle.phpt @@ -0,0 +1,25 @@ +--TEST-- +Mysqli query with SQL comment (--) protection +--INI-- +extension=mysqli.so +suhosin.sql.bailout_on_error=0 +suhosin.sql.comment=1 +suhosin.sql.opencomment=0 +suhosin.sql.multiselect=0 +suhosin.sql.union=0 +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- +query("SELECT 1 -- injection"); +flush(); +echo "mark."; +?> +--EXPECTREGEX-- +ALERT - Comment in SQL query.*mark. \ No newline at end of file diff --git a/tests/sql/mysqli_comment_sqlstyle_fail.phpt b/tests/sql/mysqli_comment_sqlstyle_fail.phpt new file mode 100644 index 0000000..83e63c5 --- /dev/null +++ b/tests/sql/mysqli_comment_sqlstyle_fail.phpt @@ -0,0 +1,25 @@ +--TEST-- +Mysqli query with SQL comment (--) protection set to fail +--INI-- +extension=mysqli.so +suhosin.sql.bailout_on_error=0 +suhosin.sql.comment=2 +suhosin.sql.opencomment=0 +suhosin.sql.multiselect=0 +suhosin.sql.union=0 +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- +query("SELECT 1 -- injection"); +flush(); +echo "mark."; +?> +--EXPECTREGEX-- +ALERT - Comment in SQL query.*\) \ No newline at end of file diff --git a/tests/sql/mysqli_multiselect.phpt b/tests/sql/mysqli_multiselect.phpt new file mode 100644 index 0000000..63d6c19 --- /dev/null +++ b/tests/sql/mysqli_multiselect.phpt @@ -0,0 +1,25 @@ +--TEST-- +Mysqli query with multiple SELECT statements +--INI-- +extension=mysqli.so +suhosin.sql.bailout_on_error=0 +suhosin.sql.comment=0 +suhosin.sql.opencomment=0 +suhosin.sql.multiselect=1 +suhosin.sql.union=0 +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- +query("SELECT 1; SELECT 2"); +flush(); +echo "mark."; +?> +--EXPECTREGEX-- +ALERT - Multiple SELECT in SQL query.*mark. \ No newline at end of file diff --git a/tests/sql/mysqli_multiselect_fail.phpt b/tests/sql/mysqli_multiselect_fail.phpt new file mode 100644 index 0000000..2bee62a --- /dev/null +++ b/tests/sql/mysqli_multiselect_fail.phpt @@ -0,0 +1,25 @@ +--TEST-- +Mysqli query with multiple SELECT statements set to fail +--INI-- +extension=mysqli.so +suhosin.sql.bailout_on_error=0 +suhosin.sql.comment=0 +suhosin.sql.opencomment=0 +suhosin.sql.multiselect=2 +suhosin.sql.union=0 +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- +query("SELECT 1; SELECT 2"); +flush(); +echo "mark."; +?> +--EXPECTREGEX-- +ALERT - Multiple SELECT in SQL query.*\) \ No newline at end of file diff --git a/tests/sql/mysqli_multiselect_subselect.phpt b/tests/sql/mysqli_multiselect_subselect.phpt new file mode 100644 index 0000000..e629720 --- /dev/null +++ b/tests/sql/mysqli_multiselect_subselect.phpt @@ -0,0 +1,25 @@ +--TEST-- +Mysqli query with sub-SELECT +--INI-- +extension=mysqli.so +suhosin.sql.bailout_on_error=0 +suhosin.sql.comment=0 +suhosin.sql.opencomment=0 +suhosin.sql.multiselect=1 +suhosin.sql.union=0 +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- +query("SELECT * FROM (SELECT 1)"); +flush(); +echo "mark."; +?> +--EXPECTREGEX-- +ALERT - Multiple SELECT in SQL query.*mark. \ No newline at end of file diff --git a/tests/sql/mysqli_no_constraints.phpt b/tests/sql/mysqli_no_constraints.phpt new file mode 100644 index 0000000..1d7fff6 --- /dev/null +++ b/tests/sql/mysqli_no_constraints.phpt @@ -0,0 +1,26 @@ +--TEST-- +Mysqli connection test without any constraints +--INI-- +extension=mysqli.so +suhosin.sql.comment=0 +suhosin.sql.bailout_on_error=0 +suhosin.sql.comment=0 +suhosin.sql.opencomment=0 +suhosin.sql.multiselect=0 +suhosin.sql.union=0 +--SKIPIF-- + +--FILE-- +query("SELECT 1 AS A UNION SELECT 2 -- injection"); +$rows = $result->fetch_all(); +if ($rows !== null && count($rows) == 2) { echo "ok"; } + +?> +--EXPECTF-- +ok \ No newline at end of file diff --git a/tests/sql/mysqli_open_comment.phpt b/tests/sql/mysqli_open_comment.phpt new file mode 100644 index 0000000..29d3536 --- /dev/null +++ b/tests/sql/mysqli_open_comment.phpt @@ -0,0 +1,25 @@ +--TEST-- +Mysqli query with SQL open comment protection (/*...) +--INI-- +extension=mysqli.so +suhosin.sql.bailout_on_error=0 +suhosin.sql.comment=0 +suhosin.sql.opencomment=1 +suhosin.sql.multiselect=0 +suhosin.sql.union=0 +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- +query("SELECT 1 /*"); +flush(); +echo "mark."; +?> +--EXPECTREGEX-- +ALERT - Open comment in SQL query.*mark. \ No newline at end of file diff --git a/tests/sql/mysqli_open_comment_fail.phpt b/tests/sql/mysqli_open_comment_fail.phpt new file mode 100644 index 0000000..4645523 --- /dev/null +++ b/tests/sql/mysqli_open_comment_fail.phpt @@ -0,0 +1,25 @@ +--TEST-- +Mysqli query with SQL open comment protection (/*...) set to fail +--INI-- +extension=mysqli.so +suhosin.sql.bailout_on_error=0 +suhosin.sql.comment=0 +suhosin.sql.opencomment=2 +suhosin.sql.multiselect=0 +suhosin.sql.union=0 +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- +query("SELECT 1 /*"); +flush(); +echo "mark."; +?> +--EXPECTREGEX-- +ALERT - Open comment in SQL query.*\) \ No newline at end of file diff --git a/tests/sql/mysqli_union.phpt b/tests/sql/mysqli_union.phpt new file mode 100644 index 0000000..9af9c61 --- /dev/null +++ b/tests/sql/mysqli_union.phpt @@ -0,0 +1,26 @@ +--TEST-- +Mysqli query with UNION protection +--INI-- +extension=mysqli.so +suhosin.sql.bailout_on_error=0 +suhosin.sql.comment=0 +suhosin.sql.opencomment=0 +suhosin.sql.multiselect=0 +suhosin.sql.union=1 +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- +query("SELECT 1 UNION SELECT 2"); +flush(); +echo "mark."; + +?> +--EXPECTREGEX-- +ALERT - UNION in SQL query.*mark. \ No newline at end of file diff --git a/tests/sql/mysqli_union_fail.phpt b/tests/sql/mysqli_union_fail.phpt new file mode 100644 index 0000000..ee51a79 --- /dev/null +++ b/tests/sql/mysqli_union_fail.phpt @@ -0,0 +1,25 @@ +--TEST-- +Mysqli query with UNION protection set to fail +--INI-- +extension=mysqli.so +suhosin.sql.bailout_on_error=0 +suhosin.sql.comment=0 +suhosin.sql.opencomment=0 +suhosin.sql.multiselect=0 +suhosin.sql.union=2 +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- +query("SELECT 1 UNION SELECT 2"); +echo "mark."; + +?> +--EXPECTREGEX-- +ALERT - UNION in SQL query.*\) \ No newline at end of file diff --git a/tests/sql/skipifmysqli.inc b/tests/sql/skipifmysqli.inc new file mode 100644 index 0000000..ee16cf1 --- /dev/null +++ b/tests/sql/skipifmysqli.inc @@ -0,0 +1,5 @@ + \ No newline at end of file -- cgit v1.3 From 63de1053dfda1faca22a84afb82d6b1315b8db6e Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Wed, 9 Jul 2014 12:47:03 +0200 Subject: added sql.user_match + username character check --- Changelog | 4 ++- execute.c | 51 ++++++++++++++++++++++++---------- php_suhosin.h | 45 +++++++++++++++--------------- suhosin.c | 15 +++++----- tests/sql/mysqli_user_match_error.phpt | 18 ++++++++++++ tests/sql/mysqli_user_match_ok.phpt | 18 ++++++++++++ 6 files changed, 106 insertions(+), 45 deletions(-) create mode 100644 tests/sql/mysqli_user_match_error.phpt create mode 100644 tests/sql/mysqli_user_match_ok.phpt (limited to 'tests/sql') diff --git a/Changelog b/Changelog index 4e83cb3..ad2438f 100644 --- a/Changelog +++ b/Changelog @@ -1,6 +1,8 @@ 2014-06-24 - 0.9.37-dev - - Added SQL injection protection for Mysqli and several test cases + - Added SQL injection protection for Mysqli and several test cases + - Added wildcard matching for SQL username + - Added check for SQL username to only contain valid characters (>= ASCII 32) 2014-06-10 - 0.9.36 diff --git a/execute.c b/execute.c index 098b074..2f280b7 100644 --- a/execute.c +++ b/execute.c @@ -24,6 +24,7 @@ #endif #include +#include #include "php.h" #include "php_ini.h" #include "zend_hash.h" @@ -1024,17 +1025,20 @@ int ih_fixusername(IH_HANDLER_PARAMS) void **p = EG(argument_stack).top_element-2; #endif unsigned long arg_count; - zval **arg;char *prefix, *postfix, *user; + zval **arg; + char *prefix, *postfix, *user, *user_match, *cp; zval *backup, *my_user; int prefix_len, postfix_len, len; - SDEBUG("function: %s", ih->name); + SDEBUG("function (fixusername): %s", ih->name); prefix = SUHOSIN_G(sql_user_prefix); postfix = SUHOSIN_G(sql_user_postfix); + user_match = SUHOSIN_G(sql_user_match); - if ((prefix == NULL || prefix[0] == 0)&& - (postfix == NULL || postfix[0] == 0)) { + if ((prefix == NULL || prefix[0] == 0) && + (postfix == NULL || postfix[0] == 0) && + (user_match == NULL || user_match[0] == 0)) { return (0); } @@ -1065,23 +1069,40 @@ int ih_fixusername(IH_HANDLER_PARAMS) user = Z_STRVAL_P(backup); } - if (prefix_len && prefix_len <= len) { - if (strncmp(prefix, user, prefix_len)==0) { - prefix = ""; - len -= prefix_len; - } - } - - if (postfix_len && postfix_len <= len) { - if (strncmp(postfix, user+len-postfix_len, postfix_len)==0) { - postfix = ""; + cp = user; + while (cp < user+len) { + if (*cp < 32) { + suhosin_log(S_SQL, "SQL username contains invalid characters"); + if (!SUHOSIN_G(simulation)) { + suhosin_bailout(TSRMLS_C); + } } + cp++; } - + MAKE_STD_ZVAL(my_user); my_user->type = IS_STRING; my_user->value.str.len = spprintf(&my_user->value.str.val, 0, "%s%s%s", prefix, user, postfix); + if (user_match && user_match[0]) { + len = Z_STRLEN_P(my_user); + user = Z_STRVAL_P(my_user); +#ifdef HAVE_FNMATCH + if (fnmatch(user_match, user, 0) != 0) { + suhosin_log(S_SQL, "SQL username ('%s') does not match suhosin.sql.user_match ('%s')", user, user_match); + if (!SUHOSIN_G(simulation)) { + suhosin_bailout(TSRMLS_C); + } + } +#else +#warning no support for fnmatch() - setting suhosin.sql.user_match will always fail. + suhosin_log(S_SQL, "suhosin.sql.user_match specified, but system does not support fnmatch()"); + if (!SUHOSIN_G(simulation)) { + suhosin_bailout(TSRMLS_C); + } +#endif + } + /* XXX: memory_leak? */ *arg = my_user; diff --git a/php_suhosin.h b/php_suhosin.h index e5604a7..e85fc38 100644 --- a/php_suhosin.h +++ b/php_suhosin.h @@ -76,15 +76,16 @@ ZEND_BEGIN_MODULE_GLOBALS(suhosin) char *filter_action; char *sql_user_prefix; char *sql_user_postfix; - long sql_comment; - long sql_opencomment; - long sql_union; - long sql_mselect; + char *sql_user_match; + long sql_comment; + long sql_opencomment; + long sql_union; + long sql_mselect; long max_execution_depth; zend_bool abort_request; long executor_include_max_traversal; - zend_bool executor_include_allow_writable_files; + zend_bool executor_include_allow_writable_files; HashTable *include_whitelist; @@ -152,11 +153,11 @@ ZEND_BEGIN_MODULE_GLOBALS(suhosin) zend_bool upload_remove_binary; char *upload_verification_script; - zend_bool no_more_variables; - zend_bool no_more_get_variables; - zend_bool no_more_post_variables; - zend_bool no_more_cookie_variables; - zend_bool no_more_uploads; + zend_bool no_more_variables; + zend_bool no_more_get_variables; + zend_bool no_more_post_variables; + zend_bool no_more_cookie_variables; + zend_bool no_more_uploads; @@ -198,8 +199,8 @@ ZEND_BEGIN_MODULE_GLOBALS(suhosin) int (*old_s_destroy)(void **mod_data, const char *key TSRMLS_DC); BYTE fi[24],ri[24]; - WORD fkey[120]; - WORD rkey[120]; + WORD fkey[120]; + WORD rkey[120]; zend_bool session_encrypt; char* session_cryptkey; @@ -247,16 +248,16 @@ ZEND_BEGIN_MODULE_GLOBALS(suhosin) zend_bool mt_is_seeded; /* PERDIR Handling */ - char *perdir; - zend_bool log_perdir; - zend_bool exec_perdir; - zend_bool get_perdir; - zend_bool post_perdir; - zend_bool cookie_perdir; - zend_bool request_perdir; - zend_bool upload_perdir; - zend_bool sql_perdir; - zend_bool misc_perdir; + char *perdir; + zend_bool log_perdir; + zend_bool exec_perdir; + zend_bool get_perdir; + zend_bool post_perdir; + zend_bool cookie_perdir; + zend_bool request_perdir; + zend_bool upload_perdir; + zend_bool sql_perdir; + zend_bool misc_perdir; ZEND_END_MODULE_GLOBALS(suhosin) diff --git a/suhosin.c b/suhosin.c index 0d1eba0..469e88f 100644 --- a/suhosin.c +++ b/suhosin.c @@ -989,13 +989,14 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("suhosin.upload.verification_script", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadString, upload_verification_script, zend_suhosin_globals, suhosin_globals) - STD_ZEND_INI_BOOLEAN("suhosin.sql.bailout_on_error", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateSQLBool, sql_bailout_on_error, zend_suhosin_globals, suhosin_globals) - STD_PHP_INI_ENTRY("suhosin.sql.user_prefix", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLString, sql_user_prefix, zend_suhosin_globals, suhosin_globals) - STD_PHP_INI_ENTRY("suhosin.sql.user_postfix", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLString, sql_user_postfix, zend_suhosin_globals, suhosin_globals) - STD_PHP_INI_ENTRY("suhosin.sql.comment", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_comment, zend_suhosin_globals, suhosin_globals) - STD_PHP_INI_ENTRY("suhosin.sql.opencomment", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_opencomment, zend_suhosin_globals, suhosin_globals) - STD_PHP_INI_ENTRY("suhosin.sql.multiselect", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_mselect, zend_suhosin_globals, suhosin_globals) - STD_PHP_INI_ENTRY("suhosin.sql.union", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_union, zend_suhosin_globals, suhosin_globals) + STD_ZEND_INI_BOOLEAN("suhosin.sql.bailout_on_error", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateSQLBool, sql_bailout_on_error, zend_suhosin_globals, suhosin_globals) + STD_PHP_INI_ENTRY("suhosin.sql.user_prefix", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLString, sql_user_prefix, zend_suhosin_globals, suhosin_globals) + STD_PHP_INI_ENTRY("suhosin.sql.user_postfix", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLString, sql_user_postfix, zend_suhosin_globals, suhosin_globals) + STD_PHP_INI_ENTRY("suhosin.sql.user_match", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLString, sql_user_match, zend_suhosin_globals, suhosin_globals) + STD_PHP_INI_ENTRY("suhosin.sql.comment", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_comment, zend_suhosin_globals, suhosin_globals) + STD_PHP_INI_ENTRY("suhosin.sql.opencomment", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_opencomment, zend_suhosin_globals, suhosin_globals) + STD_PHP_INI_ENTRY("suhosin.sql.multiselect", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_mselect, zend_suhosin_globals, suhosin_globals) + STD_PHP_INI_ENTRY("suhosin.sql.union", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_union, zend_suhosin_globals, suhosin_globals) STD_ZEND_INI_BOOLEAN("suhosin.session.encrypt", "1", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, session_encrypt, zend_suhosin_globals, suhosin_globals) STD_PHP_INI_ENTRY("suhosin.session.cryptkey", "", PHP_INI_ALL, OnUpdateString, session_cryptkey, zend_suhosin_globals, suhosin_globals) diff --git a/tests/sql/mysqli_user_match_error.phpt b/tests/sql/mysqli_user_match_error.phpt new file mode 100644 index 0000000..69db081 --- /dev/null +++ b/tests/sql/mysqli_user_match_error.phpt @@ -0,0 +1,18 @@ +--TEST-- +Mysqli connect with user_match not matching username +--INI-- +extension=mysqli.so +suhosin.sql.user_match=complicated_userprefix* +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- + +--EXPECTREGEX-- +ALERT - SQL username .* does not match.* \ No newline at end of file diff --git a/tests/sql/mysqli_user_match_ok.phpt b/tests/sql/mysqli_user_match_ok.phpt new file mode 100644 index 0000000..4d7a438 --- /dev/null +++ b/tests/sql/mysqli_user_match_ok.phpt @@ -0,0 +1,18 @@ +--TEST-- +Mysqli connect with user_match not matching username +--INI-- +extension=mysqli.so +suhosin.sql.user_match=invalid_* +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- + +--EXPECTREGEX-- +.*Access denied for user 'invalid_username'.* \ No newline at end of file -- cgit v1.3 From 84996270798fccffe2da890ad7a7c270d298a6e8 Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Wed, 9 Jul 2014 13:55:58 +0200 Subject: enforce SQL username check + return FALSE instead of bailout --- execute.c | 51 +++++++++++++------------- tests/sql/mysqli_connect_invalid_username.phpt | 17 +++++++++ tests/sql/mysqli_user_match_ok.phpt | 2 +- 3 files changed, 43 insertions(+), 27 deletions(-) create mode 100644 tests/sql/mysqli_connect_invalid_username.phpt (limited to 'tests/sql') diff --git a/execute.c b/execute.c index 2f280b7..913a82b 100644 --- a/execute.c +++ b/execute.c @@ -1036,22 +1036,6 @@ int ih_fixusername(IH_HANDLER_PARAMS) postfix = SUHOSIN_G(sql_user_postfix); user_match = SUHOSIN_G(sql_user_match); - if ((prefix == NULL || prefix[0] == 0) && - (postfix == NULL || postfix[0] == 0) && - (user_match == NULL || user_match[0] == 0)) { - return (0); - } - - if (prefix == NULL) { - prefix = ""; - } - if (postfix == NULL) { - postfix = ""; - } - - prefix_len = strlen(prefix); - postfix_len = strlen(postfix); - arg_count = (unsigned long) *p; if (ht < (long) ih->arg1) { @@ -1074,38 +1058,53 @@ int ih_fixusername(IH_HANDLER_PARAMS) if (*cp < 32) { suhosin_log(S_SQL, "SQL username contains invalid characters"); if (!SUHOSIN_G(simulation)) { - suhosin_bailout(TSRMLS_C); + RETVAL_FALSE; + return (1); } } cp++; } - MAKE_STD_ZVAL(my_user); - my_user->type = IS_STRING; - my_user->value.str.len = spprintf(&my_user->value.str.val, 0, "%s%s%s", prefix, user, postfix); + if ((prefix != NULL && prefix[0]) || (postfix != NULL && postfix[0])) { + if (prefix == NULL) { + prefix = ""; + } + if (postfix == NULL) { + postfix = ""; + } + prefix_len = strlen(prefix); + postfix_len = strlen(postfix); + + MAKE_STD_ZVAL(my_user); + my_user->type = IS_STRING; + my_user->value.str.len = spprintf(&my_user->value.str.val, 0, "%s%s%s", prefix, user, postfix); - if (user_match && user_match[0]) { + /* XXX: memory_leak? */ + *arg = my_user; + len = Z_STRLEN_P(my_user); user = Z_STRVAL_P(my_user); + } + + if (user_match && user_match[0]) { #ifdef HAVE_FNMATCH if (fnmatch(user_match, user, 0) != 0) { suhosin_log(S_SQL, "SQL username ('%s') does not match suhosin.sql.user_match ('%s')", user, user_match); if (!SUHOSIN_G(simulation)) { - suhosin_bailout(TSRMLS_C); + RETVAL_FALSE; + return (1); } } #else #warning no support for fnmatch() - setting suhosin.sql.user_match will always fail. suhosin_log(S_SQL, "suhosin.sql.user_match specified, but system does not support fnmatch()"); if (!SUHOSIN_G(simulation)) { - suhosin_bailout(TSRMLS_C); + RETVAL_FALSE; + return (1); } #endif } - /* XXX: memory_leak? */ - *arg = my_user; - SDEBUG("function: %s - user: %s", ih->name, user); return (0); diff --git a/tests/sql/mysqli_connect_invalid_username.phpt b/tests/sql/mysqli_connect_invalid_username.phpt new file mode 100644 index 0000000..532254f --- /dev/null +++ b/tests/sql/mysqli_connect_invalid_username.phpt @@ -0,0 +1,17 @@ +--TEST-- +Mysqli connect with user_match not matching username +--INI-- +extension=mysqli.so +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- + +--EXPECTREGEX-- +ALERT - SQL username contains invalid characters.* \ No newline at end of file diff --git a/tests/sql/mysqli_user_match_ok.phpt b/tests/sql/mysqli_user_match_ok.phpt index 4d7a438..a2ad832 100644 --- a/tests/sql/mysqli_user_match_ok.phpt +++ b/tests/sql/mysqli_user_match_ok.phpt @@ -1,5 +1,5 @@ --TEST-- -Mysqli connect with user_match not matching username +Mysqli connect with user_match matching username --INI-- extension=mysqli.so suhosin.sql.user_match=invalid_* -- cgit v1.3 From 1f52bf0e933fdc0cdb2c7990f2684ad96f5056fc Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Wed, 9 Jul 2014 15:23:19 +0200 Subject: test cases for user_prefix + user_postfix --- tests/sql/mysqli_user_postfix.phpt | 18 ++++++++++++++++++ tests/sql/mysqli_user_prefix.phpt | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/sql/mysqli_user_postfix.phpt create mode 100644 tests/sql/mysqli_user_prefix.phpt (limited to 'tests/sql') diff --git a/tests/sql/mysqli_user_postfix.phpt b/tests/sql/mysqli_user_postfix.phpt new file mode 100644 index 0000000..11e3fe6 --- /dev/null +++ b/tests/sql/mysqli_user_postfix.phpt @@ -0,0 +1,18 @@ +--TEST-- +Mysqli connect with user_postfix +--INI-- +extension=mysqli.so +suhosin.sql.user_postfix=_post +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- + +--EXPECTREGEX-- +.*Access denied for user 'invalid_username_post'.* \ No newline at end of file diff --git a/tests/sql/mysqli_user_prefix.phpt b/tests/sql/mysqli_user_prefix.phpt new file mode 100644 index 0000000..bb229f0 --- /dev/null +++ b/tests/sql/mysqli_user_prefix.phpt @@ -0,0 +1,18 @@ +--TEST-- +Mysqli connect with user_prefix +--INI-- +extension=mysqli.so +suhosin.sql.user_prefix=pre_ +suhosin.log.stdout=32 +--SKIPIF-- + +--FILE-- + +--EXPECTREGEX-- +.*Access denied for user 'pre_invalid_username'.* \ No newline at end of file -- cgit v1.3