Versuchen Sie, das in Chrome gespeicherte Passwort zu knacken Versuchen Sie, die in IE / Edge gespeicherten Anmeldedaten auszugeben Dieses Mal habe ich versucht herauszufinden, wie Firefox die Anmeldedaten der Website speichert.
Nach einigen Recherchen stellte ich fest, dass Firefox eine Bibliothek namens NSS (Network Security Services) verwendet, um Benutzernamen und Kennwörter zu verschlüsseln, Base64-zu codieren und im Profilordner logins.json zu speichern.
Profil ist Benutzerordner \ AppData \ Roaming \ Mozilla \ Firefox \ Profiles Es wird für jeden Ordner in verwaltet. Außerdem wird die NSS-Bibliothek in dem Ordner gespeichert, in dem Firefox installiert ist \ nss3.dll.
Implementieren wir ein Programm, das Anmeldedaten liest. Früher habe ich C # verwendet, aber diesmal hat es nicht funktioniert, also werde ich Python verwenden.
Laden Sie zunächst die für die Entschlüsselung erforderliche NSS-Bibliothek. Die PK11SlotInfo-Struktur ist undurchsichtig und daher sind keine Mitglieder definiert.
#DLL wird geladen
dllpath = os.path.join(os.environ["programfiles"], "Mozilla Firefox\\nss3.dll")
nss3 = ct.CDLL(dllpath)
#Ladefunktion
def getfunc(restype, name, *argtypes):
res = getattr(nss3, name)
res.restype = restype
res.argtypes = argtypes
return res
class SECItem(ct.Structure):
_fields_ = [
('type', ct.c_uint),
('data', ct.c_char_p),
('len', ct.c_uint),
]
class PK11SlotInfo(ct.Structure):
#Undurchsichtige Struktur
pass
SlotInfoPtr = ct.POINTER(PK11SlotInfo)
SECItemPtr = ct.POINTER(SECItem)
NSS_Init = getfunc(ct.c_int, "NSS_Init", ct.c_char_p)
NSS_Shutdown = getfunc(ct.c_int, "NSS_Shutdown")
PK11_GetInternalKeySlot = getfunc(SlotInfoPtr, "PK11_GetInternalKeySlot")
PK11_FreeSlot = getfunc(None, "PK11_FreeSlot", SlotInfoPtr)
PK11_CheckUserPassword = getfunc(ct.c_int, "PK11_CheckUserPassword", SlotInfoPtr, ct.c_char_p)
PK11SDR_Decrypt = getfunc(ct.c_int, "PK11SDR_Decrypt", SECItemPtr, SECItemPtr, ct.c_void_p)
SECITEM_ZfreeItem = getfunc(None, "SECITEM_ZfreeItem", SECItemPtr, ct.c_int)
Zählen Sie dann die auf Ihrem Computer gespeicherten Profile auf und extrahieren Sie nur die Profile, die Anmeldedaten enthalten (wobei sich logins.json befindet).
#Profile aufzählen
def getprofiles():
profdir = os.path.join(os.environ["appdata"], "Mozilla\\Firefox\\Profiles")
files = os.listdir(profdir)
profiles = [os.path.join(profdir, f) for f in files if os.path.isfile(os.path.join(profdir, f, "logins.json"))]
return profiles
Wählen Sie ein Profil aus und initialisieren Sie NSS mit diesem Profil.
profiles = getprofiles()
print("Bitte geben Sie die Profilnummer ein.")
for i in range(len(profiles)):
print("%d: %s" % (i, profiles[i]))
number = int(input("Nummer: "))
encprof = profiles[number].encode("utf8")
#NSS-Initialisierung
e = NSS_Init(b"sql:" + encprof)
if e != 0:
raise Exception("NSS konnte nicht initialisiert werden.")
Mit Firefox können Sie ein Hauptkennwort in Ihrem Profil festlegen, um Ihre persönlichen Daten zu schützen. Wenn ein Hauptkennwort festgelegt wurde, müssen Sie sich mit der Funktion PK11_CheckUserPassword authentifizieren.
keyslot = PK11_GetInternalKeySlot()
if not keyslot:
raise Exception("Keyslot konnte nicht abgerufen werden.")
askpass = input("Bitte geben Sie das Master-Passwort ein: ")
if askpass:
e = PK11_CheckUserPassword(keyslot, askpass.encode("utf8"))
if e != 0:
raise Exception("Das Master-Passwort ist falsch.")
else:
print("Kein Passwort")
PK11_FreeSlot(keyslot)
Laden Sie dann logins.json. Obwohl erheblich weggelassen, ist die Struktur von logins.json wie folgt.
{
"logins": [
{
"hostname": "https://id.unity.com",
"encryptedUsername": "Verschlüsselter Benutzername 1",
"encryptedPassword": "Verschlüsseltes Passwort 1",
"encType": 1
},
{
"hostname": "https://accounts.google.com",
"encryptedUsername": "Verschlüsselter Benutzername 2",
"encryptedPassword": "Verschlüsseltes Passwort 2",
"encType": 1
},
]
}
Laden Sie logins.json und
def getcreds(profile):
db = os.path.join(profile, "logins.json")
with open(db) as fh:
data = json.load(fh)
try:
logins = data["logins"]
except Exception:
raise Exception("{0}Kann nicht gelesen werden.".format(db))
for i in logins:
yield (i["hostname"], i["encryptedUsername"],
i["encryptedPassword"], i["encType"])
Entschlüsseln und zeigen Sie es schließlich an und schließen Sie NSS.
for url, user, passw, enctype in getcreds(profiles[number]):
if enctype:
user = decode(user)
passw = decode(passw)
print("Url: " + url)
print("Username: " + user)
print("Password: " + passw)
NSS_Shutdown()
Der Inhalt der wesentlichen Decodierungsfunktionsdecodierung ist wie folgt.
def decode(data64):
data = b64decode(data64)
inp = SECItem(0, data, len(data))
out = SECItem(0, None, 0)
e = PK11SDR_Decrypt(inp, out, None)
try:
if e == -1:
print("Entschlüsselung fehlgeschlagen.")
exit()
res = ct.string_at(out.data, out.len).decode("utf8")
finally:
#Geben Sie SECItem frei
SECITEM_ZfreeItem(out, 0)
return res
Fügen Sie die Base64-decodierten Daten in die SECItem-Struktur ein und übergeben Sie sie an die Funktion PK11SDR_Decrypt. Die entschlüsselten Daten werden zurückgegeben.
Das Programm, das Firefox-Anmeldedaten ausgibt, lautet wie folgt.
import ctypes as ct
import os
import json
from base64 import b64decode
#DLL wird geladen
dllpath = os.path.join(os.environ["programfiles"], "Mozilla Firefox\\nss3.dll")
nss3 = ct.CDLL(dllpath)
#Funktionslast
def getfunc(restype, name, *argtypes):
res = getattr(nss3, name)
res.restype = restype
res.argtypes = argtypes
return res
class SECItem(ct.Structure):
_fields_ = [
('type', ct.c_uint),
('data', ct.c_char_p),
('len', ct.c_uint),
]
class PK11SlotInfo(ct.Structure):
#Undurchsichtige Struktur
pass
SlotInfoPtr = ct.POINTER(PK11SlotInfo)
SECItemPtr = ct.POINTER(SECItem)
NSS_Init = getfunc(ct.c_int, "NSS_Init", ct.c_char_p)
NSS_Shutdown = getfunc(ct.c_int, "NSS_Shutdown")
PK11_GetInternalKeySlot = getfunc(SlotInfoPtr, "PK11_GetInternalKeySlot")
PK11_FreeSlot = getfunc(None, "PK11_FreeSlot", SlotInfoPtr)
PK11_CheckUserPassword = getfunc(ct.c_int, "PK11_CheckUserPassword", SlotInfoPtr, ct.c_char_p)
PK11SDR_Decrypt = getfunc(ct.c_int, "PK11SDR_Decrypt", SECItemPtr, SECItemPtr, ct.c_void_p)
SECITEM_ZfreeItem = getfunc(None, "SECITEM_ZfreeItem", SECItemPtr, ct.c_int)
#Entschlüsselungsprozess
def decode(data64):
data = b64decode(data64)
inp = SECItem(0, data, len(data))
out = SECItem(0, None, 0)
e = PK11SDR_Decrypt(inp, out, None)
try:
if e == -1:
print("Entschlüsselung fehlgeschlagen.")
exit()
res = ct.string_at(out.data, out.len).decode("utf8")
finally:
#Geben Sie SECItem frei
SECITEM_ZfreeItem(out, 0)
return res
#Profile aufzählen
def getprofiles():
profdir = os.path.join(os.environ["appdata"], "Mozilla\\Firefox\\Profiles")
files = os.listdir(profdir)
profiles = [os.path.join(profdir, f) for f in files if os.path.isfile(os.path.join(profdir, f, "logins.json"))]
return profiles
#Json wird geladen
def getcreds(profile):
db = os.path.join(profile, "logins.json")
with open(db) as fh:
data = json.load(fh)
try:
logins = data["logins"]
except Exception:
raise Exception("{0}Kann nicht gelesen werden.".format(db))
for i in logins:
yield (i["hostname"], i["encryptedUsername"],
i["encryptedPassword"], i["encType"])
def main():
profiles = getprofiles()
print("Bitte geben Sie die Profilnummer ein.")
for i in range(len(profiles)):
print("%d: %s" % (i, profiles[i]))
number = int(input("Nummer: "))
#NSS-Initialisierung
encprof = profiles[number].encode("utf8")
e = NSS_Init(b"sql:" + encprof)
if e != 0:
raise Exception("NSS konnte nicht initialisiert werden.")
#Passwortauthentifizierung
keyslot = PK11_GetInternalKeySlot()
if not keyslot:
raise Exception("Keyslot konnte nicht abgerufen werden.")
askpass = input("Bitte geben Sie das Master-Passwort ein: ")
if askpass:
e = PK11_CheckUserPassword(keyslot, askpass.encode("utf8"))
if e != 0:
raise Exception("Das Master-Passwort ist falsch.")
else:
print("Kein Passwort")
PK11_FreeSlot(keyslot)
#Entschlüsseln und ausgeben
for url, user, passw, enctype in getcreds(profiles[number]):
if enctype:
user = decode(user)
passw = decode(passw)
print("Url: " + url)
print("Username: " + user)
print("Password: " + passw)
NSS_Shutdown()
main()
Lassen Sie uns nun das Programm ausführen.
Wenn Sie es ausführen, werden Sie aufgefordert, das Profil zu laden. Geben Sie also diese Nummer ein.
Bitte geben Sie die Profilnummer ein.
0: C:\Users\admin\AppData\Roaming\Mozilla\Firefox\Profiles\aaaaaaaa.TestProfile
1: C:\Users\admin\AppData\Roaming\Mozilla\Firefox\Profiles\bbbbbbbb.default-release
Nummer:
Geben Sie dann das Master-Passwort ein. Wenn es nicht eingestellt ist, drücken Sie einfach die Eingabetaste.
Bitte geben Sie das Master-Passwort ein:
Dann werden die Anmeldedaten ausgegeben.
Url: https://id.unity.com
Username: admin
Password: SecurePass9999
Url: https://accounts.google.com
Username: [email protected]
Password: passwd314159
Also habe ich diesmal versucht, die Anmeldedaten von Firefox zu analysieren. Es scheint einfacher zu sein als Chrome oder Edge / IE, aber ich denke, das Festlegen eines Hauptkennworts bietet Ihnen eine höhere Sicherheit als jeder andere Browser.
Derzeit scheint es keine Möglichkeit zu geben, das Hauptkennwort direkt zu knacken. Zusammenfassend scheint es daher am sichersten zu sein, das Hauptkennwort in Firefox festzulegen und zu verwenden.
Der folgende Code ist der Code, den ich versucht habe, in C # zu implementieren.
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;
using Newtonsoft.Json;
namespace FirefoxDecrypt
{
struct SECItem
{
public uint type;
public byte[] data;
public uint len;
}
public class Logins
{
public Credential[] logins { get; set; }
}
public class Credential
{
public string hostname { get; set; }
public string encryptedUsername { get; set; }
public string encryptedPassword { get; set; }
public int encType { get; set; }
}
class Program
{
const string nss = "C:\\Program Files\\Mozilla Firefox\\nss3.dll";
const string profile = "C:\\Users\\user01\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\xxxxxxxx.default-release";
[DllImport(nss)]
static extern int NSS_Init(string s);
[DllImport(nss)]
static extern int NSS_Shutdown();
[DllImport(nss)]
static extern int PK11SDR_Decrypt(ref SECItem s1, ref SECItem s2, IntPtr ptr);
[DllImport(nss)]
static extern void SECITEM_ZfreeItem(ref SECItem s, int i);
static void Main(string[] args)
{
int e = NSS_Init("sql:" + profile);
Console.WriteLine("NSS_Init: " + e);
string db = Path.Combine(profile, "logins.json");
string v = File.ReadAllText(db);
var data = JsonConvert.DeserializeObject<Logins>(v);
foreach(var login in data.logins)
{
if(login.encType == 1)
{
var user = Decode(login.encryptedUsername);
var pass = Decode(login.encryptedPassword);
Console.WriteLine("URL: " + login.hostname);
Console.WriteLine("Username: " + user);
Console.WriteLine("Password: " + pass);
}
}
NSS_Shutdown();
Console.ReadKey(true);
}
static string Decode(string b64)
{
var bin = Convert.FromBase64String(b64);
//Vielleicht gibt es hier ein Problem
SECItem inp = new SECItem { data = bin, len = (uint)bin.Length, type = 0 };
SECItem outs = new SECItem { data = null, len = 0, type = 0 };
var e = PK11SDR_Decrypt(ref inp, ref outs, IntPtr.Zero);
Console.WriteLine("PK11SDR_Decrypt: " + e);
var res = Encoding.UTF8.GetString(outs.data);
SECITEM_ZfreeItem(ref outs, 0);
return res;
}
}
}
Es sollte fast genauso verarbeitet werden wie die Python-Version, aber wenn ich PK11SDR_Decrypt der Decode-Methode aufrufe, wird zwangsläufig der Fehlercode -1 zurückgegeben. Es gab kein Problem mit den Base64-decodierten Daten, daher denke ich, dass es ein Problem mit der SECItem-Struktur gibt, aber am Ende habe ich aufgegeben, ohne die Ursache zu kennen. Wenn jemand die Ursache kennt, lass es mich bitte in den Kommentaren wissen. ~~ Ist es nicht im Stein ... ~~
Recommended Posts