目錄
0. 前言
1.參考文獻
2.分析
3.流程
4.代碼
4.1 代碼結(jié)構
4.2 aesgcm.py
4.3 chromeCookieJar.py
4.4 decrypt.py
4.5 main.py
5.結(jié)果
0. 前言
上篇博客寫了用scrapy去爬取微博的評論,里面說到了不帶cookie值去爬,微博可能會把你當成游客,無法正確爬取數(shù)據(jù)
Cookie(百度百科):Cookie,有時也用其復數(shù)形式 Cookies。類型為“小型文本文件”,是某些網(wǎng)站為了辨別用戶身份,進行Session跟蹤而儲存在用戶本地終端上的數(shù)據(jù)(通常經(jīng)過加密),由用戶客戶端計算機暫時或永久保存的信息
其實就是帶cookie發(fā)起請求,讓服務器識別到你的身份,這樣他就不會當成游客處理了
本來之前一直很反感微博亂點贊,亂關注別人這樣的現(xiàn)象
沒想到,在寫完博客之后,這樣的情況再次又雙叕降臨到了我自己頭上,好家伙我直接好家伙
本來想著忍他幾天,結(jié)果幾天之后還是在給奇怪的人點贊,氣的我直接給他來了一手改密碼,成功制止了這樣的現(xiàn)象繼續(xù)發(fā)生
1.參考文獻
首先參考文獻寫在前面,表示尊重
其次,在這次之前,本人對于算法這一類的東西是十分頭疼的,經(jīng)過這一次學習之后,其實也是知其然而不知其所以然,所以將更好、更有用的參考的鏈接放在前面,要是想學到更多的同學可以直接點擊鏈接學習
我的代碼主要參考Chrome 80.X版本如何解密Cookies文件
其實我只是簡化了他的代碼,刪除了一些我不需要用到的代碼,方便學習
原理類的文章可以看
滲透技巧——導出Chrome瀏覽器中保存的密碼
手把手用C++解密Chrome80版本數(shù)據(jù)庫
CSRF攻擊與防御(寫得非常好)
2.分析
我個人喜歡將這一類問題歸到CSRF下,
CSRF跨站點請求偽造(Cross—Site Request Forgery),跟XSS攻擊一樣,存在巨大的危害性,你可以這樣來理解:攻擊者盜用了你的身份,以你的名義發(fā)送惡意請求,對服務器來說這個請求是完全合法的,但是卻完成了攻擊者所期望的一個操作,比如以你的名義發(fā)送郵件、發(fā)消息,盜取你的賬號,添加系統(tǒng)管理員,甚至于購買商品、虛擬貨幣轉(zhuǎn)賬等
實際上歸屬于哪一類的問題還得看大家是怎么定義的
這一篇文章不打算具體分析是怎么完成攻擊的
因為在試圖溯源的時候,看了有沒有可疑進程在后臺運行,沒有發(fā)現(xiàn)
然后想起了這臺電腦一開始chrome瀏覽器首頁都是一些奇怪的360導航之類的,恢復正常之后,不記得怎么讓他打開這些導航了,這樣就不好復現(xiàn)了
但是個人猜測可能是由于這些惡意程序造成的,可能加載了一些惡意dll啊、或者啟動了一些與惡意服務器通訊的后門,獲取了瀏覽器保存的cookie值
然后拿去給別人點贊
這里就不多猜測了
所以本文主要學習、記錄的內(nèi)容是,假如別人獲得了保存在你本地的cookie文件的內(nèi)容,怎么解密還原出cookie值,并加以利用
3.流程
chrome本地cookie以sqlite的形式保存,用Navicat查看是這樣的
其中encrypted_value就是加密后的值
分析一下chrome保存的cookie的加解密流程,結(jié)合文獻和代碼來看
首先在今年(2020年)更新之前,chrome的cookie可以通過dpapi直接解密
今年改版更新之后的解密流程:
以上截圖引用來自參考文獻中
關于詳細的算法說明我沒有找到詳細的文章,有興趣的同學也許可以查找一下源碼,進一步學習
4.代碼
4.1 代碼結(jié)構
4.2 aesgcm.py
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.ciphers import ( Cipher, algorithms, modes def encrypt(cipher, plaintext, nonce): cipher.mode = modes.GCM(nonce) encryptor = cipher.encryptor() ciphertext = encryptor.update(plaintext) return (cipher, ciphertext, nonce) def decrypt(cipher, ciphertext, nonce): cipher.mode = modes.GCM(nonce) decryptor = cipher.decryptor() return decryptor.update(ciphertext) backend=default_backend()
4.3 chromeCookieJar.py
import http.cookiejar as cookiejar from decrypt import chrome_decrypt from decrypt import to_epoch class chromeCookieJar(cookiejar.FileCookieJar): def __init__(self, fileName=None, delayload=False, policy=None): os.environ['USERPROFILE'], r'AppData\Local\Google\Chrome\User Data\default\Cookies') if not os.path.exists(fileName): cookiejar.FileCookieJar.__init__(self, fileName, delayload, policy) def printCookie(self, name, value, host, path): print(name + '\t' + value + '\t' + host + '\t' + path + '\t') # ignore_discard: save even cookies set to be discarded. # ignore_expires: save even cookies that have expired.The file is overwritten if it already exists def _really_load(self, f, filename, ignore_discard, ignore_expires): con = sqlite3.connect(filename) con.row_factory = sqlite3.Row con.create_function('decrypt', 1, chrome_decrypt) con.create_function('to_epoch', 1, to_epoch) # 這個sql我只查了weibo相關的,如果有其他需要可以修改 host_key, name, path,encrypted_value as value where host_key like '%weibo%' if row['value'] is not None: value = str(chrome_decrypt(row['value'])) host = str(row['host_key']) self.printCookie(name, value, host, path)
4.4 decrypt.py
def get_key_from_local_state(): with open(os.path.join(os.environ['LOCALAPPDATA'], r"Google\Chrome\User Data\Local State"), encoding='utf-8', mode="r") as f: jsn = json.loads(str(f.readline())) return jsn["os_crypt"]["encrypted_key"] def dpapi_decrypt(encrypted): from ctypes import wintypes class DATA_BLOB(ctypes.Structure): _fields_ = [('cbData', wintypes.DWORD), ('pbData', ctypes.POINTER(ctypes.c_char))] p = ctypes.create_string_buffer(encrypted, len(encrypted)) blobin = DATA_BLOB(ctypes.sizeof(p), p) retval = ctypes.windll.crypt32.CryptUnprotectData( ctypes.byref(blobin), # pDataIn 輸入,一個指向存有加密內(nèi)容DATA_BLOB的指針, None, # pvReversed 這個保留參數(shù)must be set to NULL 0, # dwFlags 一個DWORD值指定此函數(shù)特定的選項 ctypes.byref(blobout) # 輸出 result = ctypes.string_at(blobout.pbData, blobout.cbData) ctypes.windll.kernel32.LocalFree(blobout.pbData) def aes_decrypt(encrypted_txt): encode_key = get_key_from_local_state() encrypted_key = base64.b64decode(encode_key.encode()) encrypted_key = encrypted_key[5:] key = dpapi_decrypt(encrypted_key) nonce = encrypted_txt[3:15] #關于aesgcm加密算法,沒有找到合適詳細的文章 cipher = aesgcm.get_cipher(key) return aesgcm.decrypt(cipher, encrypted_txt[15:], nonce) def chrome_decrypt(encrypted_txt): if encrypted_txt[:3] == b'v10': decrypted_txt = aes_decrypt(encrypted_txt) return decrypted_txt[:-16].decode() print("chrome_decrypt error :" + e) return chrome_ts - 11644473600 * 000 * 1000
4.5 main.py
from chromeCookieJar import chromeCookieJar if __name__ == '__main__':
5.結(jié)果
經(jīng)過對比,結(jié)果一致
|