You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sp...@apache.org on 2023/03/02 09:03:46 UTC
[apisix] 01/02: fix(proxy-rewrite): escape args part if it's not from user conf (#8888)
This is an automated email from the ASF dual-hosted git repository.
spacewander pushed a commit to branch release/2.15
in repository https://gitbox.apache.org/repos/asf/apisix.git
commit ca0c7d9da8e4b0241720a5fc46baa5baad826f74
Author: 罗泽轩 <sp...@gmail.com>
AuthorDate: Fri Feb 24 09:31:08 2023 +0800
fix(proxy-rewrite): escape args part if it's not from user conf (#8888)
---
apisix/core/utils.lua | 8 +-
apisix/plugins/proxy-rewrite.lua | 27 +++++--
t/plugin/proxy-rewrite3.t | 168 ++++++++++++++++++++++++++++++++++++++-
3 files changed, 193 insertions(+), 10 deletions(-)
diff --git a/apisix/core/utils.lua b/apisix/core/utils.lua
index f72996b78..01c8b34c8 100644
--- a/apisix/core/utils.lua
+++ b/apisix/core/utils.lua
@@ -293,6 +293,7 @@ do
local _ctx
local n_resolved
local pat = [[(?<!\\)\$\{?(\w+)\}?]]
+ local _escaper
local function resolve(m)
local v = _ctx[m[1]]
@@ -300,10 +301,13 @@ do
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
@@ -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
diff --git a/apisix/plugins/proxy-rewrite.lua b/apisix/plugins/proxy-rewrite.lua
index f53918003..9ef3b5f9f 100644
--- a/apisix/plugins/proxy-rewrite.lua
+++ b/apisix/plugins/proxy-rewrite.lua
@@ -165,13 +165,24 @@ function _M.rewrite(conf, ctx)
ctx.upstream_scheme = conf["scheme"]
end
+
+ local function escape_separator(s)
+ return re_sub(s, [[\?]], "%3F", "jo")
+ 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],
+ if not str_find(upstream_uri, "?") then
+ separator_escaped = true
+ end
+
+ local uri, _, err = re_sub(upstream_uri, conf.regex_uri[1],
conf.regex_uri[2], "jo")
if uri then
upstream_uri = uri
@@ -185,11 +196,17 @@ function _M.rewrite(conf, ctx)
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
diff --git a/t/plugin/proxy-rewrite3.t b/t/plugin/proxy-rewrite3.t
index 7501abd1d..0bedf09d4 100644
--- a/t/plugin/proxy-rewrite3.t
+++ b/t/plugin/proxy-rewrite3.t
@@ -327,8 +327,6 @@ ngx.var.request_uri: /print_uri_detailed
GET /t
--- response_body
passed
---- no_error_log
-[error]
@@ -339,5 +337,167 @@ GET /echo HTTP/1.1
X-Forwarded-Host: apisix.ai
--- response_headers
X-Forwarded-Host: test.com
---- no_error_log
-[error]
+
+
+
+=== TEST 14: 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 15: 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 16: 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 17: 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
+
+
+
+=== TEST 18: regex_uri with args
+--- 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": {
+ "regex_uri": ["^/test/(.*)/(.*)/(.*)", "/$1_$2_$3?a=c"]
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:8125": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/test/*"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+
+
+
+=== TEST 19: hit
+--- request
+GET /test/plugin/proxy/rewrite HTTP/1.1
+--- http_config
+ server {
+ listen 8125;
+ location / {
+ content_by_lua_block {
+ ngx.say(ngx.var.request_uri)
+ }
+ }
+ }
+--- response_body
+/plugin_proxy_rewrite?a=c