Let's Hack a Parental Control App - How I Uncovered a Conspiracy
Background
To start this out I'd like to say parental control apps aka spyware, are some of the most malicious applications to exist. These apps are poorly written and you should never trust them to secure you, or your children's data. Would you believe me if I told you apps such as this are rarely used for parental control/monitoring? It's true! The actually audience for these apps are jealous partners and stalkers. For that reason moving forward I'll be referring to such apps as stalkerware.
Intro
I decided to target https://phonsee.com which after purchasing using a vulnerability to literally change the price turns out is just https://eyeszy.com. Funny enough, these companies and https://parentaler.com (which is seen referenced in the page source) are all subsidiaries of Fortunex Limited. This company seems to be part of some conspiracy that has a monopoly over the entire stalkerware market.
Testing Security
First, let's get access to something other than their landing page. This was extremely easy since Phonsee is vulnerable to IDOR. I was able to purchase a license for just 69 cents.. nice...
We can send a POST request with a discount
of up to 99 to endpoint /backend/get-checkout
and the server validates it. Then we can actually purchase it and well...
We have an Eyezy account with premium. If you remember from earlier these are are the same companies. The first thing I did was explore the dashboard and try to setup a device to monitor. I selected IOS and downloaded the Eyezy_setup.exe
to a virtual machine to examine. In Ghidra I can see just from searching through the strings it's indeed an installation wizard which will install to the C drive. Confirming this I install the application and see it a new directory Eyezy
in my C drive.
Visually I can tell it's a C# application right away. This means reversal will be simple with Dnspy
. The first thing that draws my attention are api keys:
if (this.AppState.AppBrand.ToLower() == "eyezy") {
this.AppState.AmplitudeApiKey = "2872c418988f2edc2172b32287a8c649";
return;
}
if (this.AppState.AppBrand.ToLower() == "mstar") {
this.AppState.AmplitudeApiKey = "9902da5576bd7f81dfcd05dcce8c21d9";
return;
}
if (this.AppState.AppBrand.ToLower() == "spynger") {
this.AppState.AmplitudeApiKey = "5fc821f6238efa3bd223e282420ccb7";
return;
}
this.AppState.AmplitudeApiKey = "9b29e1e272040be0053b1a0af59319cf";
These are for analytics and have no value without the additional private key. The reason I'm showing this is because it seems https://mspy.mobi and https://spynger.net are both in the conspiracy. At this point I believe every parental monitoring app is just run by the same people. Actually, Spynger is completely advertised as stalkerware. They're site says it's "Your Best Tool to Catch a Cheater".
Anyway, I found some endpoints while reverse engineering it:
/api/v1/dc/sync/{0}/action-log
/api/v1/auth/login
/api/v1/auth/refresh-token
/api/v1/auth/logout
/api/v1/dc/win-client-version-latest
/api/v1/dc/win-client-version-latest/download
/api/v1/dc/osx-client-version-latest
/api/v1/dc/osx-client-version-latest/download
/api/v1/dc/sync/{0}/sensor-configs
/api/v1/dc/sync/{0}/configs
/api/v1/dc/desktop-log/upload
/api/v1/dc/sync/{0}/add-device
/api/v1/dc/device/{0}
/api/v1/dc/sync/{0}/unlink-device
/api/v1/dc/sync/{0}/unlink
/api/v1/dc/device/{0}/init-backup
/api/v1/dc/device/{0}/sensor-backups
/api/v1/dc/sensor-backup/{0}/upload
/api/v1/dc/sync
/api/v1/dc/customer/syncs
/api/v1/customer/subscriptions
/api/doc
/api/health-check/liveness
/api/health-check/readiness
/api/v1/slots/{0}/upload/start
/api/v1/slots/{0}/upload/complete
/api/v1/slots/{0}/sensors/data
Next, I'd like to see the requests in action. To do this I'm going to route all the VMs traffic through burp proxy by listing on my host linux box and configuring it in Window's VM manual proxy settings.
There we go! The requests are being intercepted by burpsuite. Looking through them I can see they're matching what was expected from reversing the application. None of this looks very interesting to me...
Oh look, another bug of course. I took a peek at the /api/v1/auth/refresh-token
POST request, which takes a refresh token as refreshToken
in the body of the request and notice I could send the request multiple times and still get a new JWT & refresh token returned back.
REQUEST 1:
REQUEST 2:
Now we're looking at a Refresh Token Reuse Vulnerability. If an attacker obtains a refresh token, they can repeatedly use it to generate new JWTs, potentially gaining persistent access to the user’s account. I think it's safe to say security wasn't a top priority for the developer. I'm assuming more can be found, but I can't trigger any more requests to intercept without plugging in my phone (which I don't want to do for obvious reasons). I'll have to reverse the app deeper to see how the other endpoints are hit.
I will be making a part two which will include a deeper analysis on the app itself to see exactly what it's doing behind the scenes. If you get anything out of reading this it should be these stalkerware applications do not have your security in mind and should never be trusted.
Part Two
First I want to see the core functionality of how the requests are made and to do this I'll use dotPeek which will let me export the decompiled app into a Visual Studio project for easier analysis.
I created a reversed app that mimicked all the requests and played with them to see if anything interesting could be done. To make a long story short, a JWT had to be send with every request for the server to validate it and there aren't any secret keys of any sort. At this point I decided to take my attention off the desktop application and focus on the mobile one. I setup burpsuite proxy on my phone and started intercepting. Not to my surprise it's using Firebase, which is a popular Database as a Service (DBaaS) for mobile and web applications.
A common technique to use against applications using Firebase is to check for a misconfiguration in rules that could let a threat actor read/write. For this I'll need to download the apk for analysis using https://apkpure.com. There's a great python tool for this called apkscan which will try to leak all secrets from the apk. You can clone it from github here https://github.com/LucasFaudman/apkscan. Keep in mind it won't work with python 3.13 because it's importing re.TEMPLATE
which is depreciated. I created a pull request removing the import, hopefully it gets accepted. If you want to use python 3.13 you'll need to remove line 7 of secret_scanner.py
, or clone from my fork https://github.com/pwnengine/apkscan. I was not able to retrieve any secrets, but it's still a good tool to have in the arsenal. My attention was then directed to /v2/parent/accounts
which responds with all monitored devices data associated with the authToken
. This token is a not a standard JWT and has no session binding. It's 32 bits and could be another point of interest considering burp's sequencer found the entropy to be poor.
Here's the problem, I wanted to check to see if tokens could be reused after another is issued and send this request with an empty deviceToken
which crashed the server. Now, the app is completely unusable and I can't do much else. On the plus side this means there's a Denial of Service vulnerability here.
Part Three
It's the next day and the api still returns a 502. I'm assuming that sending the request to /v2/parent/login
without an empty deviceToken
field caused an exception that was uncaught. So, we successfully took down the stalkerware. This wasn't how I wanted to end this, but that's all I got so far. Never use these stalkerware applications!