Is Free VPN For Chrome & Ad blocker - Planet VPN safe?
Free VPN For Chrome - Planet VPN resolves its backend API URL from a Telegraph dead-drop page on every startup, allowing the operator to silently redirect all traffic.
On each startup, the extension fetches a Telegraph page and decrypts its content using a hardcoded AES key to obtain the actual backend domain used for all API calls, including login, user data, and VPN network endpoints. Free-tier users also receive server-controlled interstitial ads that open arbitrary URLs as new browser tabs. The default fallback backend is sola55.online.
Who publishes itFREE VPN PLANET SRL - 11 other listings from the same operator, 2 of them carrying a finding
FREE VPN PLANET SRL - 11 other listings from the same operator, 2 of them carrying a finding
What this publisher told the store about itself, and the other listings that told it the same thing.
Same store account
11 other listings published from this account, 2.5M+ users between them. 2 of them carry a finding.
Shared hosts - 12 hostnames
Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Telegraph Dead-Drop Resolves Backend API via Hardcoded AES Key
On startup, the extension fetches an encrypted payload from a Telegraph page to pick a backend, decrypted with an AES key from hardcoded literals.
The operator controls the page; traffic redirects anytime; analysis found 5fvfofc9f.online.
You install the extension or restart your browser.
The extension fetches an encrypted payload from a Telegraph page and decrypts it using a hardcoded key to resolve which backend server to contact.
All subsequent API requests, login, VPN server list, user profile, and ad delivery, are directed to the domain resolved from this dead-drop rather than a domain owned by the extension publisher.
AES key assembly and Telegraph decrypt (background.js)
// Three string literals concatenated with '+' chars stripped produce the AES-256-CBC key
const of = () => {
const t = "C3g4V+nKy7r+iXc/p", // → 'C3g4VnKy7riXc/p'
e = "G5Gab+bMpwa+Dh940", // → 'G5GabbMpwaDh940'
s = "P82d+ulCj+zx72A=", // → 'P82dulCjzx72A='
i = "+",
r = u => u ? u.split(i).join("") : "",
_ = r(t),
o = r(e),
a = r(s);
return _ + o + a;
// returns: 'C3g4VnKy7riXc/pG5GabbMpwaDh940P82dulCjzx72A='
// Base64-decoded: 32 bytes → AES-256
};// Decrypts the Telegraph payload using the hardcoded key
const jr = t => {
try {
const e = of(), // retrieve hardcoded AES-256 key (Base64)
// t is Base64-encoded JSON string: { iv, value, mac, tag }
s = JSON.parse(je.enc.Base64.parse(t).toString(je.enc.Utf8)),
i = je.enc.Base64.parse(e), // key bytes
r = je.enc.Base64.parse(s.iv), // IV bytes
_ = je.AES.decrypt(s.value, i, { iv: r }).toString(je.enc.Utf8);
return JSON.parse(_);
// returns: { domain_api: '...', domain_gapi: '...', domain_cdn: '...' }
} catch (e) {
console.error("Error decrypting data:", e);
}
};Extracts the hardcoded AES-256-CBC key from the extension source, fetches the live Telegraph dead-drop page, and decrypts the payload to reveal the current backend API domain.
#!/usr/bin/env node
/**
* Reproducer for claim 14289 — Planet VPN (hipncndjamdcmphkgngojegjblibadbe v2.5.0)
* CWE-506: Backend API URL resolved via Telegraph dead-drop with hardcoded AES-CBC key
*
* Source: background.js (deobfuscated) lines 8777-8846
*
* The extension assembles an AES-256-CBC key from three hardcoded string literals,
* strips the '+' characters to produce a Base64 key, then uses it to decrypt
* content fetched from a Telegraph page (dead-drop resolver).
*
* Usage:
* node planet-vpn-telegraph-decrypt.js
*
* Expected output: JSON with domain_api, domain_gapi, domain_cdn fields showing
* the operator-controlled backend API domain.
*/
const https = require('https');
const crypto = require('crypto');
// Step 1: Reconstruct AES key from deobfuscated/background.js:8778-8786
// of() function: strips '+' from each part, concatenates
const t = 'C3g4V+nKy7r+iXc/p'; // background.js:8778
const e = 'G5Gab+bMpwa+Dh940'; // background.js:8779
const s = 'P82d+ulCj+zx72A='; // background.js:8780
const stripPlus = u => (u ? u.split('+').join('') : '');
const aesKeyB64 = stripPlus(t) + stripPlus(e) + stripPlus(s);
// aesKeyB64 = 'C3g4VnKy7riXc/pG5GabbMpwaDh940P82dulCjzx72A='
console.log('=== Hardcoded AES-256-CBC Key (Base64) ===');
console.log(aesKeyB64);
const aesKey = Buffer.from(aesKeyB64, 'base64');
console.log('Key length:', aesKey.length, 'bytes (AES-256)');
console.log('Key hex:', aesKey.toString('hex'));
console.log('');
// Step 2: Fetch Telegraph dead-drop page (background.js:1687)
const telegraphUrl = 'https://api.telegra.ph/getPage/E-04-01-3?return_content=true';
console.log('=== Fetching Telegraph dead-drop ===');
console.log('URL:', telegraphUrl);
https.get(telegraphUrl, res => {
let data = '';
res.on('data', chunk => (data += chunk));
res.on('end', () => {
const json = JSON.parse(data);
// Extract content[0].children[0] per background.js:8818
const encryptedB64 = json.result.content[0].children[0];
console.log('Encrypted payload (first 80 chars):', encryptedB64.substring(0, 80) + '...');
console.log('');
// Step 3: Decrypt per jr() at background.js:8788-8800
// Inner envelope: Base64-decode -> parse JSON -> {iv, value}
const envelope = JSON.parse(Buffer.from(encryptedB64, 'base64').toString('utf8'));
const iv = Buffer.from(envelope.iv, 'base64');
const ciphertext = Buffer.from(envelope.value, 'base64');
const decipher = crypto.createDecipheriv('aes-256-cbc', aesKey, iv);
const decrypted = Buffer.concat([
decipher.update(ciphertext),
decipher.final(),
]).toString('utf8');
console.log('=== Decrypted Backend Configuration ===');
const config = JSON.parse(decrypted);
console.log(JSON.stringify(config, null, 2));
console.log('');
console.log('RESULT: Operator can rotate all API traffic by updating the Telegraph page.');
console.log('Current active domain_api:', config.domain_api);
});
}).on('error', err => {
console.error('Request failed:', err.message);
});
- 1node planet-vpn-telegraph-decrypt.js
- api.telegra.ph
Dead-drop storing the encrypted backend domain. Operated by Telegraph (a Telegram project); the extension operator controls what's published, redirecting all API traffic instantly.
- 5fvfofc9f.online
Active backend domain resolved from the dead-drop at analysis time. Used for /login, /v3/user, /v2/network/data/extensive, /ads-interstitial, /device-token/add.
- sola55.online
Hardcoded fallback API domain (background.js:8802) used when the Telegraph fetch fails or the decrypted domain fails a reachability check.
- gapi.sola55.online
Hardcoded fallback general-API domain (background.js:8803) used alongside sola55.online when the Telegraph fetch fails.
What it can do
Permissions this extension asks for, as declared in version 2.5.0. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to. The current listed version is 3.8.1, which we have not unpacked yet.
Read and change your data on every site you visit
<all_urls> and 1 more
Read and change your data on every secure site you visit
https://*/*
Route all of your browsing through a server of its choosing
proxy
Store data in your browser
storage
Store an unlimited amount of data in your browser
unlimitedStorage
Read and change your full browsing history
history
Watch every request your browser makes
webRequest
Block and redirect the requests your browser makes
declarativeNetRequest
See which of your requests its blocking rules matched
declarativeNetRequestFeedback
See the address and title of every tab you have open
tabs
Change your browser's privacy and security settings
privacy
See, disable and uninstall your other extensions, including your security ones
management
Run its own code inside the pages you visit
scripting
Run hidden pages in the background
offscreen
Show you desktop notifications
notifications
Where it sends data
Destinations our analysis observed Free VPN For Chrome & Ad blocker - Planet VPN contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.
- api.telegra.ph
Free VPN For Chrome & Ad blocker - Planet VPN sends data to api.telegra.ph. 5 other extensions we have analysed send data here.
- s3.amazonaws.com
Free VPN For Chrome & Ad blocker - Planet VPN sends data to s3.amazonaws.com. One other extension we have analysed sends data here.
- cdn.freevpnplanet.com
Free VPN For Chrome & Ad blocker - Planet VPN sends data to cdn.freevpnplanet.com. No other extension we have analysed sends data here.
- gapi.sola55.online
Free VPN For Chrome & Ad blocker - Planet VPN sends data to gapi.sola55.online. No other extension we have analysed sends data here.
- sola55.online
Free VPN For Chrome & Ad blocker - Planet VPN sends data to sola55.online. No other extension we have analysed sends data here.