summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Göttsche2023-12-13 20:37:42 +0100
committerJulien Voisin2023-12-13 22:32:49 +0100
commit3c720bec3a78775f37839256cfc4b2fea1348550 (patch)
tree5231fd396c26896cf4b7eb5657fe504c0444b1bb
parentfed8c8f180b275147940b1c6bf8f2c95dfb1ada2 (diff)
print key and value on INI violations
On violations of INI settings include the key and if appropriate the value in the log message. This helps to locate offenders and fine tune the configuration itself.
-rw-r--r--src/php_snuffleupagus.h1
-rw-r--r--src/sp_ini.c60
-rw-r--r--src/tests/ini/ini_min_policy_drop.phpt2
-rw-r--r--src/tests/ini/ini_minmax.phpt4
-rw-r--r--src/tests/ini/ini_null.phpt2
-rw-r--r--src/tests/ini/ini_regexp.phpt2
-rw-r--r--src/tests/ini/ini_regexp_drop.phpt2
-rw-r--r--src/tests/ini/ini_regexp_drop_base64.phpt13
8 files changed, 75 insertions, 11 deletions
diff --git a/src/php_snuffleupagus.h b/src/php_snuffleupagus.h
index 53cf1da..6e035d4 100644
--- a/src/php_snuffleupagus.h
+++ b/src/php_snuffleupagus.h
@@ -17,6 +17,7 @@
17#include <glob.h> 17#include <glob.h>
18#endif 18#endif
19 19
20#include <ctype.h>
20#include <errno.h> 21#include <errno.h>
21#include <fcntl.h> 22#include <fcntl.h>
22#include <inttypes.h> 23#include <inttypes.h>
diff --git a/src/sp_ini.c b/src/sp_ini.c
index 7b22012..8860a92 100644
--- a/src/sp_ini.c
+++ b/src/sp_ini.c
@@ -11,6 +11,29 @@
11 sp_log_auto2("ini_protection", simulation, (cfg->policy_drop || (entry && entry->drop)), __VA_ARGS__); \ 11 sp_log_auto2("ini_protection", simulation, (cfg->policy_drop || (entry && entry->drop)), __VA_ARGS__); \
12 } 12 }
13 13
14static const char* check_safe_key(const char* string) {
15 for (const char* p = string; *p != '\0'; p++) {
16 if (!isalnum((unsigned char)*p) && *p != '_' && *p != '.') {
17 return NULL;
18 }
19 }
20
21 return string;
22}
23
24static const char* check_safe_value(const char* string) {
25 for (const char* p = string; *p != '\0'; p++) {
26 if (*p == '\'' || *p == '"') {
27 return NULL;
28 }
29
30 if (!isgraph((unsigned char)*p)) {
31 return NULL;
32 }
33 }
34
35 return string;
36}
14 37
15static bool /* success */ sp_ini_check(zend_string *const restrict varname, zend_string const *const restrict new_value, sp_ini_entry **sp_entry_p) { 38static bool /* success */ sp_ini_check(zend_string *const restrict varname, zend_string const *const restrict new_value, sp_ini_entry **sp_entry_p) {
16 if (!varname || ZSTR_LEN(varname) == 0) { 39 if (!varname || ZSTR_LEN(varname) == 0) {
@@ -27,7 +50,8 @@ static bool /* success */ sp_ini_check(zend_string *const restrict varname, zend
27 if (!entry) { 50 if (!entry) {
28 if (cfg->policy_readonly) { 51 if (cfg->policy_readonly) {
29 if (!cfg->policy_silent_ro) { 52 if (!cfg->policy_silent_ro) {
30 sp_log_ini_check_violation("INI setting is read-only"); 53 sp_log_ini_check_violation("INI setting `%s` is read-only",
54 check_safe_key(ZSTR_VAL(varname)) ? ZSTR_VAL(varname) : "<invalid>");
31 } 55 }
32 return simulation; 56 return simulation;
33 } 57 }
@@ -38,7 +62,11 @@ static bool /* success */ sp_ini_check(zend_string *const restrict varname, zend
38 62
39 if (SP_INI_ACCESS_READONLY_COND(entry, cfg)) { 63 if (SP_INI_ACCESS_READONLY_COND(entry, cfg)) {
40 if (!cfg->policy_silent_ro) { 64 if (!cfg->policy_silent_ro) {
41 sp_log_ini_check_violation("%s", (entry->msg ? ZSTR_VAL(entry->msg) : "INI setting is read-only")); 65 if (entry->msg) {
66 sp_log_ini_check_violation("%s", ZSTR_VAL(entry->msg));
67 } else {
68 sp_log_ini_check_violation("INI setting `%s` is read-only", ZSTR_VAL(entry->key));
69 }
42 } 70 }
43 return simulation; 71 return simulation;
44 } 72 }
@@ -48,7 +76,7 @@ static bool /* success */ sp_ini_check(zend_string *const restrict varname, zend
48 return true; // allow NULL value and skip other tests 76 return true; // allow NULL value and skip other tests
49 } 77 }
50 if (SP_INI_HAS_CHECKS_COND(entry)) { 78 if (SP_INI_HAS_CHECKS_COND(entry)) {
51 sp_log_ini_check_violation("new INI value must not be NULL or empty"); 79 sp_log_ini_check_violation("new INI value for `%s` must not be NULL or empty", ZSTR_VAL(entry->key));
52 return simulation; 80 return simulation;
53 } 81 }
54 return true; // no new_value, but no checks to perform 82 return true; // no new_value, but no checks to perform
@@ -66,14 +94,36 @@ static bool /* success */ sp_ini_check(zend_string *const restrict varname, zend
66 if ((entry->min && zend_atol(ZSTR_VAL(entry->min), ZSTR_LEN(entry->min)) > lvalue) || 94 if ((entry->min && zend_atol(ZSTR_VAL(entry->min), ZSTR_LEN(entry->min)) > lvalue) ||
67 (entry->max && zend_atol(ZSTR_VAL(entry->max), ZSTR_LEN(entry->max)) < lvalue)) { 95 (entry->max && zend_atol(ZSTR_VAL(entry->max), ZSTR_LEN(entry->max)) < lvalue)) {
68#endif 96#endif
69 sp_log_ini_check_violation("%s", (entry->msg ? ZSTR_VAL(entry->msg) : "INI value out of range")); 97 if (entry->msg) {
98 sp_log_ini_check_violation("%s", ZSTR_VAL(entry->msg));
99 } else {
100 sp_log_ini_check_violation("INI value %lld for `%s` out of range", lvalue, ZSTR_VAL(entry->key));
101 }
70 return simulation; 102 return simulation;
71 } 103 }
72 } 104 }
73 105
74 if (entry->regexp) { 106 if (entry->regexp) {
75 if (!sp_is_regexp_matching_zstr(entry->regexp, new_value)) { 107 if (!sp_is_regexp_matching_zstr(entry->regexp, new_value)) {
76 sp_log_ini_check_violation("%s", (entry->msg ? ZSTR_VAL(entry->msg) : "INI value does not match regex")); 108 if (entry->msg) {
109 sp_log_ini_check_violation("%s", ZSTR_VAL(entry->msg));
110 } else {
111 zend_string *base64_new_val = NULL;
112 const char *safe_new_val = check_safe_value(ZSTR_VAL(new_value));
113 if (!safe_new_val) {
114 base64_new_val = php_base64_encode((const unsigned char*)(ZSTR_VAL(new_value)), ZSTR_LEN(new_value));
115 safe_new_val = base64_new_val ? ZSTR_VAL(base64_new_val) : "<invalid>";
116 }
117
118 sp_log_ini_check_violation("INI value `%s`%s for `%s` does not match regex",
119 safe_new_val,
120 base64_new_val ? "(base64)" : "",
121 ZSTR_VAL(entry->key));
122
123 if (base64_new_val) {
124 zend_string_release(base64_new_val);
125 }
126 }
77 return simulation; 127 return simulation;
78 } 128 }
79 } 129 }
diff --git a/src/tests/ini/ini_min_policy_drop.phpt b/src/tests/ini/ini_min_policy_drop.phpt
index 1ec9f9a..43e180e 100644
--- a/src/tests/ini/ini_min_policy_drop.phpt
+++ b/src/tests/ini/ini_min_policy_drop.phpt
@@ -10,4 +10,4 @@ var_dump(ini_set("max_execution_time", "29") === false);
10var_dump(ini_get("max_execution_time")); 10var_dump(ini_get("max_execution_time"));
11?> 11?>
12--EXPECTF-- 12--EXPECTF--
13Fatal error: [snuffleupagus][0.0.0.0][ini_protection][drop] INI value out of range in %a/ini_min_policy_drop.php on line 2%A 13Fatal error: [snuffleupagus][0.0.0.0][ini_protection][drop] INI value 29 for `max_execution_time` out of range in %a/ini_min_policy_drop.php on line 2%A
diff --git a/src/tests/ini/ini_minmax.phpt b/src/tests/ini/ini_minmax.phpt
index facb73e..10c15a4 100644
--- a/src/tests/ini/ini_minmax.phpt
+++ b/src/tests/ini/ini_minmax.phpt
@@ -25,10 +25,10 @@ string(2) "30"
25bool(false) 25bool(false)
26string(3) "300" 26string(3) "300"
27 27
28Warning: [snuffleupagus][0.0.0.0][ini_protection][log] INI value out of range in %a/ini_minmax.php on line 8 28Warning: [snuffleupagus][0.0.0.0][ini_protection][log] INI value 29 for `max_execution_time` out of range in %a/ini_minmax.php on line 8
29bool(true) 29bool(true)
30string(3) "300" 30string(3) "300"
31 31
32Warning: [snuffleupagus][0.0.0.0][ini_protection][log] INI value out of range in %a/ini_minmax.php on line 11 32Warning: [snuffleupagus][0.0.0.0][ini_protection][log] INI value 301 for `max_execution_time` out of range in %a/ini_minmax.php on line 11
33bool(true) 33bool(true)
34string(3) "300"%A 34string(3) "300"%A
diff --git a/src/tests/ini/ini_null.phpt b/src/tests/ini/ini_null.phpt
index dfc2555..0835222 100644
--- a/src/tests/ini/ini_null.phpt
+++ b/src/tests/ini/ini_null.phpt
@@ -21,6 +21,6 @@ string(15) "foo@example.com"
21bool(false) 21bool(false)
22string(0) "" 22string(0) ""
23 23
24Warning: [snuffleupagus][0.0.0.0][ini_protection][log] new INI value must not be NULL or empty in %a/ini_null.php on line 8 24Warning: [snuffleupagus][0.0.0.0][ini_protection][log] new INI value for `unserialize_callback_func` must not be NULL or empty in %a/ini_null.php on line 8
25bool(true) 25bool(true)
26string(3) "def"%A 26string(3) "def"%A
diff --git a/src/tests/ini/ini_regexp.phpt b/src/tests/ini/ini_regexp.phpt
index c7cab35..3d2156c 100644
--- a/src/tests/ini/ini_regexp.phpt
+++ b/src/tests/ini/ini_regexp.phpt
@@ -15,5 +15,5 @@ var_dump(ini_get("highlight.comment"));
15--EXPECTF-- 15--EXPECTF--
16string(7) "#000aBc" 16string(7) "#000aBc"
17 17
18Warning: [snuffleupagus][0.0.0.0][ini_protection][log] INI value does not match regex in %a/ini_regexp.php on line 5 18Warning: [snuffleupagus][0.0.0.0][ini_protection][log] INI value `xxx` for `highlight.comment` does not match regex in %a/ini_regexp.php on line 5
19string(7) "#000aBc"%A 19string(7) "#000aBc"%A
diff --git a/src/tests/ini/ini_regexp_drop.phpt b/src/tests/ini/ini_regexp_drop.phpt
index 432be8d..134e5c3 100644
--- a/src/tests/ini/ini_regexp_drop.phpt
+++ b/src/tests/ini/ini_regexp_drop.phpt
@@ -10,4 +10,4 @@ var_dump(ini_set("user_agent", "Foo") === false);
10var_dump(ini_get("user_agent")); 10var_dump(ini_get("user_agent"));
11?> 11?>
12--EXPECTF-- 12--EXPECTF--
13Fatal error: [snuffleupagus][0.0.0.0][ini_protection][drop] INI value does not match regex in %a/ini_regexp_drop.php on line 2%A%A%A%A 13Fatal error: [snuffleupagus][0.0.0.0][ini_protection][drop] INI value `Foo` for `user_agent` does not match regex in %a/ini_regexp_drop.php on line 2%A%A%A%A
diff --git a/src/tests/ini/ini_regexp_drop_base64.phpt b/src/tests/ini/ini_regexp_drop_base64.phpt
new file mode 100644
index 0000000..32076d5
--- /dev/null
+++ b/src/tests/ini/ini_regexp_drop_base64.phpt
@@ -0,0 +1,13 @@
1--TEST--
2INI protection .min() + .drop(), log base64
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print("skip"); ?>
5--INI--
6sp.configuration_file={PWD}/config/sp.ini
7--FILE--
8<?php
9var_dump(ini_set("user_agent", "Foo\n\r") === false);
10var_dump(ini_get("user_agent"));
11?>
12--EXPECTF--
13Fatal error: [snuffleupagus][0.0.0.0][ini_protection][drop] INI value `Rm9vCg0=`(base64) for `user_agent` does not match regex in %a/ini_regexp_drop_base64.php on line 2%A%A%A%A