Skip to content

Commit

Permalink
manage encrypted chrome passwords
Browse files Browse the repository at this point in the history
  • Loading branch information
AlessandroZ committed Sep 16, 2019
1 parent a122f72 commit 72c5494
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 7 deletions.
4 changes: 2 additions & 2 deletions Linux/lazagne/config/constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class constant():
folder_name = 'results_{current_time}'.format(current_time=date)
file_name_results = 'credentials' # The extension is added depending on the user output choice
max_help = 27
CURRENT_VERSION = '1.4.2'
CURRENT_VERSION = '1.4.3'
output = None
file_logger = None
verbose = False
Expand All @@ -20,4 +20,4 @@ class constant():
quiet_mode = False
st = None # Standard output
modules_dic = {}

chrome_storage = None # Retrieved from libsecrets module
64 changes: 59 additions & 5 deletions Linux/lazagne/softwares/browsers/chrome.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import shutil
import sqlite3
import os
import struct
import traceback

from hashlib import pbkdf2_hmac

# For non-keyring storage
from lazagne.config.constant import constant
from lazagne.config.crypto.pyaes import AESModeOfOperationCBC
from lazagne.config.module_info import ModuleInfo
from lazagne.config import homes


class Chrome(ModuleInfo):
def __init__(self):
ModuleInfo.__init__(self, 'chrome', 'browsers')
self.enc_config = {
'iv': b' ' * 16,
'length': 16,
'salt': b'saltysalt',
'iterations': 1,
}
self.AES_BLOCK_SIZE = 16

def get_paths(self):
for profile_dir in homes.get(directory=[u'.config/google-chrome', u'.config/chromium']):
Expand All @@ -26,6 +38,28 @@ def get_paths(self):
if os.path.isfile(login_data):
yield login_data

def remove_padding(self, data):
"""
Remove PKCS#7 padding
"""
try:
nb = struct.unpack('B', data[-1])[0] # Python 2
except Exception:
nb = data[-1] # Python 3

try:
return data[:-nb]
except Exception:
self.debug(traceback.format_exc())
return data

def chrome_decrypt(self, encrypted_value, key, init_vector):
encrypted_value = encrypted_value[3:]
aes = AESModeOfOperationCBC(key, iv=init_vector)
cleartxt = b"".join([aes.decrypt(encrypted_value[i:i + self.AES_BLOCK_SIZE])
for i in range(0, len(encrypted_value), self.AES_BLOCK_SIZE)])
return self.remove_padding(cleartxt)

def get_passwords(self, path):
try:
conn = sqlite3.connect(path)
Expand All @@ -36,14 +70,34 @@ def get_passwords(self, path):
try:
cursor.execute('SELECT origin_url,username_value,password_value FROM logins')
for url, user, password in cursor:
if not user=="":
# Password encrypted on the database
if password[:3] == b'v10' or password[:3] == b'v11':

# To decrypt it, Chromium Safe Storage from libsecret module is needed
if not constant.chrome_storage:
self.info('Password encrypted and chrome secret storage not found')
continue

else:
try:
enc_key = pbkdf2_hmac(
hash_name='sha1',
password=constant.chrome_storage,
salt=self.enc_config['salt'],
iterations=self.enc_config['iterations'],
dklen=self.enc_config['length'])

password = self.chrome_decrypt(password, key=enc_key, init_vector=self.enc_config['iv'])
except Exception:
print(traceback.format_exc())
if user:
yield {
'URL': url,
'Login': user,
'Password': password
}
except Exception as e:
self.debug(e)
except Exception:
print(traceback.format_exc())

finally:
cursor.close()
Expand Down

0 comments on commit 72c5494

Please sign in to comment.