summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjvoisin2018-07-09 07:37:58 +0000
committerxXx-caillou-xXx2018-07-09 09:37:58 +0200
commit5da3a92492bf169e62367d954cfa7432bee51fed (patch)
tree2e094ed1a5a8400269c48c520539b7dac28ced27
parentca3be84076521c4bb053511775c94c0b195aeac8 (diff)
Trying to fix sloppy comparison (#186)
* Trying to fix sloppy comparison https://github.com/nbs-system/snuffleupagus/issues/10 by modifying php's opcode
-rw-r--r--doc/source/config.rst13
-rw-r--r--src/config.m42
-rw-r--r--src/php_snuffleupagus.h1
-rw-r--r--src/snuffleupagus.c5
-rw-r--r--src/sp_config.c1
-rw-r--r--src/sp_config.h4
-rw-r--r--src/sp_config_keywords.c5
-rw-r--r--src/sp_config_keywords.h1
-rw-r--r--src/sp_execute.c1
-rw-r--r--src/sp_sloppy.c39
-rw-r--r--src/sp_sloppy.h8
-rw-r--r--src/tests/config/sloppy_comparison.ini1
-rw-r--r--src/tests/sloppy_comparison.phpt30
-rw-r--r--src/tests/sloppy_comparison_disable.phpt14
14 files changed, 124 insertions, 1 deletions
diff --git a/doc/source/config.rst b/doc/source/config.rst
index b5bcad4..0186b4a 100644
--- a/doc/source/config.rst
+++ b/doc/source/config.rst
@@ -106,6 +106,19 @@ It can either be ``enabled`` or ``disabled``.
106 106
107.. _config_global: 107.. _config_global:
108 108
109Prevent sloppy comparison
110^^^^^^^^^^^^^^^^
111
112sloppy_comparison, disabled by default, will prevent php `type
113juggling <https://secure.php.net/manual/en/language.types.type-juggling.php>`_ (``==``) , preventing any bypass of a comparison.
114
115It can either be ``enabled`` or ``disabled``.
116
117::
118
119 sp.sloppy_comparison.enable();
120 sp.sloppy_comparison.disable();
121
109unserialize_hmac 122unserialize_hmac
110^^^^^^^^^^^^^^^^ 123^^^^^^^^^^^^^^^^
111 124
diff --git a/src/config.m4 b/src/config.m4
index a4fea4d..0165f87 100644
--- a/src/config.m4
+++ b/src/config.m4
@@ -6,7 +6,7 @@ sources="$sources sp_unserialize.c sp_utils.c sp_disable_xxe.c sp_list.c"
6sources="$sources sp_disabled_functions.c sp_execute.c sp_upload_validation.c" 6sources="$sources sp_disabled_functions.c sp_execute.c sp_upload_validation.c"
7sources="$sources sp_cookie_encryption.c sp_network_utils.c tweetnacl.c" 7sources="$sources sp_cookie_encryption.c sp_network_utils.c tweetnacl.c"
8sources="$sources sp_config_keywords.c sp_var_parser.c sp_var_value.c sp_tree.c" 8sources="$sources sp_config_keywords.c sp_var_parser.c sp_var_value.c sp_tree.c"
9sources="$sources sp_pcre_compat.c sp_crypt.c sp_session.c" 9sources="$sources sp_pcre_compat.c sp_crypt.c sp_session.c sp_sloppy.c"
10 10
11PHP_ARG_ENABLE(snuffleupagus, whether to enable snuffleupagus support, 11PHP_ARG_ENABLE(snuffleupagus, whether to enable snuffleupagus support,
12[ --enable-snuffleupagus Enable snuffleupagus support]) 12[ --enable-snuffleupagus Enable snuffleupagus support])
diff --git a/src/php_snuffleupagus.h b/src/php_snuffleupagus.h
index f80ae66..008a480 100644
--- a/src/php_snuffleupagus.h
+++ b/src/php_snuffleupagus.h
@@ -43,6 +43,7 @@
43#include "sp_utils.h" 43#include "sp_utils.h"
44#include "sp_crypt.h" 44#include "sp_crypt.h"
45#include "sp_session.h" 45#include "sp_session.h"
46#include "sp_sloppy.h"
46 47
47 48
48extern zend_module_entry snuffleupagus_module_entry; 49extern zend_module_entry snuffleupagus_module_entry;
diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c
index c3fc686..08b2083 100644
--- a/src/snuffleupagus.c
+++ b/src/snuffleupagus.c
@@ -72,6 +72,7 @@ PHP_GINIT_FUNCTION(snuffleupagus) {
72 72
73 SP_INIT(snuffleupagus_globals->config.config_unserialize); 73 SP_INIT(snuffleupagus_globals->config.config_unserialize);
74 SP_INIT(snuffleupagus_globals->config.config_random); 74 SP_INIT(snuffleupagus_globals->config.config_random);
75 SP_INIT(snuffleupagus_globals->config.config_sloppy);
75 SP_INIT(snuffleupagus_globals->config.config_readonly_exec); 76 SP_INIT(snuffleupagus_globals->config.config_readonly_exec);
76 SP_INIT(snuffleupagus_globals->config.config_global_strict); 77 SP_INIT(snuffleupagus_globals->config.config_global_strict);
77 SP_INIT(snuffleupagus_globals->config.config_auto_cookie_secure); 78 SP_INIT(snuffleupagus_globals->config.config_auto_cookie_secure);
@@ -212,6 +213,10 @@ static PHP_INI_MH(OnUpdateConfiguration) {
212 213
213 SNUFFLEUPAGUS_G(is_config_valid) = true; 214 SNUFFLEUPAGUS_G(is_config_valid) = true;
214 215
216 if ((SNUFFLEUPAGUS_G(config).config_sloppy->enable)) {
217 hook_sloppy();
218 }
219
215 if (SNUFFLEUPAGUS_G(config).config_random->enable) { 220 if (SNUFFLEUPAGUS_G(config).config_random->enable) {
216 hook_rand(); 221 hook_rand();
217 } 222 }
diff --git a/src/sp_config.c b/src/sp_config.c
index a89174a..eb5b324 100644
--- a/src/sp_config.c
+++ b/src/sp_config.c
@@ -22,6 +22,7 @@ sp_config_tokens const sp_func[] = {
22 {.func = parse_eval_blacklist, .token = SP_TOKEN_EVAL_BLACKLIST}, 22 {.func = parse_eval_blacklist, .token = SP_TOKEN_EVAL_BLACKLIST},
23 {.func = parse_eval_whitelist, .token = SP_TOKEN_EVAL_WHITELIST}, 23 {.func = parse_eval_whitelist, .token = SP_TOKEN_EVAL_WHITELIST},
24 {.func = parse_session, .token = SP_TOKEN_SESSION_ENCRYPTION}, 24 {.func = parse_session, .token = SP_TOKEN_SESSION_ENCRYPTION},
25 {.func = parse_sloppy_comparison, .token = SP_TOKEN_SLOPPY_COMPARISON},
25 {NULL, NULL}}; 26 {NULL, NULL}};
26 27
27/* Top level keyword parsing */ 28/* Top level keyword parsing */
diff --git a/src/sp_config.h b/src/sp_config.h
index b44960f..979feda 100644
--- a/src/sp_config.h
+++ b/src/sp_config.h
@@ -53,6 +53,8 @@ typedef struct { bool enable; } sp_config_global_strict;
53 53
54typedef struct { bool enable; } sp_config_random; 54typedef struct { bool enable; } sp_config_random;
55 55
56typedef struct { bool enable; } sp_config_sloppy;
57
56typedef struct { bool enable; } sp_config_auto_cookie_secure; 58typedef struct { bool enable; } sp_config_auto_cookie_secure;
57 59
58typedef struct { bool enable; } sp_config_disable_xxe; 60typedef struct { bool enable; } sp_config_disable_xxe;
@@ -151,6 +153,7 @@ typedef struct {
151 153
152typedef struct { 154typedef struct {
153 sp_config_random *config_random; 155 sp_config_random *config_random;
156 sp_config_sloppy *config_sloppy;
154 sp_config_unserialize *config_unserialize; 157 sp_config_unserialize *config_unserialize;
155 sp_config_disabled_functions *config_disabled_functions; 158 sp_config_disabled_functions *config_disabled_functions;
156 sp_config_disabled_functions *config_disabled_functions_ret; 159 sp_config_disabled_functions *config_disabled_functions_ret;
@@ -192,6 +195,7 @@ typedef struct {
192#define SP_TOKEN_DISABLE_XXE ".disable_xxe" 195#define SP_TOKEN_DISABLE_XXE ".disable_xxe"
193#define SP_TOKEN_EVAL_BLACKLIST ".eval_blacklist" 196#define SP_TOKEN_EVAL_BLACKLIST ".eval_blacklist"
194#define SP_TOKEN_EVAL_WHITELIST ".eval_whitelist" 197#define SP_TOKEN_EVAL_WHITELIST ".eval_whitelist"
198#define SP_TOKEN_SLOPPY_COMPARISON ".sloppy_comparison"
195 199
196// common tokens 200// common tokens
197#define SP_TOKEN_ENABLE ".enable(" 201#define SP_TOKEN_ENABLE ".enable("
diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c
index cc1f0f9..2a570cd 100644
--- a/src/sp_config_keywords.c
+++ b/src/sp_config_keywords.c
@@ -105,6 +105,11 @@ int parse_random(char *line) {
105 NULL); 105 NULL);
106} 106}
107 107
108int parse_sloppy_comparison(char *line) {
109 return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_sloppy->enable),
110 NULL);
111}
112
108int parse_disable_xxe(char *line) { 113int parse_disable_xxe(char *line) {
109 return parse_enable( 114 return parse_enable(
110 line, &(SNUFFLEUPAGUS_G(config).config_disable_xxe->enable), NULL); 115 line, &(SNUFFLEUPAGUS_G(config).config_disable_xxe->enable), NULL);
diff --git a/src/sp_config_keywords.h b/src/sp_config_keywords.h
index f1f414a..36c66a5 100644
--- a/src/sp_config_keywords.h
+++ b/src/sp_config_keywords.h
@@ -15,5 +15,6 @@ int parse_upload_validation(char *line);
15int parse_eval_blacklist(char *line); 15int parse_eval_blacklist(char *line);
16int parse_eval_whitelist(char *line); 16int parse_eval_whitelist(char *line);
17int parse_session(char *line); 17int parse_session(char *line);
18int parse_sloppy_comparison(char *line);
18 19
19#endif // __SP_CONFIG_KEYWORDS_H 20#endif // __SP_CONFIG_KEYWORDS_H
diff --git a/src/sp_execute.c b/src/sp_execute.c
index ef71227..fb956ca 100644
--- a/src/sp_execute.c
+++ b/src/sp_execute.c
@@ -1,4 +1,5 @@
1#include "php_snuffleupagus.h" 1#include "php_snuffleupagus.h"
2#include "zend_vm.h"
2#include <errno.h> 3#include <errno.h>
3#include <string.h> 4#include <string.h>
4 5
diff --git a/src/sp_sloppy.c b/src/sp_sloppy.c
new file mode 100644
index 0000000..05d2505
--- /dev/null
+++ b/src/sp_sloppy.c
@@ -0,0 +1,39 @@
1#include "sp_sloppy.h"
2
3ZEND_API zend_op_array* (*zend_compile_file_default)(zend_file_handle* file_handle, int type) = NULL;
4ZEND_API zend_op_array* (*zend_compile_string_default)(zval* source_string, char* filename) = NULL;
5
6static void modify_opcode(zend_op_array* opline) {
7 if (NULL != opline) {
8 zend_op* orig_opline = opline->opcodes;
9 for (; NULL != orig_opline->handler; orig_opline++) {
10 if (orig_opline->opcode == ZEND_IS_EQUAL) {
11 orig_opline->opcode = ZEND_IS_IDENTICAL;
12 zend_vm_set_opcode_handler(orig_opline);
13 } else if (orig_opline->opcode == ZEND_IS_NOT_EQUAL) {
14 orig_opline->opcode = ZEND_IS_NOT_IDENTICAL;
15 zend_vm_set_opcode_handler(orig_opline);
16 }
17 }
18 }
19}
20
21ZEND_API zend_op_array* sp_compile_string(zval* source_string, char* filename) {
22 zend_op_array* opline = zend_compile_string_default(source_string, filename);
23 modify_opcode(opline);
24 return opline;
25}
26
27ZEND_API zend_op_array* sp_compile_file(zend_file_handle* file_handle, int type) {
28 zend_op_array* opline = zend_compile_file_default(file_handle, type);
29 modify_opcode(opline);
30 return opline;
31}
32
33void hook_sloppy() {
34 zend_compile_file_default = zend_compile_file;
35 zend_compile_file = sp_compile_file;
36
37 zend_compile_string_default = zend_compile_string;
38 zend_compile_string = sp_compile_string;
39}
diff --git a/src/sp_sloppy.h b/src/sp_sloppy.h
new file mode 100644
index 0000000..c01b77c
--- /dev/null
+++ b/src/sp_sloppy.h
@@ -0,0 +1,8 @@
1#ifndef SP_SLOPPY_H
2#define SP_SLOPPY_H
3#include "php_snuffleupagus.h"
4#include "zend_vm.h"
5
6void hook_sloppy();
7
8#endif
diff --git a/src/tests/config/sloppy_comparison.ini b/src/tests/config/sloppy_comparison.ini
new file mode 100644
index 0000000..ab2d32a
--- /dev/null
+++ b/src/tests/config/sloppy_comparison.ini
@@ -0,0 +1 @@
sp.sloppy_comparison.enable();
diff --git a/src/tests/sloppy_comparison.phpt b/src/tests/sloppy_comparison.phpt
new file mode 100644
index 0000000..da28e3d
--- /dev/null
+++ b/src/tests/sloppy_comparison.phpt
@@ -0,0 +1,30 @@
1--TEST--
2Sloppy comparison
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/sloppy_comparison.ini
7--FILE--
8<?php
9$qwe = "abc";
10if ($qwe == 0) {
11 echo "failed";
12}
13$qwe = "0e123";
14if ("0e432" == $qwe) {
15 echo "failed";
16}
17$qwe = [];
18$test = false;
19if ($test != $qwe) {
20 echo "lol";
21}
22eval("
23\$asd = 'qwe';
24if (\$asd == 0) {
25 echo 'oops';
26}
27");
28?>
29--EXPECT--
30lol
diff --git a/src/tests/sloppy_comparison_disable.phpt b/src/tests/sloppy_comparison_disable.phpt
new file mode 100644
index 0000000..f22804b
--- /dev/null
+++ b/src/tests/sloppy_comparison_disable.phpt
@@ -0,0 +1,14 @@
1--TEST--
2Sloppy comparison
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6--FILE--
7<?php
8$qwe = "abc";
9if ($qwe == 0) {
10 echo "OK";
11}
12?>
13--EXPECT--
14OK