Implement generic variables $urlencode_<name> and $urldecode_<name> for get urlencode/urldecode of v


#1

Raw value of arguments from request string can help for XSS.

src/http/ngx_http_variables.c | 134
+++++++++++++++++++++++++++++++++++++++++
1 files changed, 134 insertions(+), 0 deletions(-)

diff --git a/src/http/ngx_http_variables.c
b/src/http/ngx_http_variables.c
index
22f213cf6157ab5b99e481835acf9a394ef21919…035f6cc4687d20646d156d0ed58a303aef76b8d8
100644
— a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -31,6 +31,10 @@ static ngx_int_t
ngx_http_variable_cookie(ngx_http_request_t *r,
static ngx_int_t ngx_http_variable_ssi(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
#endif
+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);

@@ -530,6 +534,24 @@ ngx_http_get_variable(ngx_http_request_t *r,
ngx_str_t *name, ngx_uint_t key,
}
#endif

  • 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_urldecode(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) {
@@ -831,6 +853,104 @@ ngx_http_variable_ssi(ngx_http_request_t *r,
ngx_http_variable_value_t *v,

static ngx_int_t
+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;
  • ngx_str_t sub_name;
  • ngx_uint_t key;
  • 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 = 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) {
  •    v->not_found = 1;
    
  •    return NGX_OK;
    
  • }
  • (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->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)
{
@@ -1789,6 +1909,20 @@ ngx_http_variables_init_vars(ngx_conf_t *cf)
}
#endif

  •    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;
    
  •    }
    
  •    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;