小贴士

哈希(又称为散列算法)不是加密,不是编码;哈希是不可逆的,加密可逆;编码解码不需要密钥,加解密需要密钥

常见的编码 & 哈希 & 加解密算法如下

编码:base64 Hex编码 Huffman编码

哈希:md5 SHA-1 SHA-128 SHA-256 SHA-512 SM3

加密:

​ - 对称加密(加解密密钥一样):DES AES SM4

​ - 非对称加密(加解密密钥不一样):RSA DSA SM2

场景

利用GlassFish任意文件读取漏洞,读取了/etc/shadow文件,可是密码是哈希过的,怎么破解呢?

FOFA:"GlassFish" && port="4848" && country="IN"

/etc/shadow文件介绍

首先说一下Linux shadow文件和passwd文件的小小区别

文件用户可访问?
/etc/shadow所有用户可读取
/etc/passwdroot可读取
cat /etc/shadow          # 看一下我自己的shadow文件的其中一行
root:$6$C.nLBV0u$Ya4XCw1/jEiqx8/nnwE0r6tEtw/l1zt5iUr8GMrsdxTN1Omp2uPVtFNIZb0ZsNFRImJvvj0CSgNvAcsZo7i6d0:18002:0:99999:7:::

/etc/passwd一样,shadow 文件中的每个字段也用“ : : :”冒号分隔,如下所示:

  1. 用户名:系统上存在的有效帐户名。

  2. 密码:您的密码采用哈希格式保存。散列值长度应至少为 15-20 个字符,包括特殊字符、数字、小写字母等。这里保存的是密码的哈希值。目前 Linux 的密码采用的是 SHA512 散列算法,原来采用的是 MD5 或 DES 算法。SHA512 散列算法的更加安全

    注意,这串密码产生的乱码不能手工修改,如果手工修改,系统将无法识别密码,导致密码失效。很多软件透过这个功能,在密码串前加上 “!”、“*” 或 “x” 使密码暂时失效。

    所有伪用户的密码都是 “!!” 或 “*”,代表没有密码是不能登录的。当然,新创建的用户如果不设定密码,那么它的密码项也是 “!!”,代表这个用户没有密码,不能登录。密码格式设置为$id$salt$hashed,$id值与 GNU/Linux 上使用的哈希算法对应如下:

    • $1$ is MD5

    • $2a$ is Blowfish

    • $2y$ is Blowfish

    • $5$ is SHA-256

    • $6$ is SHA-512

  3. 上次密码更改 (last changed):上次更改密码的日期,表示为自 1970 年 1 月 1 日(Unix 时间)以来的天数。值 0 具有特殊含义,即用户下次登录系统时应更改密码。空字段表示禁用密码老化功能。

  4. 最小值:密码更改之间所需的最短天数,即允许用户再次更改密码之前的剩余天数。空字段和值 0 表示没有最短密码期限。

  5. 最大值:密码有效的最大天数,在该用户被迫再次更改她的密码之后。

  6. 警告:密码到期前的天数,警告用户必须更改他/她的密码

  7. Inactive:密码过期后该帐户被禁用的天数。

  8. Expire:帐户的到期日期,表示为自 1970 年 1 月 1 日以来的天数。

什么是加盐?

明文密码是 passwdsalt 是随机字串

假设id=1,即选择md5哈希算法。

那么加盐的过程就是 计算 h a s h e d = m d 5 ( s a l t + p a s s w d ) hashed=md5(salt+passwd) hashed=md5(salt+passwd)

算出来之后就是咱们在shadow文件里读的 $id$salt$hashed

🤔注意,此处仅为举例,Linux怎么加盐我也没细究,salt也可以在passwd后面~

能破解吗?

由于进行 hash 的时候,采用了 salt 机制,所以传统的彩虹表方式将起不到作用。

不加盐现在的常见密码hash值库太大了,太容易泄露密码了 ,cmd5 教做人

破解方法有字典破解和暴力破解。 字典我找不到太好用的:https://github.com/DrKadron/List.txt

破解脚本如下,在Linux上运行(crypt这个库是Linux上的)

import crypt   ## 导入 Linux 口令加密库
def testPass(cryptPass):
    salt=cryptPass[cryptPass.find("$"):cryptPass.rfind("$")]  ## 获得盐值,包含 $id 部分
    dictFile=open('key.txt','r')
    for word in dictFile.readlines():
        word=word.strip("\n")
        cryptWord=crypt.crypt(word,salt)                   ## 将密码字典中的值和盐值一起加密
        if (cryptWord==cryptPass):                           ## 判断加密后的数据和密码字段是否相等
            print ("[+]Found Password:"+word+"\n" )      ## 如果相等则打印出来
            return 
    print ("[-] Password Not Found.\n")
    return 
 
def main():
    passFile=open('shadow.txt')
    for line in passFile.readlines():      ## 读取文件中的所有内容
        if ":" in line:
            user=line.split(":")[0]                     ## 获得用户名
            cryptPass=line.split(":")[1].strip(' ')     ## 获得密码字段
            print ("[*] Cracking Password for:"+user)
            testPass(cryptPass)
main()

偶然还看到了国光大佬提到了利用GPU破解密码的工具 Hashcat,以后遇到特想干的目标再学!

References

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐