diff --git a/apisix/core/utils.lua b/apisix/core/utils.lua index d85f7bb42db1..9e8fc1e02e46 100644 --- a/apisix/core/utils.lua +++ b/apisix/core/utils.lua @@ -25,6 +25,7 @@ local math = math local sub_str = string.sub local str_byte = string.byte local tonumber = tonumber +local type = type local C = ffi.C local ffi_string = ffi.string local get_string_buf = base.get_string_buf @@ -165,4 +166,32 @@ function _M.uri_safe_encode(uri) end +function _M.validate_header_field(field) + for i = 1, #field do + local b = str_byte(field, i, i) + -- '!' - '~', excluding ':' + if not (32 < b and b < 127) or b == 58 then + return false + end + end + return true +end + + +function _M.validate_header_value(value) + if type(value) ~= "string" then + return true + end + + for i = 1, #value do + local b = str_byte(value, i, i) + -- control characters + if b < 32 or b >= 127 then + return false + end + end + return true +end + + return _M diff --git a/apisix/plugins/proxy-rewrite.lua b/apisix/plugins/proxy-rewrite.lua index b65384d88b7c..5fc4906d3a11 100644 --- a/apisix/plugins/proxy-rewrite.lua +++ b/apisix/plugins/proxy-rewrite.lua @@ -97,6 +97,12 @@ function _M.check_schema(conf) if #field == 0 then return false, 'invalid field length in header' end + if not core.utils.validate_header_field(field) then + return false, 'invalid field character in header' + end + if not core.utils.validate_header_value(value) then + return false, 'invalid value character in header' + end core.table.insert(conf.headers_arr, field) core.table.insert(conf.headers_arr, value) else diff --git a/t/plugin/proxy-rewrite.t b/t/plugin/proxy-rewrite.t index 35f4176d28c3..a5752e0a2f3f 100644 --- a/t/plugin/proxy-rewrite.t +++ b/t/plugin/proxy-rewrite.t @@ -915,3 +915,87 @@ GET /t property "uri" validation failed: failed to match pattern "^\\/.*" with "home" --- no_error_log [error] + + + +=== TEST 32: set route(invalid header field) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "proxy-rewrite": { + "uri": "/uri/plugin_proxy_rewrite", + "headers": { + "X-Api:Version": "v2" + } + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- error_code: 400 +--- response_body eval +qr/invalid field character/ +--- no_error_log +[error] + + + +=== TEST 33: set route(invalid header value) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "proxy-rewrite": { + "uri": "/uri/plugin_proxy_rewrite", + "headers": { + "X-Api-Version": "v2\r\n" + } + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- error_code: 400 +--- response_body eval +qr/invalid value character/ +--- no_error_log +[error]