diff options
| author | xXx-caillou-xXx | 2017-11-24 14:03:37 +0100 |
|---|---|---|
| committer | jvoisin | 2017-11-24 14:03:37 +0100 |
| commit | 5a224ee0c92d1639395d6a0c629316ae64226125 (patch) | |
| tree | 8925d27e2bbfa877e9fb1fc20868fbef3d009b04 /src/sp_cookie_encryption.c | |
| parent | 79304a29661476dc75bba07c5a83133122bbcb5c (diff) | |
Implement anti csrf measures
This is done by using the "samesite" cookie attribute.
Diffstat (limited to 'src/sp_cookie_encryption.c')
| -rw-r--r-- | src/sp_cookie_encryption.c | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/src/sp_cookie_encryption.c b/src/sp_cookie_encryption.c index 2ebcc96..eb20c52 100644 --- a/src/sp_cookie_encryption.c +++ b/src/sp_cookie_encryption.c | |||
| @@ -45,12 +45,12 @@ int decrypt_cookie(zval *pDest, int num_args, va_list args, | |||
| 45 | size_t value_len; | 45 | size_t value_len; |
| 46 | zend_string *debase64; | 46 | zend_string *debase64; |
| 47 | unsigned char *decrypted; | 47 | unsigned char *decrypted; |
| 48 | sp_cookie *cookie = zend_hash_find_ptr(SNUFFLEUPAGUS_G(config).config_cookie->cookies, | ||
| 49 | hash_key->key); | ||
| 48 | int ret = 0; | 50 | int ret = 0; |
| 49 | 51 | ||
| 50 | /* If the cookie isn't in the conf, it shouldn't be encrypted. */ | 52 | /* If the cookie isn't in the conf, it shouldn't be encrypted. */ |
| 51 | if (0 == | 53 | if (!cookie || !cookie->encrypt) { |
| 52 | zend_hash_exists(SNUFFLEUPAGUS_G(config).config_cookie_encryption->names, | ||
| 53 | hash_key->key)) { | ||
| 54 | return ZEND_HASH_APPLY_KEEP; | 54 | return ZEND_HASH_APPLY_KEEP; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| @@ -135,11 +135,13 @@ static zend_string *encrypt_data(char *data, unsigned long long data_len) { | |||
| 135 | 135 | ||
| 136 | PHP_FUNCTION(sp_setcookie) { | 136 | PHP_FUNCTION(sp_setcookie) { |
| 137 | zval params[7] = { 0 }; | 137 | zval params[7] = { 0 }; |
| 138 | zend_string *name = NULL, *value = NULL, *path = NULL, *domain = NULL; | 138 | zend_string *name = NULL, *value = NULL, *path = NULL, *domain = NULL, *samesite = NULL; |
| 139 | zend_long expires = 0; | 139 | zend_long expires = 0; |
| 140 | zend_bool secure = 0, httponly = 0; | 140 | zend_bool secure = 0, httponly = 0; |
| 141 | zval ret_val; | 141 | zval ret_val; |
| 142 | const sp_cookie *cookie_node = NULL; | ||
| 142 | zval func_name; | 143 | zval func_name; |
| 144 | char *cookie_samesite; | ||
| 143 | 145 | ||
| 144 | 146 | ||
| 145 | // LCOV_EXCL_BR_START | 147 | // LCOV_EXCL_BR_START |
| @@ -167,17 +169,18 @@ PHP_FUNCTION(sp_setcookie) { | |||
| 167 | } | 169 | } |
| 168 | } | 170 | } |
| 169 | 171 | ||
| 172 | cookie_node = | ||
| 173 | zend_hash_find_ptr(SNUFFLEUPAGUS_G(config).config_cookie->cookies, name); | ||
| 174 | |||
| 170 | /* If the cookie's value is encrypted, it won't be usable by | 175 | /* If the cookie's value is encrypted, it won't be usable by |
| 171 | * javascript anyway. | 176 | * javascript anyway. |
| 172 | */ | 177 | */ |
| 173 | if (zend_hash_exists(SNUFFLEUPAGUS_G(config).config_cookie_encryption->names, | 178 | if (cookie_node && cookie_node->encrypt) { |
| 174 | name) > 0) { | ||
| 175 | httponly = 1; | 179 | httponly = 1; |
| 176 | } | 180 | } |
| 177 | 181 | ||
| 178 | /* Shall we encrypt the cookie's value? */ | 182 | /* Shall we encrypt the cookie's value? */ |
| 179 | if (zend_hash_exists(SNUFFLEUPAGUS_G(config).config_cookie_encryption->names, | 183 | if (httponly && value) { |
| 180 | name) > 0 && value) { | ||
| 181 | zend_string *encrypted_data = encrypt_data(value->val, value->len); | 184 | zend_string *encrypted_data = encrypt_data(value->val, value->len); |
| 182 | ZVAL_STR_COPY(¶ms[1], encrypted_data); | 185 | ZVAL_STR_COPY(¶ms[1], encrypted_data); |
| 183 | zend_string_release(encrypted_data); | 186 | zend_string_release(encrypted_data); |
| @@ -188,9 +191,6 @@ PHP_FUNCTION(sp_setcookie) { | |||
| 188 | ZVAL_STRING(&func_name, "setcookie"); | 191 | ZVAL_STRING(&func_name, "setcookie"); |
| 189 | ZVAL_STR_COPY(¶ms[0], name); | 192 | ZVAL_STR_COPY(¶ms[0], name); |
| 190 | ZVAL_LONG(¶ms[2], expires); | 193 | ZVAL_LONG(¶ms[2], expires); |
| 191 | if (path) { | ||
| 192 | ZVAL_STR_COPY(¶ms[3], path); | ||
| 193 | } | ||
| 194 | if (domain) { | 194 | if (domain) { |
| 195 | ZVAL_STR_COPY(¶ms[4], domain); | 195 | ZVAL_STR_COPY(¶ms[4], domain); |
| 196 | } | 196 | } |
| @@ -201,6 +201,23 @@ PHP_FUNCTION(sp_setcookie) { | |||
| 201 | ZVAL_LONG(¶ms[6], httponly); | 201 | ZVAL_LONG(¶ms[6], httponly); |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | /* param[3](path) is concatenated to path= and is not filtered, we can inject | ||
| 205 | the samesite parameter here */ | ||
| 206 | if (cookie_node && cookie_node->samesite) { | ||
| 207 | if (!path) { | ||
| 208 | path = zend_string_init("", 0, 0); | ||
| 209 | } | ||
| 210 | cookie_samesite = (cookie_node->samesite == lax) ? SAMESITE_COOKIE_FORMAT SP_TOKEN_SAMESITE_LAX | ||
| 211 | : SAMESITE_COOKIE_FORMAT SP_TOKEN_SAMESITE_STRICT; | ||
| 212 | /* Concatenating everything, as is in PHP internals */ | ||
| 213 | samesite = zend_string_extend(path, ZSTR_LEN(path) + strlen(cookie_samesite) + 1, 0); | ||
| 214 | memcpy(ZSTR_VAL(samesite) + ZSTR_LEN(path), cookie_samesite, strlen(cookie_samesite) + 1); | ||
| 215 | ZVAL_STR_COPY(¶ms[3], samesite); | ||
| 216 | zend_string_release(path); | ||
| 217 | } else if (path) { | ||
| 218 | ZVAL_STR_COPY(¶ms[3], path); | ||
| 219 | } | ||
| 220 | |||
| 204 | /* This is the _fun_ part: because PHP is utterly idiotic and nonsensical, | 221 | /* This is the _fun_ part: because PHP is utterly idiotic and nonsensical, |
| 205 | the `call_user_function` macro will __discard__ (yes) its first argument | 222 | the `call_user_function` macro will __discard__ (yes) its first argument |
| 206 | (the hashtable), effectively calling functions from `CG(function_table)`. | 223 | (the hashtable), effectively calling functions from `CG(function_table)`. |
