hash函数是一类函数的统称,这类函数的输入是任意的二进制数据,输出是固定长度的二进制数据,这类函数具有如下特点:
单向性:由输入计算得到输出是简单迅速的,而由输出反推出输入在数学上讲是不可行的
碰撞约束:寻找到两个不同的输入,具有相同的输出是极为困难的
满足这些特点的函数均可称为hash函数。将某数据作为hash函数的输入,计算得到输出,习惯上将这一输出称为该数据的hash值。
hash函数的一大作用便是安全地存储密码,不直接保存密码(也就是不存储明文的密码),而是保存密码的hash值,验证时只需再次计算输入的密码的hash值,与保存的密码的hash值相比较便可得知密码是否正确。由于hash函数的单向性与碰撞约束的特点,攻击者即使拿到了密码的hash值,也难以知道密码本身。
攻击者拿到了密码的hash值,真的没有办法知道密码本身吗?当然不是,虽然由密码的hash值直接计算密码本身从数学上讲就是不可行的,但我们知道hash函数由输入计算得到输出是简单迅速的,大不了可以试嘛,人类可能设置的密码也就那些,一个一个地试,运气好还是可以试出来的。通过不断尝试获得hash值对应的输入的操作就被称做爆破。
基于这样的思路,hashcat应运而生,据说hashcat的诞生就是为了证明爆破hash是很简单的事。hashcat自称是世界上最快的hash爆破工具,它甚至支持GPU和FGPA,如果你有的话。
hashcat不仅速度快,而且专业支持两百多种hash函数,使用命令:
hashcat --help
可以看到hashcat支持的所有hash函数的列表,太多了我这里就不贴出来了。
Kali中默认安装了hashcat,可直接使用。但我的Kali安装在VirtualBox中,总觉得虚拟机会慢一些,所以想要在物理主机中使用hashcat。先到hashchat的官网下载hashcat,截止目前,最新版是v3.5.0,发布于2017.04.05,从更新日期可见hashchat是充满活力的。免去编译的麻烦,直接下载二进制包,只有2.7M,与动辄几十G的游戏相比是很小的。
下载完成后解压hashcat,看到有:
hashcat32.bin
hashcat32.exe
hashcat64.bin
hashcat64.exe
这样的文件,分别是32位和64位下的linux中和windows中的可执行文件,按自己电脑的情况选择其中之一即可。我选择的是hashcat64.bin,为漂亮起见,在~/.bashrc文件中添加一行:
alias hashcat='hashcat64.bin的路径'
保存后重新打开虚拟终端,使~/.bashrc文件生效,这样,无论在哪,直接输入hashcat命令就可以了,不用切换目录,也不用输入输入难看的“64.bin”,如下图所示。
好了,现在可以开始使用hashcat爆破各种hash了。
md5应该是最著名、使用最为广泛的hash函数之一了。先用Python生成几个md5值用于爆破,代码如下:
import hashlib passwords = ['123123', 'bond007', 'xxxxxx', '*H@&(NT*@BR#^'] for password in passwords: md5 = hashlib.md5() md5.update(password) print md5.hexdigest()
以上代码分别计算了四个字符串的hash值,输出的结果是:
4297f44b13955235245b2497399d7a93 cbdb7e2b1ed566ceb796af2df07205a3 dad3a37aa9d50688b5157698acfd7aee d77db958c179bbffae04b2b908b75c26
将输出结果保存在文件md5.hash中,一行一个hahs值。然后用hashcat爆破这几个hash值,命令如下:
hashcat -w 3 -a 0 -m 0 --remove -o md5.out md5.hash wordlist.dic
参数-w用于指定工作模式,共有四种,如下表所示:
N | Performance | Runtime | Power Consumption | Desktop Impact |
---|---|---|---|---|
1 | Low | 2 ms | Low | Minimal |
2 | Default | 12 ms | Economic | Noticeable |
3 | High | 96 ms | High | Unresponsive |
4 | Nightmare | 480 ms | Insane | Headless |
参数-a用于指定攻击模式,0的含义是直接地、连续的,也就是用密码字典爆破,-a的取值共有五种,如下表所示:
N | Mode |
---|---|
0 | Straight |
1 | Combination |
3 | Brute-force |
6 | Hybrid Wordlist + Mask |
7 | Hybrid Mask + Wordlist |
-m用于指定要爆破的hash值的hash函数,0表示hash函数是md5,其他取值如下表所示:
N | Name | Category |
---|---|---|
0 | MD5 | Raw Hash |
300 | MySQL4.1/MySQL5 | Database Server |
1000 | NTLM | Operating Systems |
1800 | sha512crypt $6$, SHA512 (Unix) | Operating Systems |
2611 | vBulletin < v3.8.5 | Forums, CMS, E-Commerce, Frameworks |
这张表太长了,我这里只展示本文中涉及到的几种hash函数,用参数–help可以看到全部。
参数–remove的含义是若成功爆破某hash值,就将该值从md5.hash中移除。
参数-o后接一个文件名,指出保存爆破结果的地方。
最后的两个参数md5.hash和wordlist.dic分别是待爆破的hash值和密码字典,hash值与密码字典都是一行一个。md5.hash中的内容已经由Python算,若你手头没有合适的密码字典,可以用命令:
wget -O wordlist.dic https://samsclass.info/123/proj10/500_passwords.txt
下载一个。现在完事具备,按下回车,结果华丽地报错:(
clGetPlatformIDs(): CL_PLATFORM_NOT_FOUND_KHR
大概是缺少什么运行环境,那就安装呗。我总共安装了这些东西:
sudo apt-get install gcc make p7zip-full git lsb-core wget http://registrationcenter-download.intel.com/akdlm/irc_nas/9019/opencl_runtime_16.1.1_x64_ubuntu_6.4.0.25.tgz tar -xvf opencl_runtime_16.1.1_x64_ubuntu_6.4.0.25.tgz cd opencl_runtime_16.1.1_x64_ubuntu_6.4.0.25 sudo ./install.sh
网速好的话一小会就安好了,第一条命令报错:
/sbin/ldconfig.real: /usr/lib/nvidia-375/libEGL.so.1 is not a symbolic link /sbin/ldconfig.real: /usr/lib32/nvidia-375/libEGL.so.1 is not a symbolic link
但是好像不影响什么,忽略掉好了。安装完这些后,再次按下回车,运行原本报错的命令,发现果然没有再次报错,且转瞬之间,便执行完毕。命令执行完毕后查看文件md5.hash和md5.out的内容,发现md5.hash中只剩一个hash,爆破成功的三个hash已经被转移到文件md5.out中,md5.out中是三个hash值及其原值,如下图所示:
Windows的登录密码的hash值保存在SAM文件中,SAM是“security account manager”的首字母缩写。通常,它位于
C:\windows\system32\config\SAM
SAM文件被Windows保护,不能直接读取,需借助工具,如SAMInside。找一台Windows7虚拟机,新建一个名为hashcat的管理员用户,并设置密码,在Windows7中下载并解压SAMInside后以管理员权限运行,然后点击File->Import Local Users vis Scheduler,如下图所示:
之后SAMInside可能会“未响应”,但不要紧,耐心地等待几秒,SAMInside不负所望地读出了我们想要的hash,如下图所示:
选中我们想要爆破密码的用户“hashcat”,按Ctrl+5复制NT-hash,然后回到安装了hashcat的Ubuntu中,用如下命令将复制出的hash值保存到文件win7.hash中:
echo 356CEAE0C89FB65ED6D6AA7A445C4CE5 > win7.hash
NT-hash便是Windows7保存登录密码使用的hash函数,接着用如下命令爆破NT-hash:
hashcat -w 3 -a 0 -m 1000 --remove -o win7.out win7.hash wordlist.dic
片刻后执行完毕,查看win7.out文件,发现爆破成功,用户hashcat的登录密码是rush2112:
werner@Yasser:~/hashcat$ cat win7.out 356ceae0c89fb65ed6d6aa7a445c4ce5:rush2112
怎样拿到SAM文件可参考《如何导出Windows哈希系列一 》。下面记录我读取虚拟机Windows7中SAM文件的过程。
若是物理机,用Win PE启动机器,读取磁盘上的SAM文件即可。我的是虚拟机,将虚拟磁盘文件挂载到文件系统中就可以读虚拟磁盘中的文件了。我用的虚拟机是VirtualBox,使用命令vdfuse可以完成此事。若没有vdfuse则需先安装virtualbox-fuse:
sudo apt-get install virtualbox-fuse
也可下载virtualbox-fuse的安装包自己安装。
安装完成后便有了vdfuse命令,可以开始虚拟磁盘映射、挂载了:
mkdir -p ~/vmdisk sudo vdfuse -t VMDK -f Win7Pro32.vmdk ~/vmdisk/
执行完这步后查看~/vmdisk目录,其中有三个文件:EntireDisk、Partition1和Partition2,新建目录:
mkdir -p ~/vmdisk_en mkdir -p ~/vmdisk_1 mkdir -p ~/vmdisk_2
用mount命令分别挂载EntireDisk、Partition1和Partition2这三个文件:
sudo mount ~/vmdisk/EntireDisk ~/vmdisk_en sudo mount ~/vmdisk/Partition1 ~/vmdisk_1 sudo mount ~/vmdisk/Partition2 ~/vmdisk_2
发现,EntireDisk挂载失败,Partition1中内容不是我想要的,Partition2中是Windows7虚拟机中的文件,正是我想要的。从vmdisk_fs中复制出我们的目标SAM文件:
cp ~/vmdisk_2/Windows/System32/config/SAM ./
顺便把SYSTEM文件也复制出来:
cp ~/vmdisk_2/Windows/System32/config/SYSTEM ./
查看SAM文件的内容,如下图所示,竟然不是纯文本文件,果然是Windows的风格,
好吧,虽然成功打开了SAM文件,但我们还是没有得到hash,接下来改怎么办?只能借助工具解析SAM文件内容了。把SAM文件和SYSTEM文件都搞到Kali中,运行命令:
samdump2 -o sam.hash SYSTEM SAM
然后查看sam.hash,也可以看到各个用户登录密码的hash值。sam.hash文件中每行是一个用户,每一行的格式均为:
用户名称:RID:LM-hash值:NTLM-hash值
注意此格式是samdump2命令输出格式,并不是“Windows下的Hash密码格式”。
首先,得有一台运行linux系统的电脑,这个好说,虚拟机就可以了。然后,运行如下命令添加新用户并设置密码,以供我们爆破之用:
sudo adduser justforfun
linux中用户登录密码的hash值存放在文件/etc/shadow中(注意:不是/etc/passwd),使用如下命令查看新建用户的登录密码的hash值:
test@test-VirtualBox:~$ sudo tail -n 1 /etc/shadow justforfun:$6$0fokwg59$6hpMS5dM9wDT/42DDoSD0i0g/wHab50Xs9iEvVLC3V20yf1kRmXZHGXCM0Efv6XU69hdgMZ4FwaMzso4hQaGQ0:17373:0:99999:7:::
tail命令用于读一个文件的最后几行,默认是10行,用参数-n指定行数。我们刚刚新建的用户自然在最后一行,故用tail -n 1读取。读到的结果是以“:”分割的数据,第一部分是用户名“justforfun”,第二部分便是密码的hash值了,其他的部分在本文中不必关心。我们重点研究第二部分。
开头的“$6$”指所用hash函数的类型为SHA-512,除“$6$”外,在linux中,“$1$”指MD5, “$2a$”指Blowfish, “$2y$”指Blowfish(correct handling of 8-bit chars), “$5$”指SHA-256,详情参见维基百科:passwd。此外,文件/etc/login.defs也对hash算法有所说明。
“$6$”开始到下一个“$”之前的部分“0fokwg59”是盐(SALT)。什么是盐呢?百度知道CNB2009对问题“什么是md5盐值”的回答简单易懂:
简单说就是为了使相同的密码拥有不同的hash值的一种手段,就是盐化。MD5自身是不可逆的,但是目前网路上有很多数据库支持反查询,如果用户密码数据库不小心被泄露,黑客就可以通过反查询方式获得用户密码,或者对于数据库中出现频率较高的hash码(即很多人使用的)进行暴力破解(因为它通常都是弱口令)。盐值就是在密码hash过程中添加的额外的随机值,比如我的id是癫ω倒④ゞ,密码是123456,存在数据库中的时候就可以对字符串“123456/癫ω倒④ゞ ”进行hash,而验证密码的时候也以字符串“(要验证的密码)/癫ω倒④ゞ ”进行验证。这样有另外一个笨蛋密码是123456的时候,依然能构造出不同的hash值,并且能成功的验证。这时候我的id就作为盐值 为密码进行复杂hash了。所以么。。盐值的作用是减少数据库泄露带来的损失。如果你RP非常好,猜中了我的密码是123456,我也阻止不了你啊
该回答针对md5,其他hash函数同理。盐之后的部分就是hash值了。现在复制整个第二部分到文件linux.hash中,linux.hash中的内容应为:
$6$0fokwg59$6hpMS5dM9wDT/42DDoSD0i0g/wHab50Xs9iEvVLC3V20yf1kRmXZHGXCM0Efv6XU69hdgMZ4FwaMzso4hQaGQ0
然后用如下命令爆破linux登录密码hash:
hashcat -w 3 -a 0 -m 1800 --remove -o linux.out linux.hash wordlist.dic
片刻后,爆破完成,查看结果:
werner@Yasser:~/hashcat$ cat linux.out $6$0fokwg59$6hpMS5dM9wDT/42DDoSD0i0g/wHab50Xs9iEvVLC3V20yf1kRmXZHGXCM0Efv6XU69hdgMZ4FwaMzso4hQaGQ0:4321
可见爆破成功。
首先,得有Mysql。刚好我虚拟机中就有。百度可知Mysql的登录密码的hash值保存在文件user.MYD中。文件user.MYD又在哪里?我也不知道啊,就找呗:
test@test-VirtualBox:~$ sudo find / -name user.MYD /var/lib/mysql/mysql/user.MYD
找到了,是在/var/lib/mysql/mysql/user.MYD,查看该文件内容:
sudo cat /var/lib/mysql/mysql/user.MYD
不是纯文本文件,关系不大,还是看得出用户root的登录密码的hash值是:
6B825255FB466413D6B1B724644E23428C94BBCB
将此值保存到文件mysql.hash中,用如下命令爆破Mysql登录密码hash:
hashcat -w 3 -a 0 -m 300 --remove -o mysql.out mysql.hash wordlist.dic
片刻后,爆破完成,查看结果:
werner@Yasser:~/hashcat$ cat mysql.out 6b825255fb466413d6b1b724644e23428c94bbcb:viper
可见爆破成功。
Discuz!是我国知名的php论坛程序,使用极为广泛。现在我们来爆破下Discuz!用户密码的hash值。首先得找到hash值,从哪里找呢?当然是从Discuz!的数据库里。
可Discuz!的数据库又在哪里?我是这么解决的,从它的官网下载最新版Discuz!源码,运行安装,便得到了Discuz!的数据库
Discuz!的默认数据库名为ultrax,其中的pre_ucenter_members表中保存着登录密码的hash值,“pre_”是默认的前缀,在安装时可以改变,“ucenter_members”是不会变的。用如下sql语句查询出登录密码的hash值:
select password,salt from pre_ucenter_members;
保存hash值和盐值到文件:
echo 69bcba126b93c6f397983629a0f70553:c13fd9 > discuz.hash
hash值和盐值在同一行中,以“:”分割。最后,用如下命令爆破Discuz登录密码hash:
hashcat -w 3 -a 0 -m 2611 --remove -o discuz.out discuz.hash wordlist.dic
片刻后,爆破完成,查看结果:
werner@Yasser:~/hashcat$ cat discuz.out 69bcba126b93c6f397983629a0f70553:c13fd9:winter
可见爆破成功。
截止目前,我们使用仅仅500个单词的小字典,每次都只需片刻,便顺利地爆破了各种hash,不觉得奇怪吗?这是因为我为练习使用hashcat而故意设置在字典内的弱密码,否则爆不出来岂不是让人心情很差。实际中就不可能有这么好的运气了。我们来随便计算一个不那么弱的密码的md5值,用大字典爆破,一方面试试运气,另一方面看看hashcat能有多快。
首先计算md5值:
import hashlib md5 = hashlib.md5() md5.update("werner123456!!!") print md5.hexdigest()
输出为:
b17133f9abff287ed0546c1af2b171f7
然后选择一个10.5G大小,内含9.4亿密码的字典,开始爆破:
hashcat -w 3 -a 0 -m 0 --remove -o big.out b17133f9abff287ed0546c1af2b171f7 big.dic
注意到,只有一个hash值时,不用保存在文件中,直接写在命令行参数中也可以。睡觉前开始爆破,第二天起来看结果,发现:
Started: Wed Jul 26 22:55:27 2017 Stopped: Wed Jul 26 23:02:28 2017
原来只用了7分钟!我原以为要用7个小时,比我预想的快了60倍!有点遗憾的是,并没有成功的爆破出hash值,看来“werner123456!!!”并不在密码字典中。看来我需要准备一个100G的密码字典,但这么大的字典保存、转移都很不方便,没有其他办法吗?当然有,还记得攻击模式吗?我们一直在使用“Straight”模式,接下来,研究下其他几种模式吧。
使用hashcat爆破hash,第一是要找准hash,不同的系统、不同的软件,其hash存放的位置不同,需要准确地找出hash值来;第二是要正确判断hash类型,确定hashcat是否支持这种hash,选对-m的参数,否则几乎不可能成功;第三是密码字典要好,最终能否爆破成功,还是看字典。密码字典虽不是越大越好,但总归还是大点的好,hashcat也以速度著称,大字典对hashcat不是问题。这里记录一个比较好的字典:历次泄密门+常用弱口令字典集合.7z,解压密码是:anywlan。另外,若是收集了很多小字典,可以将小字典合并、排序、去重,得到一个大字典,以便于hashcat爆破之用。如果小字典在同一个目录下,使用一条命令就可以搞定:
cat * | sort | uniq > Merge.dic
若是小字典被按类别整理,分布在多层目录中呢?只用cat命令显然不行,但其实也只需一条命令就可以了,假设小字典们均被存放在目录MyDictionary中,则命令可以这样写:
find ./MyDictionary -type f -exec cat {} \; | sort | uniq > Merge.dic