格式详解(/post/etc-shadow-file/)
mark:$6$.n.:17736:0:99999:7:::
[--] [----] [---] - [---] ----
| | | | | |||+-----------> 9. Unused
| | | | | ||+------------> 8. Expiration date
| | | | | |+-------------> 7. Inactivity period
| | | | | +--------------> 6. Warning period
| | | | +------------------> 5. Maximum password age
| | | +----------------------> 4. Minimum password age
| | +--------------------------> 3. Last password change
| +---------------------------------> 2. Encrypted Password
+----------------------------------------> 1. Username
-
Username. The string you type when you log into the system. The user account that exist on the system.
-
Encrypted Password. The password is using the
$type$salt$hashed
format.$type
is the method cryptographic hash algorithm and can have the following values:-
$1$
– MD5 -
$2a$
– Blowfish -
$2y$
– Eksblowfish -
$5$
– SHA-256 -
$6$
– SHA-512
If the password field contains an asterisk (
*
) or exclamation point (!
), the user will not be able to login to the system using password authentication. Other login methods like key-based authentication or switching to the user are still allowed.In older Linux systems, the user’s encrypted password was stored in the
/etc/passwd
file. -
-
Last password change. This is the date when the password was last changed. The number of days is counted since January 1, 1970 (epoch date).
-
Minimum password age. The number of days that must pass before the user password can be changed. Typically it is set to zero, which means that there is no minimum password age.
-
Maximum password age. The number of days after the user password must be changed. By default, this number is set to
99999
. -
Warning period. The number of days before the password expires during which the user is warned that the password must be changed.
-
Inactivity period. The number of days after the user password expires before the user account is disabled. Typically this field is empty.
-
Expiration date. The date when the account was disabled. It is represented as an epoch date.
-
Unused. This field is ignored. It is reserved for future use.
源码查找
通过passwd命令探查在centos7下 口令杂凑的计算过程
查看命令位置
命令 | 输出 |
which passwd | /usr/bin/passwd |
查看命令的安装包信息
命令 | 输出 |
yum provides passwd | passwd-0.79-6.el7.x86_64 : An utility for setting or changing passwords using PAM passwd-0.79-4.el7.x86_64 : An utility for setting or changing passwords using PAM |
下载命令源码
命令 | 备注 |
wget /7.5.1804/os/Source/SPackages/passwd-0.79-4. ./ |
http下载 |
rpm2cpio *.|cpio -iv | 转换成tar包后解压 |
浏览passwd源码,passwd依赖于PAM模块(The Linux-PAM Application Developers' Guide).主要调用过程 pam_start -> pam_chauthtok -> pam_end。其中pam_chauthtok,执行修改密码操作。浏览官方源码包 Index of /7.5.1804/os/Source/SPackages确定PAM版本。
命令 | 备注 |
wget /7.5.1804/os/Source/SPackages/pam-1.1.8-22. |
http下载pam源码 |
rpm2cpio *.|cpio -iv | 转换成tar包后解压 |
解压浏览源码,pam_start 先是加载了认证模块的配置文件 /etc//passwd 根据配置文件加载多个动态库相同符号名的符号.查看配置文件,涉及多个动态库加载。
命令 | 输出 |
cat /etc//passwd | #%PAM-1.0 auth include system-auth account include system-auth password substack system-auth -password optional pam_gnome_keyring.so use_authtok password substack postlogin |
cat /etc//system-auth | #%PAM-1.0 account required pam_unix.so password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= session optional pam_keyinit.so revoke |
继续跟踪源码 pam_start -> _pam_init_handlers -> _pam_parse_conf_file ->_pam_add_handler ->_pam_load_module,确定符号名"pam_sm_chauthtok",_pam_dlsym,其中加载生效的动态是pam_pwquality.so。继续跟踪,pam_chauthtok -> _pam_dispatch -> _pam_dispatch_aux -> h->func, "pam_sm_chauthtok" -> create_password_hash -> crypt, ().
其中crypt加密函数是的符号。 属于glibc一部分。
继续下载glibc源码 Index of /gnu/glibc
命令 | 输出 |
wget /gnu/glibc/glibc-2. |
http下载匹配glibc版本 |
解压查看源码:
crypt -> __sha512_crypt -> {...}
1)盐值有前缀 $6$ 但不参与运算。
2) __sha512_crypt 不是简单的 先杂凑口令后杂凑盐值,而是一系列sha512 操作。
3)最终的杂凑值是经过b64 编码。编码字符如下:
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
输出的字符数为ceil(64/6)*8=88 ,编码即没有按顺序,而且编码最后一个字符编码为两个字符。最终输出字符数为86.
b64_from_24bit (alt_result[0], alt_result[21], alt_result[42], 4);
b64_from_24bit (alt_result[22], alt_result[43], alt_result[1], 4);
b64_from_24bit (alt_result[44], alt_result[2], alt_result[23], 4);
b64_from_24bit (alt_result[3], alt_result[24], alt_result[45], 4);
b64_from_24bit (alt_result[25], alt_result[46], alt_result[4], 4);
b64_from_24bit (alt_result[47], alt_result[5], alt_result[26], 4);
b64_from_24bit (alt_result[6], alt_result[27], alt_result[48], 4);
b64_from_24bit (alt_result[28], alt_result[49], alt_result[7], 4);
b64_from_24bit (alt_result[50], alt_result[8], alt_result[29], 4);
b64_from_24bit (alt_result[9], alt_result[30], alt_result[51], 4);
b64_from_24bit (alt_result[31], alt_result[52], alt_result[10], 4);
b64_from_24bit (alt_result[53], alt_result[11], alt_result[32], 4);
b64_from_24bit (alt_result[12], alt_result[33], alt_result[54], 4);
b64_from_24bit (alt_result[34], alt_result[55], alt_result[13], 4);
b64_from_24bit (alt_result[56], alt_result[14], alt_result[35], 4);
b64_from_24bit (alt_result[15], alt_result[36], alt_result[57], 4);
b64_from_24bit (alt_result[37], alt_result[58], alt_result[16], 4);
b64_from_24bit (alt_result[59], alt_result[17], alt_result[38], 4);
b64_from_24bit (alt_result[18], alt_result[39], alt_result[60], 4);
b64_from_24bit (alt_result[40], alt_result[61], alt_result[19], 4);
b64_from_24bit (alt_result[62], alt_result[20], alt_result[41], 4);
b64_from_24bit (0, 0, alt_result[63], 2);