diff options
| author | jvoisin | 2022-07-13 01:11:44 +0200 |
|---|---|---|
| committer | jvoisin | 2022-07-13 01:21:45 +0200 |
| commit | 3dbb2f3feeec54c4ab6b2efc53b5c5635dbd9129 (patch) | |
| tree | da7fafe6c25eba2e28f20158d2bd9d78bb9740a6 /src/sp_utils.c | |
| parent | eaba9e0e7421fec0bc7a0cd8745dc3fb4e2e72f1 (diff) | |
Mix the stacktrace in the sha256 for the filename of .dump()
This should make it easier to fuzz using Snuffleupagus.
Diffstat (limited to 'src/sp_utils.c')
| -rw-r--r-- | src/sp_utils.c | 60 |
1 files changed, 36 insertions, 24 deletions
diff --git a/src/sp_utils.c b/src/sp_utils.c index 2ec1750..fdcdc99 100644 --- a/src/sp_utils.c +++ b/src/sp_utils.c | |||
| @@ -93,32 +93,12 @@ int compute_hash(const char* const restrict filename, | |||
| 93 | static int construct_filename(char* filename, | 93 | static int construct_filename(char* filename, |
| 94 | const zend_string* restrict folder, | 94 | const zend_string* restrict folder, |
| 95 | const zend_string* restrict textual) { | 95 | const zend_string* restrict textual) { |
| 96 | PHP_SHA256_CTX context; | ||
| 97 | unsigned char digest[SHA256_SIZE] = {0}; | ||
| 98 | char strhash[65] = {0}; | ||
| 99 | |||
| 100 | if (-1 == mkdir(ZSTR_VAL(folder), 0700) && errno != EEXIST) { | ||
| 101 | sp_log_warn("request_logging", "Unable to create the folder '%s'", | ||
| 102 | ZSTR_VAL(folder)); | ||
| 103 | return -1; | ||
| 104 | } | ||
| 105 | |||
| 106 | /* We're using the sha256 sum of the rule's textual representation | ||
| 107 | * as filename, in order to only have one dump per rule, to mitigate | ||
| 108 | * DoS attacks. */ | ||
| 109 | PHP_SHA256Init(&context); | ||
| 110 | PHP_SHA256Update(&context, (const unsigned char*)ZSTR_VAL(textual), | ||
| 111 | ZSTR_LEN(textual)); | ||
| 112 | PHP_SHA256Final(digest, &context); | ||
| 113 | make_digest_ex(strhash, digest, SHA256_SIZE); | ||
| 114 | snprintf(filename, PATH_MAX - 1, "%s/sp_dump.%s", ZSTR_VAL(folder), strhash); | ||
| 115 | |||
| 116 | return 0; | 96 | return 0; |
| 117 | } | 97 | } |
| 118 | 98 | ||
| 119 | int sp_log_request(const zend_string* restrict folder, const zend_string* restrict text_repr) { | 99 | int sp_log_request(const zend_string* restrict folder, const zend_string* restrict text_repr) { |
| 120 | FILE* file; | 100 | FILE* file; |
| 121 | const char* current_filename = zend_get_executed_filename(TSRMLS_C); | 101 | char const* const current_filename = zend_get_executed_filename(TSRMLS_C); |
| 122 | const int current_line = zend_get_executed_lineno(TSRMLS_C); | 102 | const int current_line = zend_get_executed_lineno(TSRMLS_C); |
| 123 | char filename[PATH_MAX] = {0}; | 103 | char filename[PATH_MAX] = {0}; |
| 124 | const struct { | 104 | const struct { |
| @@ -128,9 +108,41 @@ int sp_log_request(const zend_string* restrict folder, const zend_string* restri | |||
| 128 | {"COOKIE", TRACK_VARS_COOKIE}, {"SERVER", TRACK_VARS_SERVER}, | 108 | {"COOKIE", TRACK_VARS_COOKIE}, {"SERVER", TRACK_VARS_SERVER}, |
| 129 | {"ENV", TRACK_VARS_ENV}, {NULL, 0}}; | 109 | {"ENV", TRACK_VARS_ENV}, {NULL, 0}}; |
| 130 | 110 | ||
| 131 | if (0 != construct_filename(filename, folder, text_repr)) { | 111 | PHP_SHA256_CTX context; |
| 112 | unsigned char digest[SHA256_SIZE] = {0}; | ||
| 113 | char strhash[65] = {0}; | ||
| 114 | |||
| 115 | if (-1 == mkdir(ZSTR_VAL(folder), 0700) && errno != EEXIST) { | ||
| 116 | sp_log_warn("request_logging", "Unable to create the folder '%s'", | ||
| 117 | ZSTR_VAL(folder)); | ||
| 132 | return -1; | 118 | return -1; |
| 133 | } | 119 | } |
| 120 | |||
| 121 | /* We're using the sha256 sum of the rule's textual representation, as well | ||
| 122 | * as the stacktrace as filename, in order to only have one dump per rule, to | ||
| 123 | * mitigate DoS attacks. We're doing the walk-the-execution-context dance | ||
| 124 | * twice because it's easier than to cache it in a linked-list. It doesn't | ||
| 125 | * really matter, since this is a super-cold path anyway. | ||
| 126 | */ | ||
| 127 | PHP_SHA256Init(&context); | ||
| 128 | PHP_SHA256Update(&context, (const unsigned char*)ZSTR_VAL(text_repr), ZSTR_LEN(text_repr)); | ||
| 129 | zend_execute_data* orig_execute_data = EG(current_execute_data); | ||
| 130 | zend_execute_data* current = EG(current_execute_data); | ||
| 131 | while (current) { | ||
| 132 | EG(current_execute_data) = current; | ||
| 133 | char* const complete_path_function = get_complete_function_path(current); | ||
| 134 | if (complete_path_function) { | ||
| 135 | const int current_line = zend_get_executed_lineno(TSRMLS_C); | ||
| 136 | PHP_SHA256Update(&context, (const unsigned char*)complete_path_function, strlen(complete_path_function)); | ||
| 137 | efree(complete_path_function); | ||
| 138 | } | ||
| 139 | current = current->prev_execute_data; | ||
| 140 | } | ||
| 141 | EG(current_execute_data) = orig_execute_data; | ||
| 142 | PHP_SHA256Final(digest, &context); | ||
| 143 | make_digest_ex(strhash, digest, SHA256_SIZE); | ||
| 144 | snprintf(filename, PATH_MAX - 1, "%s/sp_dump.%s", ZSTR_VAL(folder), strhash); | ||
| 145 | |||
| 134 | if (NULL == (file = fopen(filename, "w+"))) { | 146 | if (NULL == (file = fopen(filename, "w+"))) { |
| 135 | sp_log_warn("request_logging", "Unable to open %s: %s", filename, | 147 | sp_log_warn("request_logging", "Unable to open %s: %s", filename, |
| 136 | strerror(errno)); | 148 | strerror(errno)); |
| @@ -141,8 +153,8 @@ int sp_log_request(const zend_string* restrict folder, const zend_string* restri | |||
| 141 | 153 | ||
| 142 | fprintf(file, "FILE: %s:%d\n", current_filename, current_line); | 154 | fprintf(file, "FILE: %s:%d\n", current_filename, current_line); |
| 143 | 155 | ||
| 144 | zend_execute_data* orig_execute_data = EG(current_execute_data); | 156 | orig_execute_data = EG(current_execute_data); |
| 145 | zend_execute_data* current = EG(current_execute_data); | 157 | current = EG(current_execute_data); |
| 146 | while (current) { | 158 | while (current) { |
| 147 | EG(current_execute_data) = current; | 159 | EG(current_execute_data) = current; |
| 148 | char* const complete_path_function = get_complete_function_path(current); | 160 | char* const complete_path_function = get_complete_function_path(current); |
