diff --git a/apisix/plugins/csrf.lua b/apisix/plugins/csrf.lua index 4ed2ad624aa7..88af4fa2d49c 100644 --- a/apisix/plugins/csrf.lua +++ b/apisix/plugins/csrf.lua @@ -23,6 +23,8 @@ local ngx_decode_base64 = ngx.decode_base64 local ngx_time = ngx.time local ngx_cookie_time = ngx.cookie_time local math = math +local type = type +local tonumber = tonumber local SAFE_METHODS = {"GET", "HEAD", "OPTIONS"} @@ -98,18 +100,18 @@ local function check_csrf_token(conf, ctx, token) end local token_table, err = core.json.decode(token_str) - if err then - core.log.error("decode token error: ", err) + if err or type(token_table) ~= "table" then + core.log.error("decode token error: ", err or "token is not an object") return false end local random = token_table["random"] - if not random then + if not random or (type(random) ~= "number" and type(random) ~= "string") then core.log.error("no random in token") return false end - local expires = token_table["expires"] + local expires = tonumber(token_table["expires"]) if not expires then core.log.error("no expires in token") return false @@ -121,7 +123,7 @@ local function check_csrf_token(conf, ctx, token) end local sign = gen_sign(random, expires, conf.key) - if token_table["sign"] ~= sign then + if type(token_table["sign"]) ~= "string" or token_table["sign"] ~= sign then core.log.error("Invalid signatures") return false end diff --git a/t/plugin/csrf.t b/t/plugin/csrf.t index 6ed8b959256c..aad4809964ec 100644 --- a/t/plugin/csrf.t +++ b/t/plugin/csrf.t @@ -388,3 +388,92 @@ apisix: --- response_body userkey mt39FazQccyMqt4ctoRV7w== + + + +=== TEST 16: non-table csrf token (JSON number) +--- request +POST /hello +--- more_headers +apisix-csrf-token: MTIz +Cookie: apisix-csrf-token=MTIz +--- error_code: 401 +--- error_log: decode token error +--- no_error_log +attempt to index +--- response_body +{"error_msg":"Failed to verify the csrf token signature"} + + + +=== TEST 17: non-table csrf token (JSON boolean) +--- request +POST /hello +--- more_headers +apisix-csrf-token: dHJ1ZQ== +Cookie: apisix-csrf-token=dHJ1ZQ== +--- error_code: 401 +--- error_log: decode token error +--- no_error_log +attempt to index +--- response_body +{"error_msg":"Failed to verify the csrf token signature"} + + + +=== TEST 18: csrf token with invalid non-numeric expires +--- request +POST /hello +--- more_headers +apisix-csrf-token: eyJyYW5kb20iOjAuMSwiZXhwaXJlcyI6ImludmFsaWQiLCJzaWduIjoiYWJjIn0= +Cookie: apisix-csrf-token=eyJyYW5kb20iOjAuMSwiZXhwaXJlcyI6ImludmFsaWQiLCJzaWduIjoiYWJjIn0= +--- error_code: 401 +--- error_log: no expires in token +--- no_error_log +attempt to perform arithmetic +--- response_body +{"error_msg":"Failed to verify the csrf token signature"} + + + + +=== TEST 19: non-table csrf token (JSON null) +--- request +POST /hello +--- more_headers +apisix-csrf-token: bnVsbA== +Cookie: apisix-csrf-token=bnVsbA== +--- error_code: 401 +--- error_log: decode token error +--- no_error_log +attempt to index +--- response_body +{"error_msg":"Failed to verify the csrf token signature"} + + + +=== TEST 20: csrf token with invalid random type +--- request +POST /hello +--- more_headers +apisix-csrf-token: eyJyYW5kb20iOnRydWUsImV4cGlyZXMiOjk5OTk5OTk5OTksInNpZ24iOiJhYmMifQ== +Cookie: apisix-csrf-token=eyJyYW5kb20iOnRydWUsImV4cGlyZXMiOjk5OTk5OTk5OTksInNpZ24iOiJhYmMifQ== +--- error_code: 401 +--- error_log: no random in token +--- no_error_log +attempt to concatenate +--- response_body +{"error_msg":"Failed to verify the csrf token signature"} + + + +=== TEST 21: csrf token with invalid sign type +--- request +POST /hello +--- more_headers +apisix-csrf-token: eyJyYW5kb20iOjAuMSwiZXhwaXJlcyI6OTk5OTk5OTk5OSwic2lnbiI6MTIzfQ== +Cookie: apisix-csrf-token=eyJyYW5kb20iOjAuMSwiZXhwaXJlcyI6OTk5OTk5OTk5OSwic2lnbiI6MTIzfQ== +--- error_code: 401 +--- error_log: Invalid signatures +--- response_body +{"error_msg":"Failed to verify the csrf token signature"}