summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog4
-rw-r--r--execute.c51
-rw-r--r--php_suhosin.h45
-rw-r--r--suhosin.c15
-rw-r--r--tests/sql/mysqli_user_match_error.phpt18
-rw-r--r--tests/sql/mysqli_user_match_ok.phpt18
6 files changed, 106 insertions, 45 deletions
diff --git a/Changelog b/Changelog
index 4e83cb3..ad2438f 100644
--- a/Changelog
+++ b/Changelog
@@ -1,6 +1,8 @@
12014-06-24 - 0.9.37-dev 12014-06-24 - 0.9.37-dev
2 2
3 - Added SQL injection protection for Mysqli and several test cases 3 - Added SQL injection protection for Mysqli and several test cases
4 - Added wildcard matching for SQL username
5 - Added check for SQL username to only contain valid characters (>= ASCII 32)
4 6
52014-06-10 - 0.9.36 72014-06-10 - 0.9.36
6 8
diff --git a/execute.c b/execute.c
index 098b074..2f280b7 100644
--- a/execute.c
+++ b/execute.c
@@ -24,6 +24,7 @@
24#endif 24#endif
25 25
26#include <fcntl.h> 26#include <fcntl.h>
27#include <fnmatch.h>
27#include "php.h" 28#include "php.h"
28#include "php_ini.h" 29#include "php_ini.h"
29#include "zend_hash.h" 30#include "zend_hash.h"
@@ -1024,17 +1025,20 @@ int ih_fixusername(IH_HANDLER_PARAMS)
1024 void **p = EG(argument_stack).top_element-2; 1025 void **p = EG(argument_stack).top_element-2;
1025#endif 1026#endif
1026 unsigned long arg_count; 1027 unsigned long arg_count;
1027 zval **arg;char *prefix, *postfix, *user; 1028 zval **arg;
1029 char *prefix, *postfix, *user, *user_match, *cp;
1028 zval *backup, *my_user; 1030 zval *backup, *my_user;
1029 int prefix_len, postfix_len, len; 1031 int prefix_len, postfix_len, len;
1030 1032
1031 SDEBUG("function: %s", ih->name); 1033 SDEBUG("function (fixusername): %s", ih->name);
1032 1034
1033 prefix = SUHOSIN_G(sql_user_prefix); 1035 prefix = SUHOSIN_G(sql_user_prefix);
1034 postfix = SUHOSIN_G(sql_user_postfix); 1036 postfix = SUHOSIN_G(sql_user_postfix);
1037 user_match = SUHOSIN_G(sql_user_match);
1035 1038
1036 if ((prefix == NULL || prefix[0] == 0)&& 1039 if ((prefix == NULL || prefix[0] == 0) &&
1037 (postfix == NULL || postfix[0] == 0)) { 1040 (postfix == NULL || postfix[0] == 0) &&
1041 (user_match == NULL || user_match[0] == 0)) {
1038 return (0); 1042 return (0);
1039 } 1043 }
1040 1044
@@ -1065,23 +1069,40 @@ int ih_fixusername(IH_HANDLER_PARAMS)
1065 user = Z_STRVAL_P(backup); 1069 user = Z_STRVAL_P(backup);
1066 } 1070 }
1067 1071
1068 if (prefix_len && prefix_len <= len) { 1072 cp = user;
1069 if (strncmp(prefix, user, prefix_len)==0) { 1073 while (cp < user+len) {
1070 prefix = ""; 1074 if (*cp < 32) {
1071 len -= prefix_len; 1075 suhosin_log(S_SQL, "SQL username contains invalid characters");
1072 } 1076 if (!SUHOSIN_G(simulation)) {
1073 } 1077 suhosin_bailout(TSRMLS_C);
1074 1078 }
1075 if (postfix_len && postfix_len <= len) {
1076 if (strncmp(postfix, user+len-postfix_len, postfix_len)==0) {
1077 postfix = "";
1078 } 1079 }
1080 cp++;
1079 } 1081 }
1080 1082
1081 MAKE_STD_ZVAL(my_user); 1083 MAKE_STD_ZVAL(my_user);
1082 my_user->type = IS_STRING; 1084 my_user->type = IS_STRING;
1083 my_user->value.str.len = spprintf(&my_user->value.str.val, 0, "%s%s%s", prefix, user, postfix); 1085 my_user->value.str.len = spprintf(&my_user->value.str.val, 0, "%s%s%s", prefix, user, postfix);
1084 1086
1087 if (user_match && user_match[0]) {
1088 len = Z_STRLEN_P(my_user);
1089 user = Z_STRVAL_P(my_user);
1090#ifdef HAVE_FNMATCH
1091 if (fnmatch(user_match, user, 0) != 0) {
1092 suhosin_log(S_SQL, "SQL username ('%s') does not match suhosin.sql.user_match ('%s')", user, user_match);
1093 if (!SUHOSIN_G(simulation)) {
1094 suhosin_bailout(TSRMLS_C);
1095 }
1096 }
1097#else
1098#warning no support for fnmatch() - setting suhosin.sql.user_match will always fail.
1099 suhosin_log(S_SQL, "suhosin.sql.user_match specified, but system does not support fnmatch()");
1100 if (!SUHOSIN_G(simulation)) {
1101 suhosin_bailout(TSRMLS_C);
1102 }
1103#endif
1104 }
1105
1085 /* XXX: memory_leak? */ 1106 /* XXX: memory_leak? */
1086 *arg = my_user; 1107 *arg = my_user;
1087 1108
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)
76 char *filter_action; 76 char *filter_action;
77 char *sql_user_prefix; 77 char *sql_user_prefix;
78 char *sql_user_postfix; 78 char *sql_user_postfix;
79 long sql_comment; 79 char *sql_user_match;
80 long sql_opencomment; 80 long sql_comment;
81 long sql_union; 81 long sql_opencomment;
82 long sql_mselect; 82 long sql_union;
83 long sql_mselect;
83 84
84 long max_execution_depth; 85 long max_execution_depth;
85 zend_bool abort_request; 86 zend_bool abort_request;
86 long executor_include_max_traversal; 87 long executor_include_max_traversal;
87 zend_bool executor_include_allow_writable_files; 88 zend_bool executor_include_allow_writable_files;
88 89
89 90
90 HashTable *include_whitelist; 91 HashTable *include_whitelist;
@@ -152,11 +153,11 @@ ZEND_BEGIN_MODULE_GLOBALS(suhosin)
152 zend_bool upload_remove_binary; 153 zend_bool upload_remove_binary;
153 char *upload_verification_script; 154 char *upload_verification_script;
154 155
155 zend_bool no_more_variables; 156 zend_bool no_more_variables;
156 zend_bool no_more_get_variables; 157 zend_bool no_more_get_variables;
157 zend_bool no_more_post_variables; 158 zend_bool no_more_post_variables;
158 zend_bool no_more_cookie_variables; 159 zend_bool no_more_cookie_variables;
159 zend_bool no_more_uploads; 160 zend_bool no_more_uploads;
160 161
161 162
162 163
@@ -198,8 +199,8 @@ ZEND_BEGIN_MODULE_GLOBALS(suhosin)
198 int (*old_s_destroy)(void **mod_data, const char *key TSRMLS_DC); 199 int (*old_s_destroy)(void **mod_data, const char *key TSRMLS_DC);
199 200
200 BYTE fi[24],ri[24]; 201 BYTE fi[24],ri[24];
201 WORD fkey[120]; 202 WORD fkey[120];
202 WORD rkey[120]; 203 WORD rkey[120];
203 204
204 zend_bool session_encrypt; 205 zend_bool session_encrypt;
205 char* session_cryptkey; 206 char* session_cryptkey;
@@ -247,16 +248,16 @@ ZEND_BEGIN_MODULE_GLOBALS(suhosin)
247 zend_bool mt_is_seeded; 248 zend_bool mt_is_seeded;
248 249
249 /* PERDIR Handling */ 250 /* PERDIR Handling */
250 char *perdir; 251 char *perdir;
251 zend_bool log_perdir; 252 zend_bool log_perdir;
252 zend_bool exec_perdir; 253 zend_bool exec_perdir;
253 zend_bool get_perdir; 254 zend_bool get_perdir;
254 zend_bool post_perdir; 255 zend_bool post_perdir;
255 zend_bool cookie_perdir; 256 zend_bool cookie_perdir;
256 zend_bool request_perdir; 257 zend_bool request_perdir;
257 zend_bool upload_perdir; 258 zend_bool upload_perdir;
258 zend_bool sql_perdir; 259 zend_bool sql_perdir;
259 zend_bool misc_perdir; 260 zend_bool misc_perdir;
260 261
261ZEND_END_MODULE_GLOBALS(suhosin) 262ZEND_END_MODULE_GLOBALS(suhosin)
262 263
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()
989 STD_PHP_INI_ENTRY("suhosin.upload.verification_script", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadString, upload_verification_script, zend_suhosin_globals, suhosin_globals) 989 STD_PHP_INI_ENTRY("suhosin.upload.verification_script", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadString, upload_verification_script, zend_suhosin_globals, suhosin_globals)
990 990
991 991
992 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) 992 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)
993 STD_PHP_INI_ENTRY("suhosin.sql.user_prefix", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLString, sql_user_prefix, zend_suhosin_globals, suhosin_globals) 993 STD_PHP_INI_ENTRY("suhosin.sql.user_prefix", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLString, sql_user_prefix, zend_suhosin_globals, suhosin_globals)
994 STD_PHP_INI_ENTRY("suhosin.sql.user_postfix", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLString, sql_user_postfix, zend_suhosin_globals, suhosin_globals) 994 STD_PHP_INI_ENTRY("suhosin.sql.user_postfix", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLString, sql_user_postfix, zend_suhosin_globals, suhosin_globals)
995 STD_PHP_INI_ENTRY("suhosin.sql.comment", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_comment, zend_suhosin_globals, suhosin_globals) 995 STD_PHP_INI_ENTRY("suhosin.sql.user_match", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLString, sql_user_match, zend_suhosin_globals, suhosin_globals)
996 STD_PHP_INI_ENTRY("suhosin.sql.opencomment", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_opencomment, zend_suhosin_globals, suhosin_globals) 996 STD_PHP_INI_ENTRY("suhosin.sql.comment", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_comment, zend_suhosin_globals, suhosin_globals)
997 STD_PHP_INI_ENTRY("suhosin.sql.multiselect", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_mselect, zend_suhosin_globals, suhosin_globals) 997 STD_PHP_INI_ENTRY("suhosin.sql.opencomment", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_opencomment, zend_suhosin_globals, suhosin_globals)
998 STD_PHP_INI_ENTRY("suhosin.sql.union", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_union, zend_suhosin_globals, suhosin_globals) 998 STD_PHP_INI_ENTRY("suhosin.sql.multiselect", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_mselect, zend_suhosin_globals, suhosin_globals)
999 STD_PHP_INI_ENTRY("suhosin.sql.union", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_union, zend_suhosin_globals, suhosin_globals)
999 1000
1000 STD_ZEND_INI_BOOLEAN("suhosin.session.encrypt", "1", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, session_encrypt, zend_suhosin_globals, suhosin_globals) 1001 STD_ZEND_INI_BOOLEAN("suhosin.session.encrypt", "1", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, session_encrypt, zend_suhosin_globals, suhosin_globals)
1001 STD_PHP_INI_ENTRY("suhosin.session.cryptkey", "", PHP_INI_ALL, OnUpdateString, session_cryptkey, zend_suhosin_globals, suhosin_globals) 1002 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 @@
1--TEST--
2Mysqli connect with user_match not matching username
3--INI--
4extension=mysqli.so
5suhosin.sql.user_match=complicated_userprefix*
6suhosin.log.stdout=32
7--SKIPIF--
8<?php
9include('skipifmysqli.inc');
10include('skipif.inc');
11?>
12--FILE--
13<?php
14include('connect.inc');
15$mysqli = new mysqli($host, 'invalid_username', $passwd, $db, $port, $socket);
16?>
17--EXPECTREGEX--
18ALERT - 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 @@
1--TEST--
2Mysqli connect with user_match not matching username
3--INI--
4extension=mysqli.so
5suhosin.sql.user_match=invalid_*
6suhosin.log.stdout=32
7--SKIPIF--
8<?php
9include('skipifmysqli.inc');
10include('skipif.inc');
11?>
12--FILE--
13<?php
14include('connect.inc');
15$mysqli = new mysqli($host, 'invalid_username', $passwd, $db, $port, $socket);
16?>
17--EXPECTREGEX--
18.*Access denied for user 'invalid_username'.* \ No newline at end of file