Retourner au contenu associé (journal : J'ai failli le faire)
Posté par sputnick (site web personnel, Mastodon) le 25 novembre 2025 à 12:23. En réponse au journal J'ai failli le faire. Évalué à 10.
C'est un sujet que j’essaye de traiter/implémenter en ce moment en utilisant un script Python.
A la fin, j'obtiens une note de 0 à 100.
0 est fiable selon mes critères, non zéro, il faut se poser des questions.
Le script:
#!/usr/bin/env python3 import zipfile import json import re import os import sys from collections import defaultdict # ----------------------------------------- # YARA-like malicious patterns # ----------------------------------------- yara_rules = { "eval_obfuscation": r"eval\s*\(", "function_constructor": r"new Function\s*\(", "xhr_suspicious": r"XMLHttpRequest\s*\(", "websocket": r"new WebSocket\s*\(", "crypto_mining": r"(CoinHive|cryptonight|miner)", "tracking_fingerprinting": r"(canvas\.toDataURL|audioContext|mediaDevices\.enumerateDevices)", "url_beacon": r"(navigator\.sendBeacon)", "shadow_dom_injection": r"(attachShadow)", "encoded_payload": r"(atob\(|btoa\()", "exfiltration_fetch": r"fetch\s*\([^)]*(http|https):\/\/", "suspicious_iframe": r"<iframe[^>]+src=" } # ----------------------------------------- # Sensitive Firefox permissions → explanations # ----------------------------------------- permission_explanations = { "tabs": "Access to all browser tabs (privacy sensitive).", "cookies": "Can read/write cookies across sites.", "webRequest": "Can monitor/modify all network requests.", "webRequestBlocking": "Can block and alter network requests (highly sensitive).", "history": "Can read browsing history.", "downloads": "Full access to all downloads.", "nativeMessaging": "Can communicate with external apps (critical).", "management": "Can manage extensions (dangerous).", "proxy": "Can alter browser network proxy settings.", "storage": "Can store arbitrary data (may include tracking identifiers)." } # ----------------------------------------- # Known tracker domains for filtering endpoints # ----------------------------------------- TRACKERS = ["google-analytics", "doubleclick", "facebook", "fbcdn", "hotjar", "mixpanel", "matomo", "segment.io", "sentry", "amplitude", "snowplow"] # ----------------------------------------- # Utility functions # ----------------------------------------- def detect_minification(content): line_lengths = [len(line) for line in content.split("\n")] long_lines = sum(1 for l in line_lengths if l > 300) ratio = long_lines / max(1, len(line_lengths)) return ratio > 0.30 # heuristic def detect_obfuscation(content): suspicious = 0 if re.search(r"[A-Za-z_$]{1,2}\d{3,}", content): suspicious += 1 if re.search(r"function\(\w,\w,\w\)\{", content): suspicious += 1 if re.search(r"while\s*\(\!\!\[\]\)", content): suspicious += 1 return suspicious >= 2 def yara_scan(content): matches = [] for name, pattern in yara_rules.items(): if re.search(pattern, content, re.IGNORECASE): matches.append(name) return matches def extract_urls(content): pattern = r"https?://[A-Za-z0-9\.\-_/~\?#=%]+(?=[\s\"\'\)\]\}<>]|$)" return re.findall(pattern, content) def classify_urls(urls): classified = {"trackers": [], "api": [], "other": []} for u in urls: if any(t in u for t in TRACKERS): classified["trackers"].append(u) elif re.search(r"/api/|/v\d+/|token|auth", u): classified["api"].append(u) else: classified["other"].append(u) return classified # ----------------------------------------- # Compute global risk score # ----------------------------------------- def compute_risk_score(permissions, minified_files, obfuscated_files, yara_hits, urls): score = 0 # Permissions if "<all_urls>" in permissions: score += 25 if "webRequest" in permissions: score += 10 if "cookies" in permissions: score += 10 if "history" in permissions: score += 10 if "nativeMessaging" in permissions: score += 20 # File metrics score += len(minified_files) * 5 score += len(obfuscated_files) * 10 # YARA hits for hits in yara_hits.values(): score += len(hits) * 10 # URLs score += min(len(urls), 10) # up to 10 points # Cap at 100 return min(score, 100) # ----------------------------------------- # Main analysis # ----------------------------------------- def analyze_xpi(file_path): report = [] js_files = {} urls_found = set() yara_hits = defaultdict(list) minified_files = [] obfuscated_files = [] with zipfile.ZipFile(file_path, 'r') as z: # ------------------------- # 1. MANIFEST EXTRACTION # ------------------------- manifest_data = None for name in z.namelist(): if name.endswith("manifest.json"): manifest_data = json.loads(z.read(name).decode("utf-8", errors="ignore")) break if manifest_data is None: report.append("No manifest.json found → invalid extension.") return "\n".join(report) # ------------------------- # 2. Inspect manifest.json # ------------------------- report.append("=== MANIFEST ANALYSIS ===\n") # Permissions permissions = manifest_data.get("permissions", []) host_permissions = manifest_data.get("host_permissions", []) report.append("Permissions declared:") if not permissions: report.append(" None") else: for perm in permissions: explanation = permission_explanations.get(perm, "No specific risk info.") report.append(f" - {perm}: {explanation}") report.append("\nHost permissions:") if not host_permissions: report.append(" None") else: for host in host_permissions: report.append(f" - {host}") # Data collection declaration dcp = manifest_data.get("data_collection_permissions", {}) report.append("\nData collection permissions:") if dcp: report.append(f" Raw: {json.dumps(dcp, indent=4)}") if dcp.get("required") == ["none"]: report.append(" → The extension claims to collect NO DATA.") else: report.append(" No data collection declaration found.") report.append("\n") # ------------------------- # 3. FILE CONTENT ANALYSIS # ------------------------- report.append("=== FILE ANALYSIS ===\n") for name in z.namelist(): if not name.endswith((".js", ".html", ".css")): continue content = z.read(name).decode("utf-8", errors="ignore") # JS only if name.endswith(".js"): js_files[name] = content # Minification detection if detect_minification(content): minified_files.append(name) # Obfuscation detection if detect_obfuscation(content): obfuscated_files.append(name) # YARA-like scan for hit in yara_scan(content): yara_hits[name].append(hit) # URL extraction (JS/HTML/CSS) for url in extract_urls(content): urls_found.add(url) # Minified report.append("Potentially minified files:") if minified_files: for f in minified_files: report.append(f" - {f}") else: report.append(" None") report.append("") # Obfuscated report.append("Potentially obfuscated files:") if obfuscated_files: for f in obfuscated_files: report.append(f" - {f}") else: report.append(" None") report.append("") # YARA hits report.append("YARA-like detection results:") if yara_hits: for f, hits in yara_hits.items(): report.append(f" {f}: {', '.join(hits)}") else: report.append(" No suspicious patterns detected.") report.append("") # URLs classified = classify_urls(urls_found) report.append("External endpoints found:") for cat, urls in classified.items(): report.append(f" {cat.capitalize()}:") if urls: for u in urls: report.append(f" - {u}") else: report.append(" None") report.append("") # ------------------------- # 4. Global risk score # ------------------------- risk_score = compute_risk_score(permissions, minified_files, obfuscated_files, yara_hits, urls_found) report.append(f"=== GLOBAL RISK SCORE: {risk_score}/100 ===\n") # ------------------------- # 5. Final Privacy Warning # ------------------------- report.append("=== PRIVACY RECOMMENDATION ===") report.append( "Always disable automatic updates for extensions when conducting security reviews. " "Updates may replace safe code with unsafe content without user confirmation." ) return "\n".join(report) if __name__ == "__main__": if len(sys.argv) != 2: print("Usage: python3 audit_xpi.py extension.xpi") sys.exit(1) filePath = sys.argv[1] print(analyze_xpi(filePath))
Le report me donne pour tampermonkey:
=== MANIFEST ANALYSIS === Permissions declared: - alarms: No specific risk info. - notifications: No specific risk info. - tabs: Access to all browser tabs (privacy sensitive). - idle: No specific risk info. - webNavigation: No specific risk info. - webRequest: Can monitor/modify all network requests. - webRequestBlocking: Can block and alter network requests (highly sensitive). - unlimitedStorage: No specific risk info. - storage: Can store arbitrary data (may include tracking identifiers). - contextMenus: No specific risk info. - clipboardWrite: No specific risk info. - cookies: Can read/write cookies across sites. - downloads: Full access to all downloads. - <all_urls>: No specific risk info. Host permissions: None Data collection permissions: No data collection declaration found. === FILE ANALYSIS === Potentially minified files: - content.js - extension.js - page.js - editor.js - lint.js - cache.js - background.js - vendor/saveas/filesaver.js - vendor/eslint/eslint.js - vendor/jsdiff/diff.js Potentially obfuscated files: - content.js - extension.js - editor.js - background.js - vendor/eslint/eslint.js YARA-like detection results: content.js: shadow_dom_injection, encoded_payload extension.js: function_constructor, crypto_mining, suspicious_iframe background.js: eval_obfuscation, function_constructor, crypto_mining, encoded_payload vendor/eslint/eslint.js: eval_obfuscation, function_constructor, tracking_fingerprinting External endpoints found: Trackers: - https://www.facebook.com/tampermonkey - https://a.tampermonkey.net/matomo.php - https://www.facebook.com/groups/SocialFixerUsersSupport/ - https://www.facebook.com/fluffbustingpurity Api: - https://api.dropboxapi.com/2/auth/token/revoke - https://cloud-api.yandex.net/v1/disk/ - https://www.googleapis.com/drive/v3/changes/startPageToken - https://www.googleapis.com/auth/drive.appdata - https://oauth.yandex.com/authorize - https://login.live.com/oauth20_authorize.srf - https://www.googleapis.com/drive/v3/files? - https://www.googleapis.com/drive/v3/changes/? - https://accounts.google.com/o/oauth2/v2/auth - https://www.googleapis.com/drive/v3/files/ - https://www.dropbox.com/oauth2/authorize - https://accounts.tampermonkey.net/e/oauth2/v1 Other: - https://eslint.org/docs/rules/no-process-env [...] filtered tons of eslint URLs - http://coffeescript.org/browser-compiler/coffeescript.js - https://eslint.org/docs/rules/no-new-native-nonconstructor - https://www.tampermonkey.net/faq#Q406 - https://github.com/ajv-validator/ajv/blob/master/lib/definition_schema.js - https://greasyfork.org/scripts/ - https://eslint.org/docs/rules/prefer-spread - https://eslint.org/docs/rules/no-undef-init - http://xkcd.com/970/ - https://api.dropboxapi.com/2/files/delete - https://api.onedrive.com/v1.0/drive/special - https://forum.userstyles.org/post/discussion?Discussion/StyleID= - http://json-schema.org/draft-07/schema# - https://eslint.org/docs/rules/no-negated-condition - https://www.tampermonkey.net/privacy.php#extension - https://bitbucket.org/ - https://content.dropboxapi.com/2/files/upload - https://github.com/openstyles/stylus - http://feross.org - https://userstyles.org/styles/ - http://userscripts.com/ - https://eslint.org/docs/rules/indent - https://eslint.org/docs/rules/require-unicode-regexp - http://socialfixer.com - http://contactbyweb.com/userscripts-mirror - https://github.com/zloirock/core-js/blob/v3.27.2/LICENSE - https://github.com/mysticatea - https://github.com/zloirock/core-js - http://www.w3.org/1999/xhtml - http://userscripts-mirror.org/scripts/review/ - http://www.w3.org/1999/xlink - https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/data.json# - https://eslint.org/docs/rules/space-before-function-paren - https://github.com/eslint/doctrine - http://www.w3.org/2000/svg - http://tampermonkey.net/ - https://www.tampermonkey.net/bug - https://opencollective.com/eslint - https://github.com/narcolepticinsomniac - https://www.tampermonkey.net/faq.php#Q204 - https://www.instagram.com/der_jan_b/ - http://userscripts-mirror.org/scripts/show/ - https://www.googleapis.com/ - https://github.com/estools/esrecurse - https://www.google.com/s2/favicons - http://json-schema.org/draft-04/schema# - https://blacklist.tampermonkey.net/get.php - https://www.fbpurity.com/ - https://www.tampermonkey.net/faq.php#Q500 - http://tmnk.net/faq#Q208 - https://api.dropboxapi.com/2/files/list_folder - https://www.tampermonkey.net/privacy.php - https://www.tampermonkey.net/scripts.php - https://www.nczonline.net - https://eslint.org/docs/rules/no-multiple-empty-lines - https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.16.0/polyfill.js - https://www.tampermonkey.net/faq.php? - http://userscripts.org/ - https://icons.duckduckgo.com/ip2/ - https://github.com/estools/esrecurse.git - https://www.tampermonkey.net - http://json-schema.org/draft-07/schema - https://github.com/Constellation - https://gitlab.com/ - https://vscode.dev/?connectTo=tampermonkey - https://api.onedrive.com/v1.0/drive/items/ - https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.18.2/babel.js - http://github.com/garycourt/uri-js - https://github.com/derjanb - https://notify.dropboxapi.com/2/files/list_folder/longpoll - https://www.tampermonkey.net/documentation.php#_connect - https://sleazyfork.org/scripts/ - https://www.tampermonkey.net/qr/ - https://content.dropboxapi.com/2/files/download - https://www.tampermonkey.net/changelog.php? - https://openuserjs.org/scripts/ - https://webdav.yandex.ru - https://stuk.github.io/jszip/documentation/howto/read_zip.html - https://www.tampermonkey.net/contrib.php?embedded=2 - http://json-schema.org/schema - https://www.tampermonkey.net/installed.php? - https://www.tampermonkey.net/faq.php#Q207 === GLOBAL RISK SCORE: 100/100 === === PRIVACY RECOMMENDATION === Always disable automatic updates for extensions when conducting security reviews. Updates may replace safe code with unsafe content without user confirmation.
On ne peut pas mettre d'array dans le string...
AltStyle によって変換されたページ (->オリジナル) / アドレス: モード: デフォルト 音声ブラウザ ルビ付き 配色反転 文字拡大 モバイル
# audit
Posté par sputnick (site web personnel, Mastodon) . En réponse au journal J'ai failli le faire. Évalué à 10.
C'est un sujet que j’essaye de traiter/implémenter en ce moment en utilisant un script Python.
A la fin, j'obtiens une note de 0 à 100.
0 est fiable selon mes critères, non zéro, il faut se poser des questions.
Le script:
Le report me donne pour tampermonkey:
On ne peut pas mettre d'array dans le string...