From a99c0b3ba7ebbd27fd62f2bde3963354c2bf55e3 Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Thu, 16 Sep 2021 12:43:11 +0200 Subject: ported sid min/max restriction from suhosin --- src/snuffleupagus.c | 2 +- src/sp_config.h | 4 ++++ src/sp_config_keywords.c | 2 ++ src/sp_session.c | 27 ++++++++++++++++++++++----- src/tests/sid_too_long.phpt | 16 ++++++++++++++++ src/tests/sid_too_short.phpt | 16 ++++++++++++++++ 6 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 src/tests/sid_too_long.phpt create mode 100644 src/tests/sid_too_short.phpt (limited to 'src') diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c index 50711f0..84ab171 100644 --- a/src/snuffleupagus.c +++ b/src/snuffleupagus.c @@ -365,7 +365,7 @@ static PHP_INI_MH(OnUpdateConfiguration) { hook_stream_wrappers(); } - if (SNUFFLEUPAGUS_G(config).config_session->encrypt) { + if (SNUFFLEUPAGUS_G(config).config_session->encrypt || SNUFFLEUPAGUS_G(config).config_session->sid_min_length || SNUFFLEUPAGUS_G(config).config_session->sid_max_length) { hook_session(); } diff --git a/src/sp_config.h b/src/sp_config.h index af9b905..df36976 100644 --- a/src/sp_config.h +++ b/src/sp_config.h @@ -81,6 +81,8 @@ typedef struct { typedef struct { bool encrypt; bool simulation; + u_long sid_min_length; + u_long sid_max_length; } sp_config_session; typedef struct { @@ -292,6 +294,8 @@ typedef struct { #define SP_TOKEN_MAX_EXECUTION_DEPTH "max_execution_depth" #define SP_TOKEN_SERVER_ENCODE "server_encode" #define SP_TOKEN_SERVER_STRIP "server_strip" +#define SP_TOKEN_SID_MIN_LENGTH "sid_min_length" +#define SP_TOKEN_SID_MAX_LENGTH "sid_max_length" // upload_validator #define SP_TOKEN_UPLOAD_SCRIPT "script" diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c index 38b8526..bd8a9a1 100644 --- a/src/sp_config_keywords.c +++ b/src/sp_config_keywords.c @@ -33,6 +33,8 @@ SP_PARSE_FN(parse_session) { {parse_empty, SP_TOKEN_ENCRYPT, &(cfg->encrypt)}, {parse_empty, SP_TOKEN_SIMULATION, &(cfg->simulation)}, {parse_empty, SP_TOKEN_SIM, &(cfg->simulation)}, + {parse_ulong, SP_TOKEN_SID_MIN_LENGTH, &(cfg->sid_min_length)}, + {parse_ulong, SP_TOKEN_SID_MAX_LENGTH, &(cfg->sid_max_length)}, {0, 0, 0}}; SP_PROCESS_CONFIG_KEYWORDS_ERR(); diff --git a/src/sp_session.c b/src/sp_session.c index 7fa4937..64233d1 100644 --- a/src/sp_session.c +++ b/src/sp_session.c @@ -24,21 +24,35 @@ static int (*old_s_write)(PS_WRITE_ARGS); static int (*previous_sessionRINIT)(INIT_FUNC_ARGS) = NULL; static ZEND_INI_MH((*old_OnUpdateSaveHandler)) = NULL; +static void check_sid_length(zend_string *sid) { + const sp_config_session *cfg = SNUFFLEUPAGUS_G(config).config_session; + + if (sid) { + if (cfg->sid_min_length && ZSTR_LEN(sid) < cfg->sid_min_length) { + sp_log_auto("session", cfg->simulation, "Session ID is too short"); + } + if (cfg->sid_max_length && ZSTR_LEN(sid) > cfg->sid_max_length) { + sp_log_auto("session", cfg->simulation, "Session ID is too long"); + } + } +} + static int sp_hook_s_read(PS_READ_ARGS) { + const sp_config_session *cfg = SNUFFLEUPAGUS_G(config).config_session; + check_sid_length(key); + int r = old_s_read(mod_data, key, val, maxlifetime); - const sp_config_session *config_session = - SNUFFLEUPAGUS_G(config).config_session; if ((NULL == val) || (NULL == *val) || (0 == ZSTR_LEN(*val))) { return r; } - if (r == SUCCESS && config_session->encrypt) { + if (r == SUCCESS && cfg->encrypt) { zend_string *orig_val = *val; zval val_zval; ZVAL_PSTRINGL(&val_zval, ZSTR_VAL(*val), ZSTR_LEN(*val)); - int ret = decrypt_zval(&val_zval, config_session->simulation, NULL); + int ret = decrypt_zval(&val_zval, cfg->simulation, NULL); if (ZEND_HASH_APPLY_KEEP != ret) { zend_bailout(); } @@ -51,7 +65,10 @@ static int sp_hook_s_read(PS_READ_ARGS) { } static int sp_hook_s_write(PS_WRITE_ARGS) { - if (ZSTR_LEN(val) > 0 && SNUFFLEUPAGUS_G(config).config_session->encrypt) { + const sp_config_session *cfg = SNUFFLEUPAGUS_G(config).config_session; + check_sid_length(key); + + if (ZSTR_LEN(val) > 0 && cfg->encrypt) { zend_string *new_val = encrypt_zval(val); return old_s_write(mod_data, key, new_val, maxlifetime); } diff --git a/src/tests/sid_too_long.phpt b/src/tests/sid_too_long.phpt new file mode 100644 index 0000000..235b166 --- /dev/null +++ b/src/tests/sid_too_long.phpt @@ -0,0 +1,16 @@ +--TEST-- +SESSION ID too long +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/sid_length_limit.ini +--FILE-- + +--EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][session][drop] Session ID is too long in %a.php on line %d + +Fatal error: [snuffleupagus][0.0.0.0][session][drop] Session ID is too long in Unknown on line 0 \ No newline at end of file diff --git a/src/tests/sid_too_short.phpt b/src/tests/sid_too_short.phpt new file mode 100644 index 0000000..0d9d514 --- /dev/null +++ b/src/tests/sid_too_short.phpt @@ -0,0 +1,16 @@ +--TEST-- +SESSION ID too short +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/sid_length_limit.ini +--FILE-- + +--EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][session][drop] Session ID is too short in %a.php on line %d + +Fatal error: [snuffleupagus][0.0.0.0][session][drop] Session ID is too short in Unknown on line 0 \ No newline at end of file -- cgit v1.3