Skip to content

Commit 7ce4da8

Browse files
committed
fix: query string bypass when use unsafe true
The real issue lies in the fact that when use_real_request_uri_unsafe is set to true and conf.uri is provided, the core.utils.resolve_var output back an upstream uri that does not include query string. Therefore we need to concatenate the query string for the case if conf.uri is true. The previous commit does not solve the issue as the issue is not related in the `if not conf.use_real_request_uri_unsafe then` statement.
1 parent 355b690 commit 7ce4da8

File tree

3 files changed

+124
-37
lines changed

3 files changed

+124
-37
lines changed

apisix/plugins/proxy-rewrite.lua

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -275,20 +275,26 @@ function _M.rewrite(conf, ctx)
275275
end
276276
end
277277

278+
-- normalized uri (without query string)
278279
local upstream_uri = ctx.var.uri
279280
local separator_escaped = false
280281

282+
local query_string = ""
281283
-- When use_real_request_uri_unsafe is true, we use real_request_uri directly
282284
if conf.use_real_request_uri_unsafe then
283-
upstream_uri = ctx.var.real_request_uri
285+
upstream_uri = ctx.var.real_request_uri -- Not normalized uri (with query string if available)
286+
local query_string_index = str_find(upstream_uri, "?")
287+
-- If query string exists, extract it. It is needed later when conf.uri is set.
288+
-- Because core.utils.resolve_var output will drop the query string part.
289+
query_string = query_string_index and sub_str(upstream_uri, query_string_index) or ""
284290
end
285291

286292
-- This block determines the upstream URI based on the configuration.
287293
-- uri has higher priority than regex_uri.
288294
if conf.uri ~= nil then
289-
separator_escaped = true
290295
-- Set the upstream_uri by resolving variables in conf.uri
291-
upstream_uri = core.utils.resolve_var(conf.uri, ctx.var, escape_separator)
296+
upstream_uri = core.utils.resolve_var(conf.uri, ctx.var, escape_separator) .. query_string
297+
separator_escaped = true
292298

293299
elseif conf.regex_uri ~= nil then
294300
if not str_find(upstream_uri, "?") then
@@ -327,8 +333,8 @@ function _M.rewrite(conf, ctx)
327333
end
328334
end
329335

330-
local index
331336
if not conf.use_real_request_uri_unsafe then
337+
local index
332338
if separator_escaped then
333339
index = str_find(upstream_uri, "?")
334340
end
@@ -344,21 +350,21 @@ function _M.rewrite(conf, ctx)
344350
end
345351

346352
req_set_uri(upstream_uri)
347-
else
348-
ctx.var.upstream_uri = upstream_uri
349-
end
350353

351-
-- Incoming request has arguments, append them to the upstream_uri
352-
-- to form the complete upstream_uri
353-
if ctx.var.is_args == "?" then
354-
if index then
355-
-- Upstream already has a '?', so we append incoming args with '&'
356-
ctx.var.upstream_uri = upstream_uri .. "&" .. (ctx.var.args or "")
354+
-- Incoming request has arguments, append them to the upstream_uri
355+
-- to form the complete upstream_uri
356+
if ctx.var.is_args == "?" then
357+
if index then
358+
-- Upstream already has a '?', so we append incoming args with '&'
359+
ctx.var.upstream_uri = upstream_uri .. "&" .. (ctx.var.args or "")
360+
else
361+
-- Upstream has no '?', so we start the query string with '?'
362+
ctx.var.upstream_uri = upstream_uri .. "?" .. (ctx.var.args or "")
363+
end
364+
-- Incoming request had no arguments
357365
else
358-
-- Upstream has no '?', so we start the query string with '?'
359-
ctx.var.upstream_uri = upstream_uri .. "?" .. (ctx.var.args or "")
366+
ctx.var.upstream_uri = upstream_uri
360367
end
361-
-- Incoming request had no arguments
362368
else
363369
ctx.var.upstream_uri = upstream_uri
364370
end

t/plugin/proxy-rewrite.t

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,3 +1231,95 @@ GET /hello
12311231
uri: /uri
12321232
host: test.com:6443
12331233
x-real-ip: 127.0.0.1
1234+
1235+
1236+
1237+
=== TEST 45: set route(rewrite uri args with unsafe allowed)
1238+
--- config
1239+
location /t {
1240+
content_by_lua_block {
1241+
local t = require("lib.test_admin").test
1242+
local code, body = t('/apisix/admin/routes/1',
1243+
ngx.HTTP_PUT,
1244+
[[{
1245+
"plugins": {
1246+
"proxy-rewrite": {
1247+
"uri": "/plugin_proxy_rewrite_args",
1248+
"use_real_request_uri_unsafe": true
1249+
}
1250+
},
1251+
"upstream": {
1252+
"nodes": {
1253+
"127.0.0.1:1980": 1
1254+
},
1255+
"type": "roundrobin"
1256+
},
1257+
"uri": "/hello"
1258+
}]]
1259+
)
1260+
1261+
if code >= 300 then
1262+
ngx.status = code
1263+
end
1264+
ngx.say(body)
1265+
}
1266+
}
1267+
--- request
1268+
GET /t
1269+
--- response_body
1270+
passed
1271+
1272+
1273+
1274+
=== TEST 46: rewrite uri args
1275+
--- request
1276+
GET /hello?q=apisix&a=iresty HTTP/1.1
1277+
--- response_body
1278+
uri: /plugin_proxy_rewrite_args
1279+
a: iresty
1280+
q: apisix
1281+
1282+
1283+
1284+
=== TEST 47: set route(rewrite uri empty args with unsafe allowed)
1285+
--- config
1286+
location /t {
1287+
content_by_lua_block {
1288+
local t = require("lib.test_admin").test
1289+
local code, body = t('/apisix/admin/routes/1',
1290+
ngx.HTTP_PUT,
1291+
[[{
1292+
"plugins": {
1293+
"proxy-rewrite": {
1294+
"uri": "/plugin_proxy_rewrite_args",
1295+
"use_real_request_uri_unsafe": true
1296+
}
1297+
},
1298+
"upstream": {
1299+
"nodes": {
1300+
"127.0.0.1:1980": 1
1301+
},
1302+
"type": "roundrobin"
1303+
},
1304+
"uri": "/hello"
1305+
}]]
1306+
)
1307+
1308+
if code >= 300 then
1309+
ngx.status = code
1310+
end
1311+
ngx.say(body)
1312+
}
1313+
}
1314+
--- request
1315+
GET /t
1316+
--- response_body
1317+
passed
1318+
1319+
1320+
1321+
=== TEST 48: rewrite uri empty args
1322+
--- request
1323+
GET /hello HTTP/1.1
1324+
--- response_body
1325+
uri: /plugin_proxy_rewrite_args

t/plugin/proxy-rewrite3.t

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ plugin_proxy_rewrite get method: POST
199199
200200
201201
202-
=== TEST 8: set route(unsafe uri not normalized at request)
202+
=== TEST 8: set route(unsafe uri not normalized at request with unsafe allowed)
203203
--- config
204204
location /t {
205205
content_by_lua_block {
@@ -243,7 +243,7 @@ ngx.var.request_uri: /print%5Furi%5Fdetailed
243243
244244
245245
246-
=== TEST 10: set route(safe uri not normalized at request)
246+
=== TEST 10: set route(safe uri not normalized at request with unsafe allowed)
247247
--- config
248248
location /t {
249249
content_by_lua_block {
@@ -1002,18 +1002,18 @@ GET /hello/%ED%85%8C%EC%8A%A4%ED%8A%B8 HTTP/1.1
10021002
10031003
10041004
1005-
=== TEST 42: set route(rewrite uri args with unsafe)
1005+
=== TEST 45: set route(unsafe uri normalized at request with unsafe not allowed)
10061006
--- config
10071007
location /t {
10081008
content_by_lua_block {
10091009
local t = require("lib.test_admin").test
10101010
local code, body = t('/apisix/admin/routes/1',
10111011
ngx.HTTP_PUT,
10121012
[[{
1013+
"methods": ["GET"],
10131014
"plugins": {
10141015
"proxy-rewrite": {
1015-
"uri": "/plugin_proxy_rewrite_args",
1016-
"use_real_request_uri_unsafe": true
1016+
"use_real_request_uri_unsafe": false
10171017
}
10181018
},
10191019
"upstream": {
@@ -1022,7 +1022,7 @@ GET /hello/%ED%85%8C%EC%8A%A4%ED%8A%B8 HTTP/1.1
10221022
},
10231023
"type": "roundrobin"
10241024
},
1025-
"uri": "/hello"
1025+
"uri": "/print_uri_detailed"
10261026
}]]
10271027
)
10281028
@@ -1032,25 +1032,14 @@ GET /hello/%ED%85%8C%EC%8A%A4%ED%8A%B8 HTTP/1.1
10321032
ngx.say(body)
10331033
}
10341034
}
1035-
--- request
1036-
GET /t
10371035
--- response_body
10381036
passed
10391037
10401038
10411039
1042-
=== TEST 43: rewrite uri args with unsafe
1043-
--- request
1044-
GET /hello?q=apisix&a=iresty HTTP/1.1
1045-
--- response_body
1046-
uri: /plugin_proxy_rewrite_args
1047-
a: iresty
1048-
q: apisix
1049-
1050-
1051-
1052-
=== TEST 44: rewrite uri empty args with unsafe
1040+
=== TEST 46: unsafe uri normalized at request
10531041
--- request
1054-
GET /hello HTTP/1.1
1042+
GET /print%5Furi%5Fdetailed HTTP/1.1
10551043
--- response_body
1056-
uri: /plugin_proxy_rewrite_args
1044+
ngx.var.uri: /print_uri_detailed
1045+
ngx.var.request_uri: /print_uri_detailed

0 commit comments

Comments
 (0)