[FOLIO-2564] investigate HTTP Response Header injection Created: 16/Apr/20 Updated: 13/Jul/21 Resolved: 05/May/20 |
|
| Status: | Closed |
| Project: | FOLIO |
| Components: | None |
| Affects versions: | None |
| Fix versions: | None |
| Type: | Task | Priority: | P2 |
| Reporter: | Jakub Skoczen | Assignee: | Craig McNally |
| Resolution: | Done | Votes: | 0 |
| Labels: | platform-backlog, security | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original estimate: | Not Specified | ||
| Issue links: |
|
||||||||||||||||||||||||||||
| Sprint: | CP: sprint 87, CP: sprint 88 | ||||||||||||||||||||||||||||
| Story Points: | 3 | ||||||||||||||||||||||||||||
| Development Team: | Core: Platform | ||||||||||||||||||||||||||||
| Description |
|
Problem The application reflects the value of any HTTP headers into the response headers. This may allow an attacker to insert arbitrary code into the response, including additional HTTP head- ers and potentially body content. An attacker can leverage HTTP response header injection to perform cross-site scripting, cross-user defacement, cache poisoning attacks and more. However, due to cross-origin setting of HTTP headers being blocked by the CORS policy, the severity of this finding is set to Medium. Steps to verify Perform a GET request with with a valid JWT and a set-cookie header and observe the set-cookie header in HTTP response, e.g: GET /users?query=%28id%3D%3D%22f5f46a28-d34f-4c8d-9e7f-d88206141d12%22%20or%20id% 3D%3D%22a058f28f-80ac-4994-add6-e4d02fc238fe%22%20or%20id%3D%3D%22e19ae972-63 41-4451-9ca1-1f4aabfc986e%22%29 Acceptance criteria Ensure that:
List of Q1 modules: https://docs.google.com/spreadsheets/d/1NvvCq1wTfDeCnd7zHDIzLI7RBfuSr_Ty0tbzYzgEaI8/edit#gid=0 |
| Comments |
| Comment by Craig McNally [ 22/Apr/20 ] |
|
I was able to reproduce this against an edelweiss deployment for a few modules:
Example: ..elided... > Set-Cookie: token=foobarbaz; path=/; expires=Fri, 01 Jan 2021 00:00:00 GMT > < HTTP/1.1 200 OK < Date: Wed, 22 Apr 2020 14:15:00 GMT < Content-Type: application/json < Transfer-Encoding: chunked < Connection: keep-alive < Server: nginx/1.10.3 < X-Okapi-Trace: GET mod-authtoken-2.4.0 http://<masked>:8051/mod-authtoken/loan-storage/loans.. : 202 8572us < x-forwarded-for: <masked> < x-forwarded-proto: http < x-forwarded-port: 8051 < x-amzn-trace-id: Self=1-5ea05164-a3e7a75c3d2325a8ad153628;Root=1-5ea05164-45990650726085cc22435244 < x-nginx-proxy: true < user-agent: curl/7.47.0 < accept: */* < set-cookie: token=foobarbaz; path=/; expires=Fri, 01 Jan 2021 00:00:00 GMT < x-okapi-request-id: 793543/loan-storage < x-okapi-tenant: fs00000002 < x-okapi-url: http://<masked>:9130 < x-okapi-request-ip: <masked> < x-okapi-request-timestamp: 1587564900099 < x-okapi-request-method: GET < x-okapi-permissions: ["circulation-storage.loans.collection.get"] < x-okapi-user-id: f9e1f652-efed-49c9-a3e4-34c3374047bc < x-okapi-match-path-pattern: /loan-storage/loans < X-Okapi-Trace: GET mod-circulation-storage-10.0.1 http://<masked>:8051/mod-circulation-storage/loan-storage/loans.. : 200 7253us < { "loans" : [ ], "totalRecords" : 192 } I did not try every module, but focused on those that had an older version of RMB (or weren't using RMB). The handful of modules I tested that were running RMB 29.X did not echo the request headers. When retesting these modules against fameflower, I was able to verify that the problem has been addressed in most cases. However, there's at least one case where the problem still exists.
...elided... > Set-Cookie: token=foobarbaz; path=/; expires=Fri, 01 Jan 2021 00:00:00 GMT > X-Okapi-Tenant: diku > X-Okapi-Foo: bar > < HTTP/1.1 200 OK < Date: Wed, 22 Apr 2020 14:30:10 GMT < Content-Type: application/json < Transfer-Encoding: chunked < Connection: keep-alive < X-Okapi-Trace: GET mod-authtoken-2.4.0 http://10.36.1.37:9175/loan-storage/loans.. : 202 6586us < X-Okapi-Trace: GET mod-circulation-storage-11.0.0 http://10.36.1.37:9176/loan-storage/loans.. : 200 2496us < { "loans" : [ ], "totalRecords" : 5 * Connection #0 to host folio-fameflower-okapi.dev.folio.org left intact }
...elided... > Set-Cookie: token=foobarbaz; path=/; expires=Fri, 01 Jan 2021 00:00:00 GMT > X-Okapi-Tenant: diku > X-Okapi-Foo: bar > < HTTP/1.1 200 OK < Date: Wed, 22 Apr 2020 14:31:23 GMT < Content-Type: application/json < Transfer-Encoding: chunked < Connection: keep-alive < X-Okapi-Trace: GET mod-authtoken-2.4.0 http://10.36.1.37:9175/accounts.. : 202 32237us < X-Okapi-Trace: GET mod-feesfines-15.7.2 http://10.36.1.37:9137/accounts.. : 200 19008us < { "accounts" : [ ], "totalRecords" : 0, "resultInfo" : { "totalRecords" : 0, "facets" : [ ], "diagnostics" : [ ] } * Connection #0 to host folio-fameflower-okapi.dev.folio.org left intact }
...elided... > Set-Cookie: token=foobarbaz; path=/; expires=Fri, 01 Jan 2021 00:00:00 GMT > X-Okapi-Tenant: diku > X-Okapi-Foo: bar > < HTTP/1.1 200 OK < Date: Wed, 22 Apr 2020 14:32:37 GMT < Content-Type: application/json < Transfer-Encoding: chunked < Connection: keep-alive < X-Okapi-Trace: GET mod-authtoken-2.4.0 http://10.36.1.37:9175/notify.. : 202 31585us < x-forwarded-for: 24.63.116.35 < x-forwarded-proto: https < x-forwarded-port: 443 < host: folio-fameflower-okapi.dev.folio.org < x-amzn-trace-id: Root=1-5ea05585-9371801b241a16cb03fd3c7a < user-agent: curl/7.47.0 < accept: */* < set-cookie: token=foobarbaz; path=/; expires=Fri, 01 Jan 2021 00:00:00 GMT < x-okapi-tenant: diku < x-okapi-foo: bar < x-okapi-request-id: 606342/notify < x-okapi-url: http://10.36.1.37:9130 < x-okapi-request-ip: 10.36.10.74 < x-okapi-request-timestamp: 1587565957613 < x-okapi-request-method: GET < x-okapi-permissions: ["notify.collection.get"] < x-okapi-user-id: ff8a07c0-9985-50c4-82be-d71aca738738 < x-okapi-match-path-pattern: /notify < X-Okapi-Trace: GET mod-notify-2.5.0 http://10.36.1.37:9162/notify.. : 200 206911us < { "notifications" : [ ], "totalRecords" : 0 * Connection #0 to host folio-fameflower-okapi.dev.folio.org left intact }
...elided... > Set-Cookie: token=foobarbaz; path=/; expires=Fri, 01 Jan 2021 00:00:00 GMT > X-Okapi-Tenant: diku > X-Okapi-Foo: bar > < HTTP/1.1 200 OK < Date: Wed, 22 Apr 2020 14:35:55 GMT < Content-Type: application/json;charset=UTF-8 < Transfer-Encoding: chunked < Connection: keep-alive < X-Okapi-Trace: GET mod-authtoken-2.4.0 http://10.36.1.37:9175/licenses/licenses.. : 202 6735us < X-Application-Context: application:production < X-Okapi-Trace: GET mod-licenses-2.1.1 http://10.36.1.37:9164/licenses/licenses.. : 200 96036us < { [13986 bytes data] * Connection #0 to host folio-fameflower-okapi.dev.folio.org left intact
...elided... > Set-Cookie: token=foobarbaz; path=/; expires=Fri, 01 Jan 2021 00:00:00 GMT > X-Okapi-Tenant: diku > X-Okapi-Foo: bar > < HTTP/1.1 200 OK < Date: Wed, 22 Apr 2020 14:38:18 GMT < Content-Type: application/json;charset=UTF-8 < Transfer-Encoding: chunked < Connection: keep-alive < X-Okapi-Trace: GET mod-authtoken-2.4.0 http://10.36.1.37:9175/erm/sas.. : 202 31902us < X-Application-Context: application:production < X-Okapi-Trace: GET mod-agreements-2.2.0 http://10.36.1.37:9178/erm/sas.. : 200 28761us < { [791 bytes data] * Connection #0 to host folio-fameflower-okapi.dev.folio.org left intact
...elided... > Set-Cookie: token=foobarbaz; path=/; expires=Fri, 01 Jan 2021 00:00:00 GMT > X-Okapi-Tenant: diku > X-Okapi-Foo: bar > < HTTP/1.1 200 OK < Date: Wed, 22 Apr 2020 14:40:01 GMT < Content-Type: application/json < Transfer-Encoding: chunked < Connection: keep-alive < X-Okapi-Trace: GET mod-authtoken-2.4.0 http://10.36.1.37:9175/saml/check : 202 7417us < X-Okapi-Trace: GET mod-login-saml-1.3.0 http://10.36.1.37:9153/saml/check : 200 20497us < { [28 bytes data] * Connection #0 to host folio-fameflower-okapi.dev.folio.org left intact
...elided... > Set-Cookie: token=foobarbaz; path=/; expires=Fri, 01 Jan 2021 00:00:00 GMT > X-Okapi-Tenant: diku > X-Okapi-Foo: bar > < HTTP/1.1 200 OK < Date: Thu, 23 Apr 2020 15:26:20 GMT < Content-Type: text/plain < Transfer-Encoding: chunked < Connection: keep-alive < X-Okapi-Trace: GET mod-authtoken-2.4.0 http://10.36.1.37:9175/ncipconfigcheck : 202 6468us < X-Okapi-Trace: GET mod-ncip-1.1.1 http://10.36.1.37:9179/ncipconfigcheck : 200 265768us < * Connection #0 to host folio-fameflower-okapi.dev.folio.org left intact OK
...elided... > Set-Cookie: token=foobarbaz; path=/; expires=Fri, 01 Jan 2021 00:00:00 GMT > X-Okapi-Tenant: diku > X-Okapi-Foo: bar > Content-Length: 779 > * upload completely sent off: 779 out of 779 bytes < HTTP/1.1 200 OK < Date: Thu, 23 Apr 2020 15:54:34 GMT < Content-Type: application/json < Transfer-Encoding: chunked < Connection: keep-alive < X-Okapi-Trace: POST mod-authtoken-2.4.0 http://10.36.1.37:9175/user-import : 202 7621us < X-Okapi-Trace: POST mod-user-import-3.2.0 http://10.36.1.37:9142/user-import : 200 899483us < { "message" : "Users were imported successfully.", "createdRecords" : 0, "updatedRecords" : 0, "failedRecords" : 1, "failedUsers" : [ { "username" : "jhandey", "externalSystemId" : "source1_111_112", "errorMessage" : "Failed to create new user with externalSystemId: source1_111_112" } ], "totalRecords" : 1 * Connection #0 to host folio-fameflower-okapi.dev.folio.org left intact } |
| Comment by Craig McNally [ 27/Apr/20 ] |
|
The only module I found that still had this issue in the fameflower release (mod-notify) has already been fixed. I verified this on folio-testing: ...elided... > set-cookie: token=foobarbaz; path=/; expires=Fri, 01 Jan 2021 00:00:00 GMT > X-Okapi-Tenant: diku > X-Okapi-foo: bar > < HTTP/1.1 200 OK < Date: Mon, 27 Apr 2020 12:28:15 GMT < Content-Type: application/json < Transfer-Encoding: chunked < Connection: keep-alive < X-Okapi-Trace: GET mod-authtoken-2.5.0-SNAPSHOT.66 http://10.36.1.210:9133/notify : 202 8019us < X-Okapi-Trace: GET mod-notify-2.6.0-SNAPSHOT.91 http://10.36.1.210:9143/notify : 200 261488us < { "notifications" : [ ], "totalRecords" : 0 * Connection #0 to host folio-testing-okapi.aws.indexdata.com left intact } |
| Comment by Hongwei Ji [ 27/Apr/20 ] |
|
Looks good. Just want to clear, for q2 release, are there any modules that need to upgrade RMB due to this header injection issue? |
| Comment by Craig McNally [ 28/Apr/20 ] |
|
The latest release of mod-notify is 2.5.0, which uses an older RMB (26.2.2). So yes, a mod-notify release will need to be made that includes a fix for this security issue. |
| Comment by Jakub Skoczen [ 04/May/20 ] |
|
Craig McNally Oleksii Petrenko The remaining problem in mod-notify has been fixed on the master branch, we need to make sure the module gets released for Goldenrod. |
| Comment by Oleksii Popov [ 05/May/20 ] |
|
What is left: ping release coordinator about module release. |