Skip to content

Commit

Permalink
fix(proxy-rewrite): escape args part if it's not from user conf
Browse files Browse the repository at this point in the history
Signed-off-by: spacewander <[email protected]>
  • Loading branch information
spacewander committed Feb 20, 2023
1 parent cfeadfb commit b201ff5
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 10 deletions.
8 changes: 7 additions & 1 deletion apisix/core/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -293,17 +293,21 @@ do
local _ctx
local n_resolved
local pat = [[(?<!\\)\$\{?(\w+)\}?]]
local _escaper

local function resolve(m)
local v = _ctx[m[1]]
if v == nil then
return ""
end
n_resolved = n_resolved + 1
if _escaper then
return _escaper(tostring(v))
end
return tostring(v)
end

function resolve_var(tpl, ctx)
function resolve_var(tpl, ctx, escaper)
n_resolved = 0
if not tpl then
return tpl, nil, n_resolved
Expand All @@ -316,8 +320,10 @@ do

-- avoid creating temporary function
_ctx = ctx
_escaper = escaper
local res, _, err = re_gsub(tpl, pat, resolve, "jo")
_ctx = nil
_escaper = nil
if not res then
return nil, err
end
Expand Down
30 changes: 21 additions & 9 deletions apisix/plugins/proxy-rewrite.lua
Original file line number Diff line number Diff line change
Expand Up @@ -253,18 +253,24 @@ do
end


function _M.rewrite(conf, ctx)
for _, name in ipairs(upstream_names) do
if conf[name] then
ctx.var[upstream_vars[name]] = conf[name]
end
local function escape_separator(s)
return re_sub(s, [[\?]], "%3F", "jo")
end

function _M.rewrite(conf, ctx)
for _, name in ipairs(upstream_names) do
if conf[name] then
ctx.var[upstream_vars[name]] = conf[name]
end
end

local upstream_uri = ctx.var.uri
local separator_escaped = false
if conf.use_real_request_uri_unsafe then
upstream_uri = ctx.var.real_request_uri
elseif conf.uri ~= nil then
upstream_uri = core.utils.resolve_var(conf.uri, ctx.var)
separator_escaped = true
upstream_uri = core.utils.resolve_var(conf.uri, ctx.var, escape_separator)
elseif conf.regex_uri ~= nil then
local uri, _, err = re_sub(ctx.var.uri, conf.regex_uri[1],
conf.regex_uri[2], "jo")
Expand All @@ -280,11 +286,17 @@ do
end

if not conf.use_real_request_uri_unsafe then
local index = str_find(upstream_uri, "?")
local index
if separator_escaped then
index = str_find(upstream_uri, "?")
end

if index then
upstream_uri = core.utils.uri_safe_encode(sub_str(upstream_uri, 1, index-1)) ..
sub_str(upstream_uri, index)
upstream_uri = core.utils.uri_safe_encode(sub_str(upstream_uri, 1, index - 1)) ..
sub_str(upstream_uri, index)
else
-- The '?' may come from client request '%3f' when we use ngx.var.uri directly or
-- via regex_uri
upstream_uri = core.utils.uri_safe_encode(upstream_uri)
end

Expand Down
111 changes: 111 additions & 0 deletions t/plugin/proxy-rewrite3.t
Original file line number Diff line number Diff line change
Expand Up @@ -455,3 +455,114 @@ passed
GET /echo HTTP/1.1
--- response_headers
test: test_in_set
=== TEST 21: set route
--- 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": {
"host": "test.xxxx.com"
}
},
"upstream": {
"nodes": {
"127.0.0.1:8125": 1
},
"type": "roundrobin"
},
"uri": "/hello*"
}]]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
=== TEST 22: hit with CRLF
--- request
GET /hello%3f0z=700%26a=c%20HTTP/1.1%0D%0AHost:google.com%0d%0a%0d%0a
--- http_config
server {
listen 8125;
location / {
content_by_lua_block {
ngx.say(ngx.var.host)
ngx.say(ngx.var.request_uri)
}
}
}
--- response_body
test.xxxx.com
/hello%3F0z=700&a=c%20HTTP/1.1%0D%0AHost:google.com%0D%0A%0D%0A
=== TEST 23: set route with uri
--- 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/remain",
"host": "test.xxxx.com"
}
},
"upstream": {
"nodes": {
"127.0.0.1:8125": 1
},
"type": "roundrobin"
},
"uri": "/hello*"
}]]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
=== TEST 24: hit with CRLF
--- request
GET /hello%3f0z=700%26a=c%20HTTP/1.1%0D%0AHost:google.com%0d%0a%0d%0a
--- http_config
server {
listen 8125;
location / {
content_by_lua_block {
ngx.say(ngx.var.host)
ngx.say(ngx.var.request_uri)
}
}
}
--- response_body
test.xxxx.com
//hello%253F0z=700&a=c%20HTTP/1.1%0D%0AHost:google.com%0D%0A%0D%0A/remain

0 comments on commit b201ff5

Please sign in to comment.