Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(proxy-rewrite): escape args part if it's not from user conf #8888

Merged
merged 2 commits into from
Feb 24, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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