Slack Web Hook Message Injection Advisory

Jun 5 2024

Slack integrations such as webhook APIs are often used to alert on user actions to internal teams. A vulnerability was noted when user supplied data containing a large amount of white space was included in a request to the Slack webhook API. By including enough white space in this data, the messages would be split and truncated. As a result, the malicious payload after the whitespace would appear as a standalone message from the Slack bot. An attacker could exploit this to forge messages containing Slack message markup to perform social engineering and other attacks if an integration, such as a website or other software, included unvalidated user input in the message to the Slack webhook.

The payload could include links and formatted mentions to users, and user groups such as @here and @channel within the context of the channel. The @channel mentions would also trigger an email notification for members of the channels. Further information about formatted text is available in the Slack documentation.

An attacker could exploit this vulnerability to perform social engineering attacks, by crafting a malicious message which appears to be sent from a legitimate source. Social engineering attacks performed using this vector are more likely to be successful due to leveraging the Slack platform to add legitimacy to the attack.

There were some constraints in the payloads an attacker could send:

  • Messages were only sent and displayed to a channel the chat bot was configured to access.
  • The @everyone mention appeared valid in the chat window, but it did not notify users in the general channel as was expected behaviour per the Slack documentation.
  • Specific users could be mentioned via the payload using the <@USERID> notation. Mentioning a user that was not part of the Slack bot’s channel did not add them to the chat or notify the user.

Note: other Slack integration methods were not tested, and it is not clear if they are affected by similar issues.

Exploitation

The following example API was created to demonstrate the Slack Web Hook Message Injection attack. The proof-of-concept API below accepts user input which is then used to create a Slack web hook call to post a message to a Slack channel.

The following code shows the example method which passes the user supplied input into the payload for the Slack web hook call:

@app.route('/signup', methods=['POST'])
def register_user():
url = 'https://hooks.slack.com/services/T...redacted...Y/H...redacted...q'
username = request.json['username']
password = request.json['password']
input = {"text": "A new user has been registered " + username}
payload = requests.post(url, json=input)
return "You have been registered"

An attacker could submit a POST request containing an injection payload in the username parameters. The malicious payload was included as part of the username value below, which gets passed into the message for the slack bot.

curl -X POST -H 'Content-Type: application/json' http://localhost:5000/signup -d "{\"username\":\"fooo $(printf ' %.0s' {1..4000}) <\!channel> :star: :star: Please fill out this mandatory staff survey <https://pulsesecurity.co.nz|Legit Survey> :star: :star:\", \"password\":\"blah\"}"

The amount of whitespace required depends on the message content which the attacker-controlled input is injected into. By setting this to a large value, such as 4000 space characters, knowledge of the underlying slack message structure is not required.

The demo API is configured so that once a user is successfully registered, the API sends a message to the Slack web hook to notify a Slack channel.

The following screenshot shows the injected message rendering in the Slack channel:

The following screenshot shows the notification email sent to all users currently in the channel:

Remediation

Slack webhook messages may be exploited by an attacker if included user input isn’t carefully validated and malicious message content rejected. At the date of publication, Slack documentation did not provide guidance on validating user input for message markup or additional controls to prevent this style of attack. As such, the responsibility for ensuring this vulnerability is addressed lies with the customers integrating with Slack. This vulnerability can be addressed by:

  • Ensure any data included in Slack messages is carefully validated and allows only the expected character sets.
  • In particular, the message length should be as restrictive as possible and Slack mentions and links should not be allowed.
  • Strip whitespace from messages to prevent the truncation of user input.
  • An allow-list of valid characters is preferred to a deny-list blocking Slack message markup characters.

Additional resources

Timeline

  • 06/03/2024: Initial slack contact
  • 06/03/2024: Slack requested disclosure via HackerOne - declined and asked for a security contact.
  • 07/03/2024: Advisory Sent to Slack Security Team.
  • 13/03/2024: Slack confirmed the advisory was with their internal team for review.
  • 19/03/2024: Slack advised the advisory was still with their internal team for review.
  • 22/03/2024: Slack requested disclosure via HackerOne - declined and asked for an advisory update
  • 25/03/2024: Slack requested disclosure via HackerOne - declined and asked for a direct contact in the security team
  • 27/03/2024: Advisory Sent to Slack Security Team.
  • 08/04/2024: Followed up with the Security Team, notifying them of the 30-day mark - no response.
  • 06/05/2024: Followed up with the Security Team, notifying them of the 60-day mark - no response.
  • 04/06/2024: The 90-day disclosure period ended.


Follow us on LinkedIn