-
-
Notifications
You must be signed in to change notification settings - Fork 625
Open
Description
The request_uri API syntax: res, err = httpc:request_uri(uri, params) allows the 1st param uri to contain CRLF (\r\n), which can be used to inject another request with http pipelining.
For example, the following code will result in 3 requests to be made.
- run nc as dummy http server
nc -k -l 127.0.0.1 8088 - run test code
local http = require 'resty.http'
local httpc = http.new()
local mq = " HTTP/1.1\r\nHost: 127.0.0.1:8088\r\nContent-Type: application/json\r\nX-File: abc\r\nContent-Length: 2\r\n\r\n{}GET /xxx-inject HTTP/1.1\r\nHost: 127.0.0.1:8088\r\nContent-Length: 0\r\n\r\nGET /world"
local ret, err = httpc:request_uri('http://127.0.0.1:8088/hello'..mq)Result in nc output:
GET /hello HTTP/1.1
Host: 127.0.0.1:8088
Content-Type: application/json
X-File: abc
Content-Length: 2
{}GET /xxx-inject HTTP/1.1
Host: 127.0.0.1:8088
Content-Length: 0
GET /world HTTP/1.1
User-Agent: lua-resty-http/0.16.1 (Lua) ngx_lua/10019
Host: 127.0.0.1:8088A possible fix is:
local http = require 'resty.http'
local httpc = http.new()
local mq = " HTTP/1.1\r\nHost: 127.0.0.1:8088\r\nContent-Type: application/json\r\nX-File: abc\r\nContent-Length: 2\r\n\r\n{}GET /xxx-inject HTTP/1.1\r\nHost: 127.0.0.1:8088\r\nContent-Length: 0\r\n\r\nGET /world"
local function uri_gsub_crlf(uri)
return string.gsub(uri, '[\r\n]', function (s)
return string.format('%%%02X', string.byte(s))
end)
end
mq = uri_gsub_crlf(mq)
local ret, err = httpc:request_uri('http://127.0.0.1:8088/hello'..mq)
After the above fix, output in nc will be:
GET /hello HTTP/1.1%0D%0AHost: 127.0.0.1:8088%0D%0AContent-Type: application/json%0D%0AX-File: abc%0D%0AContent-Length: 2%0D%0A%0D%0A{}GET /xxx-inject HTTP/1.1%0D%0AHost: 127.0.0.1:8088%0D%0AContent-Length: 0%0D%0A%0D%0AGET /world HTTP/1.1
User-Agent: lua-resty-http/0.16.1 (Lua) ngx_lua/10019
Host: 127.0.0.1:8088TemaSM
Metadata
Metadata
Assignees
Labels
No labels