Coordinated Disclosure Timeline

Summary

Multiple reflected XSS vulnerabilities exist in the registration and login forms of habitica, giving the attacker control of the victim’s account when a victim registers or logins with a specially crafted link.

Project

habitica

Tested Version

v5.25.2

Details

Issue 1: Reflected XSS in /login (GHSL-2024-109)

The login and social media function in RegisterLoginReset.vue contains two reflected XSS vulnerabilities due to an incorrect sanitization function. An attacker can specify a malicious redirectTo parameter to trigger the vulnerability.

Case 1:

async login () {
      await this.$store.dispatch('auth:login', {
        username: this.username,
        // email: this.email,
        password: this.password,
      });

      const redirectTo = this.sanitizeRedirect(this.$route.query.redirectTo);

      window.location.href = redirectTo;
}

Case 2:

 async socialAuth (network) {
      if (network === 'apple') {
        window.location.href = buildAppleAuthUrl();
      }

       const redirectTo = this.sanitizeRedirect(this.$route.query.redirectTo);

      window.location.href = redirectTo;

Impact

This issue may lead to XSS. An attacker may be able to access an victim’s account via their user id and api key.

Proof of Concept

An attacker can send the following link to a victim, who will login.

www.habitica.com/login?redirectTo=javascript(alert(localStorage['habit-mobile-settings']))

For sake of demonstration, the API key for the user will be displayed on an alert. Arbitrary javascript can be executed by the attacker in the context of the victim’s session.

Issue 2: Reflected XSS in /register (GHSL-2024-110)

The register function in RegisterLoginReset.vue contains a reflected XSS vulnerability due to an incorrect sanitization function. An attacker can specify a malicious redirectTo parameter to trigger the vulnerability.

async register () {
      // @TODO do not use alert
      if (!this.email) {
        window.alert(this.$t('missingEmail')); // eslint-disable-line no-alert
        return;
      }
      const redirectTo = this.sanitizeRedirect(this.$route.query.redirectTo);

      window.location.href = redirectTo;

Impact

This issue may lead to XSS. An attacker may be able to access a victim’s account via their user id and api key.

Resources

An attacker can send the following link to a victim, who will register.

www.habitica.com/register?redirectTo=javascript(alert(localStorage['habit-mobile-settings']))

For sake of demonstration, the API key for the user will be displayed on an alert. Arbitrary javascript can be executed by the attacker in the context of the victim’s session.

Issue 3: Reflected XSS in /home (GHSL-2024-111)

The register function in home.vue contains a reflected XSS vulnerability due to an incorrect sanitization function. An attacker can specify a malicious redirectTo parameter to trigger the vulnerability.

 // @TODO this is totally duplicate from the registerLogin component
    async register () {
      let groupInvite = '';
      window.location.href = this.$route.query.redirectTo || '/';

Impact

This issue may lead to XSS.

Proof of Concept

An attacker can send the following link to a victim, who will register.

www.habitica.com/static/home?redirectTo=javascript(alert(localStorage['habit-mobile-settings']))

For sake of demonstration, the API key for the user will be displayed on an alert. Arbitrary javascript can be executed by the attacker in the context of the victim’s session.

Credit

These issues were discovered and reported by GHSL team member @Kwstubbs (Kevin Stubbings).

Contact

You can contact the GHSL team at securitylab@github.com, please include a reference to GHSL-2024-109, GHSL-2024-110, or GHSL-2024-111 in any communication regarding these issues.