Ubuntu系统中/etc目录下有三个和用户登录访问控制相关的文件:passwd、shadow、group。以前比较老的Unix系统将经过哈希处理的密码直接放在passwd文件中,现在的*nix则把经过处理的密码放在shadow这个文件中,这三个文件的用途可以参考:http://blog.sina.com.cn/s/blog_5edae1a101017gfn.html
打开/etc/shadow文件内容如下图:
可以看到从“$6$”开始到“GJr..”结束这一段字符是经过哈希处理的用户密码,那么我们现在想知道这个字符串是如何生成的,我们查看了Ubuntu官方的文档:
shadow文件说明:http://manpages.ubuntu.com/manpages/karmic/man5/shadow.5.html
crypt加密算法说明:http://manpages.ubuntu.com/manpages/karmic/man3/crypt.3.html
从官方文档中我们可以知道用户密码经过了glibc中的crypt算法的处理,“$6$3rhg9.la$”是哈希过程中使用到的盐值,那么盐值有什么作用呢?我们知道对于一个已知的哈希算法和一个固定的字符串来说,其哈希的结果是相同的,那么假设一个系统中有很多用户,那么其中的一些用户就可能使用相同的密码,例如两人都使用了“123456”作为登陆密码,那么在不使用盐值的情况下,经过处理的密码字符串就是一样的。虽然“非法***者”无法直接从经过处理的字符串获得明文密码,但仍然可以知道有两个人使用了相同的密码。为了避免这种情况,我们就可以在对用户的密码进行哈希时在原始密码的后边拼上一个盐值(m//salt),这样做的好处有两个:一方面由于盐值随机产生,避免相同密码产生同意的哈希值;另一方面增加了***者暴力破解的计算复杂度(增加了2^|salt|倍)。“$6$3rhg9.la$”分为两个部分:“6”和“3rhg9.la”,第一个参数是哈希算法选择参数,在官方文档中已经提到,第二个是随机产生的字符串。
python自带的crypt算法可以调用glibc中的crypt算法,我们打开python源文件中lib目录下的crypt.py文件可以看到python对glibc中的crypt算法的调用过程:
def crypt(word, salt=None):
"""Return a string representing the one-way hash of a password, with a salt
prepended.
If ``salt`` is not specified or is ``None``, the strongest
available method will be selected and a salt generated. Otherwise,
``salt`` may be one of the ``crypt.METHOD_*`` values, or a string as
returned by ``crypt.mksalt()``.
"""
if salt is None or isinstance(salt, _Method):
salt = mksalt(salt)
return _crypt.crypt(word, salt)
打开glibc源文件中crypt目录下的crypt-entry.c文件,我们可以看到根据盐值前三个字符进行哈希算法选择的代码:
/* Define our magic string to mark salt for MD5 encryption
replacement. This is meant to be the same as for other MD5 based
encryption implementations. */
static const char md5_salt_prefix[] = "$1$";
/* Magic string for SHA256 encryption. */
static const char sha256_salt_prefix[] = "$5$";
/* Magic string for SHA512 encryption. */
static const char sha512_salt_prefix[] = "$6$";
/* For use by the old, non-reentrant routines (crypt/encrypt/setkey) */
extern struct crypt_data _ufc_foobar;
在测试过程中最开始下载的是glibc2.6,这个版本并没有$5$和$6$对应的sha256/sha512算法,只有MD5,然后下载了最新的glibc2.18版本才看到了这两个算法,可以猜出使用glibc2.6版本及以前的版本的linux系统中,shadow文件并不是现在这样的。本Ubuntu系统的gblic版本是2.11(ldd --version查看),该版本glibc也支持sha256/sha512。我们给出的例子里前三个字符是“$6$”,我们可以知道系统使用的哈希算法是sha512。由于python调用的是glibc中的crypt算法,所以自然可以知道在windows平台下python的这个算法是无法调用的。现在使用python写一些脚本来测试一下:
在crypt函数中输入两个参数,一个是我们的登陆密码,另一个是盐值,我们可以看到输出的结果和shadow文件中经过处理的密码字符串相同。
shadow文件默认只能由root用户访问,一般用户没有访问权限,非法***者通过一定途径获得该文件后通过暴力尝试密码就有可能获得原始的明文密码,所以用户在设置密码的时候尽量包含多种字符(大小写、数字、特殊符号)并超过一定的长度,以此来提升系统的安全性。
转载于:https://blog.51cto.com/ciphertext/1275485