From 68f41a7883f75b30293eb0d599cc3dcfb0b373c7 Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Wed, 25 Mar 2009 20:11:48 +0300 Subject: [PATCH 1/6] Implements the $encoded_arg_ variables for get url encode value of argument from request string. Cc: catap@catap.ru Raw value of arguments from request string can help for XSS. --- src/http/ngx_http_variables.c | 56 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 56 insertions(+), 0 deletions(-) diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index 0c46c35..6840237 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -27,6 +27,10 @@ static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_ssi(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_encoded_argument(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -505,6 +509,15 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key, return NULL; } + if (ngx_strncmp(name->data, "encoded_arg_", 12) == 0) { + + if (ngx_http_variable_encoded_argument(r, vv, (uintptr_t) name) == NGX_OK) { + return vv; + } + + return NULL; + } + if (ngx_strncmp(name->data, "arg_", 4) == 0) { if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) { @@ -773,6 +786,42 @@ ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v, static ngx_int_t +ngx_http_variable_encoded_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + ngx_str_t *name = (ngx_str_t *) data; + + u_char *arg; + size_t len; + ngx_str_t value; + + len = name->len - (sizeof("encoded_arg_") - 1); + arg = name->data + sizeof("encoded_arg_") - 1; + + if (ngx_http_arg(r, arg, len, &value) != NGX_OK) { + v->not_found = 1; + return NGX_OK; + } + + v->len = value.len + + 2 * ngx_escape_uri(NULL, value.data, value.len, NGX_ESCAPE_ARGS); + + v->data = ngx_palloc(r->pool, v->len); + if (v->data == NULL) { + v->not_found = 1; + return NGX_OK; + } + + (void) ngx_escape_uri(v->data, value.data, value.len, NGX_ESCAPE_ARGS); + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + + +static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { @@ -1658,6 +1707,13 @@ ngx_http_variables_init_vars(ngx_conf_t *cf) continue; } + if (ngx_strncmp(v[i].name.data, "encoded_arg_", 12) == 0) { + v[i].get_handler = ngx_http_variable_encoded_argument; + v[i].data = (uintptr_t) &v[i].name; + + continue; + } + if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) { v[i].get_handler = ngx_http_variable_argument; v[i].data = (uintptr_t) &v[i].name; -- 1.6.2 From 9cd7b315d29bd952a074643903fe8193924eedf1 Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Thu, 26 Mar 2009 18:43:05 +0300 Subject: [PATCH 2/6] Implement generic variables $urlencode_ and $urldecode_ for get urlencode/urldecode of value of variable. Cc: catap@catap.ru --- src/http/ngx_http_variables.c | 112 +++++++++++++++++++++++++++++++++++------ 1 files changed, 96 insertions(+), 16 deletions(-) diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index 6840237..106e45b 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -29,7 +29,9 @@ static ngx_int_t ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_ssi(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_variable_encoded_argument(ngx_http_request_t *r, +static ngx_int_t ngx_http_variable_urlencode(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_urldecode(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -509,9 +511,18 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key, return NULL; } - if (ngx_strncmp(name->data, "encoded_arg_", 12) == 0) { + if (ngx_strncmp(name->data, "urlencode_", 10) == 0) { + + if (ngx_http_variable_urlencode(r, vv, (uintptr_t) name) == NGX_OK) { + return vv; + } + + return NULL; + } + + if (ngx_strncmp(name->data, "urldecode_", 10) == 0) { - if (ngx_http_variable_encoded_argument(r, vv, (uintptr_t) name) == NGX_OK) { + if (ngx_http_variable_urldecode(r, vv, (uintptr_t) name) == NGX_OK) { return vv; } @@ -786,25 +797,35 @@ ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v, static ngx_int_t -ngx_http_variable_encoded_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, +ngx_http_variable_urlencode(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_str_t *name = (ngx_str_t *) data; - u_char *arg; - size_t len; - ngx_str_t value; + ngx_str_t sub_name; - len = name->len - (sizeof("encoded_arg_") - 1); - arg = name->data + sizeof("encoded_arg_") - 1; + ngx_uint_t key; - if (ngx_http_arg(r, arg, len, &value) != NGX_OK) { + ngx_http_variable_value_t *vv; + + sub_name.len = name->len - (sizeof("urlencode_") - 1); + sub_name.data = name->data + sizeof("urlencode_") - 1; + + key = ngx_hash_strlow(sub_name.data, sub_name.data, sub_name.len); + + vv = ngx_http_get_variable(r, &sub_name, key, 0); + + if (vv == NULL || !vv->valid) { + return NGX_ERROR; + } + + if (vv->not_found) { v->not_found = 1; return NGX_OK; } - v->len = value.len + - 2 * ngx_escape_uri(NULL, value.data, value.len, NGX_ESCAPE_ARGS); + v->len = vv->len + + 2 * ngx_escape_uri(NULL, vv->data, vv->len, NGX_ESCAPE_ARGS); v->data = ngx_palloc(r->pool, v->len); if (v->data == NULL) { @@ -812,10 +833,62 @@ ngx_http_variable_encoded_argument(ngx_http_request_t *r, ngx_http_variable_valu return NGX_OK; } - (void) ngx_escape_uri(v->data, value.data, value.len, NGX_ESCAPE_ARGS); + (void) ngx_escape_uri(v->data, vv->data, vv->len, NGX_ESCAPE_ARGS); + + v->valid = 1; + v->not_found = 0; + v->no_cacheable = vv->no_cacheable; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_urldecode(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + ngx_str_t *name = (ngx_str_t *) data; + + u_char *dst, *src; + ngx_str_t sub_name; + ngx_uint_t key; + + ngx_http_variable_value_t *vv; + + sub_name.len = name->len - (sizeof("urldecode_") - 1); + sub_name.data = name->data + sizeof("urldecode_") - 1; + + key = ngx_hash_strlow(sub_name.data, sub_name.data, sub_name.len); + + vv = ngx_http_get_variable(r, &sub_name, key, 0); + + if (vv == NULL || !vv->valid) { + return NGX_ERROR; + } + + if (vv->not_found) { + v->not_found = 1; + return NGX_OK; + } + + v->len = vv->len; + + v->data = ngx_palloc(r->pool, v->len); + if (v->data == NULL) { + v->not_found = 1; + return NGX_OK; + } + + dst = v->data; + src = vv->data; + + ngx_unescape_uri(&dst, &src, vv->len, NGX_ESCAPE_ARGS); + + v->len = dst - v->data; + v->valid = 1; - v->no_cacheable = 0; v->not_found = 0; + v->no_cacheable = vv->no_cacheable; return NGX_OK; } @@ -1707,8 +1780,15 @@ ngx_http_variables_init_vars(ngx_conf_t *cf) continue; } - if (ngx_strncmp(v[i].name.data, "encoded_arg_", 12) == 0) { - v[i].get_handler = ngx_http_variable_encoded_argument; + if (ngx_strncmp(v[i].name.data, "urlencode_", 10) == 0) { + v[i].get_handler = ngx_http_variable_urlencode; + v[i].data = (uintptr_t) &v[i].name; + + continue; + } + + if (ngx_strncmp(v[i].name.data, "urldecode_", 10) == 0) { + v[i].get_handler = ngx_http_variable_urldecode; v[i].data = (uintptr_t) &v[i].name; continue; -- 1.6.2 From 76ffbb2bccc57bce9fc5c7bfd7dae444cdb13cc4 Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Fri, 24 Apr 2009 18:02:29 +0400 Subject: [PATCH 3/6] Implement $uri_remainder Cc: catap@catap.ru --- src/http/ngx_http_core_module.c | 5 +++++ src/http/ngx_http_request.h | 1 + src/http/ngx_http_variables.c | 4 ++++ 3 files changed, 10 insertions(+), 0 deletions(-) diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 26f24b3..971329e 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -838,6 +838,11 @@ ngx_http_core_find_config_phase(ngx_http_request_t *r, clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + if (!clcf->regex_locations) { + r->uri_remainder.len = r->uri.len - clcf->name.len; + r->uri_remainder.data = r->uri.data + clcf->name.len; + } + if (!r->internal && clcf->internal) { ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND); return NGX_OK; diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index 23a8846..6e8af66 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -373,6 +373,7 @@ struct ngx_http_request_s { ngx_str_t request_line; ngx_str_t uri; + ngx_str_t uri_remainder; ngx_str_t args; ngx_str_t exten; ngx_str_t unparsed_uri; diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index 106e45b..2051f46 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -164,6 +164,10 @@ static ngx_http_variable_t ngx_http_core_variables[] = { offsetof(ngx_http_request_t, uri), NGX_HTTP_VAR_NOCACHEABLE, 0 }, + { ngx_string("uri_remainder"), NULL, ngx_http_variable_request, + offsetof(ngx_http_request_t, uri_remainder), + NGX_HTTP_VAR_NOCACHEABLE, 0 }, + { ngx_string("document_uri"), NULL, ngx_http_variable_request, offsetof(ngx_http_request_t, uri), NGX_HTTP_VAR_NOCACHEABLE, 0 }, -- 1.6.2 From 9895f414613d437dad7f8264ba2adba1e5d976d7 Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Tue, 28 Apr 2009 16:11:35 +0400 Subject: [PATCH 4/6] Reset uri_remainder for regex locations Cc: catap@catap.ru --- src/http/ngx_http_core_module.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 971329e..28f2cc1 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -841,6 +841,9 @@ ngx_http_core_find_config_phase(ngx_http_request_t *r, if (!clcf->regex_locations) { r->uri_remainder.len = r->uri.len - clcf->name.len; r->uri_remainder.data = r->uri.data + clcf->name.len; + } else { + r->uri_remainder.len = 0; + r->uri_remainder.data = NULL; } if (!r->internal && clcf->internal) { -- 1.6.2 From 3d307efe97ff80a8a91fe2d269292db2cebe8124 Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Wed, 13 May 2009 15:37:56 +0400 Subject: [PATCH 5/6] Implement generic variables $crc32_ for get crc32 value of variable. Cc: catap@catap.ru --- src/http/ngx_http_variables.c | 63 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 63 insertions(+), 0 deletions(-) diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index 2051f46..676b02f 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -33,6 +33,8 @@ static ngx_int_t ngx_http_variable_urlencode(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_urldecode(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_crc32(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -533,6 +535,15 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key, return NULL; } + if (ngx_strncmp(name->data, "crc32_", 6) == 0) { + + if (ngx_http_variable_crc32(r, vv, (uintptr_t) name) == NGX_OK) { + return vv; + } + + return NULL; + } + if (ngx_strncmp(name->data, "arg_", 4) == 0) { if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) { @@ -899,6 +910,51 @@ ngx_http_variable_urldecode(ngx_http_request_t *r, ngx_http_variable_value_t *v, static ngx_int_t +ngx_http_variable_crc32(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + ngx_str_t *name = (ngx_str_t *) data; + + ngx_str_t sub_name; + ngx_uint_t key; + + ngx_http_variable_value_t *vv; + + sub_name.len = name->len - (sizeof("crc32_") - 1); + sub_name.data = name->data + sizeof("crc32_") - 1; + + key = ngx_hash_strlow(sub_name.data, sub_name.data, sub_name.len); + + vv = ngx_http_get_variable(r, &sub_name, key, 0); + + if (vv == NULL || !vv->valid) { + return NGX_ERROR; + } + + if (vv->not_found) { + v->not_found = 1; + return NGX_OK; + } + + v->len = sizeof("3C32515A") - 1; + + v->data = ngx_palloc(r->pool, v->len); + if (v->data == NULL) { + v->not_found = 1; + return NGX_OK; + } + + ngx_sprintf(v->data, "%08XD", ngx_crc32_long(vv->data, vv->len)); + + v->valid = 1; + v->not_found = 0; + v->no_cacheable = vv->no_cacheable; + + return NGX_OK; +} + + +static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { @@ -1798,6 +1854,13 @@ ngx_http_variables_init_vars(ngx_conf_t *cf) continue; } + if (ngx_strncmp(v[i].name.data, "crc32_", 6) == 0) { + v[i].get_handler = ngx_http_variable_crc32; + v[i].data = (uintptr_t) &v[i].name; + + continue; + } + if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) { v[i].get_handler = ngx_http_variable_argument; v[i].data = (uintptr_t) &v[i].name; -- 1.6.2 From 195118f78a1d5f001ebcd8f5d91b79eedd7a0c27 Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Wed, 13 May 2009 15:47:04 +0400 Subject: [PATCH 6/6] Implement generic variables $md5_ for get md5 value of variable. Cc: catap@catap.ru --- src/http/ngx_http_variables.c | 70 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 70 insertions(+), 0 deletions(-) diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index 676b02f..8a21e79 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -35,6 +36,8 @@ static ngx_int_t ngx_http_variable_urldecode(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_crc32(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_md5(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -544,6 +547,15 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key, return NULL; } + if (ngx_strncmp(name->data, "md5_", 4) == 0) { + + if (ngx_http_variable_md5(r, vv, (uintptr_t) name) == NGX_OK) { + return vv; + } + + return NULL; + } + if (ngx_strncmp(name->data, "arg_", 4) == 0) { if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) { @@ -955,6 +967,57 @@ ngx_http_variable_crc32(ngx_http_request_t *r, ngx_http_variable_value_t *v, static ngx_int_t +ngx_http_variable_md5(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + ngx_str_t *name = (ngx_str_t *) data; + + ngx_str_t sub_name; + ngx_uint_t key; + ngx_md5_t md5; + uint32_t hash[4]; + + ngx_http_variable_value_t *vv; + + sub_name.len = name->len - (sizeof("md5_") - 1); + sub_name.data = name->data + sizeof("md5_") - 1; + + key = ngx_hash_strlow(sub_name.data, sub_name.data, sub_name.len); + + vv = ngx_http_get_variable(r, &sub_name, key, 0); + + if (vv == NULL || !vv->valid) { + return NGX_ERROR; + } + + if (vv->not_found) { + v->not_found = 1; + return NGX_OK; + } + + v->len = sizeof("7002945D4B8D9E472866092689DB3EAD") - 1; + + v->data = ngx_palloc(r->pool, v->len); + if (v->data == NULL) { + v->not_found = 1; + return NGX_OK; + } + + ngx_md5_init(&md5); + ngx_md5_update(&md5, vv->data, vv->len); + ngx_md5_final((u_char*)hash, &md5); + + ngx_sprintf(v->data, "%08XD%08XD%08XD%08XD", hash[0], hash[1], hash[2], hash[3]); + + v->valid = 1; + v->not_found = 0; + v->no_cacheable = vv->no_cacheable; + + return NGX_OK; +} + + +static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { @@ -1861,6 +1924,13 @@ ngx_http_variables_init_vars(ngx_conf_t *cf) continue; } + if (ngx_strncmp(v[i].name.data, "md5_", 4) == 0) { + v[i].get_handler = ngx_http_variable_md5; + v[i].data = (uintptr_t) &v[i].name; + + continue; + } + if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) { v[i].get_handler = ngx_http_variable_argument; v[i].data = (uintptr_t) &v[i].name; -- 1.6.2