1) 查看shadow文件的内容

cat /etc/shadow

可以得到shadow文件的内容,限于篇幅,我们举例说明:

root:$1$Bg1H/4mz$X89TqH7tpi9dX1B9j5YsF.:14838:0:99999:7:::

其格式为:

{用户名}:{加密后的口令密码}:{口令最后修改时间距原点(1970-1-1)的天数}:{口令最小修改间隔(防止修改口令,如果时限未到,将恢复至旧口令):{口令最大修改间隔}:{口令失效前的警告天数}:{账户不活动天数}:{账号失效天数}:{保留}

【注】:shadow文件为可读文件,普通用户没有读写权限,超级用户拥有读写权限。如果密码字符串为*,则表示系统用户不能被登入;如果字符串为!,则表示用户名被禁用;如果字符串为空,则表示没有密码。

我们可以使用passwd –d 用户名 清空一个用户的口令密码。

2) 解析shadow文件中密码字符串的内容

对于示例的密码域$1$Bg1H/4mz$X89TqH7tpi9dX1B9j5YsF.,我们参考了Linux标准源文件passwd.c,在其中的pw_encrypt函数中找到了加密方法。

我们发现所谓的加密算法,其实就是用明文密码和一个叫salt的东西通过函数crypt()完成加密。

而所谓的密码域密文也是由三部分组成的,即:$id$salt$encrypted。

【注】: id为1时,采用md5进行加密;

id为5时,采用SHA256进行加密;

id为6时,采用SHA512进行加密。

3) 数据加密函数crypt()讲解

i. 头文件:#define _XOPEN_SOURCE

#include <unistd.h>

ii. 函数原型:char *crypt(const char *key, const char *salt);

iii. 函数说明:crypt()将使用DES演算法将参数key所指的字符串加以编码,key字符串长度仅取前8个字符,超过此长度的字符没有意义。参数salt为两个字符组成的字符串,由a-z、A-Z、0-9,’.’和’/’所组成,用来决定使用4096种不同内建表格的哪一种。函数执行成功后会返回指向编码过的字符串指针,参数key所指向的字符串不会有所改动。编码过的字符串长度为13个字符,前两个字符为参数salt代表的字符串。

iv. 返回值:返回一个指向以NULL结尾的密码字符串

v. 附加说明:使用GCC编译时需要加上 –lcrypt

4) 加密参数salt的由来

在我们的示例密码域中salt为Bg1H/4mz,那么它又是如何来的?

我们还是从标准源文件passwd.c中查找答案。在passwd.c中,我们找到了与salt相关的函数crypt_make_salt。

在函数crypt_make_salt中出现了很多的判断条件来选择以何种方式加密(通过id值来判断),但其中对我们最重要的一条语句是gensalt(salt_len)。

我们继续查看了函数static char *gensalt (unsigned int salt_size),才发现原来神秘无比的salt参数只是某个固定长度的随机字符串而已。

5) 最终结论

在我们每次改写密码时,都会随机生成一个这样的salt。我们登录时输入的明文密码经过上述的演化后与shadow里的密码域进行字符串比较,以此来判断是否允许用户登录。

【注】:经过上述的分析,我们发现破解linux下的口令也不是什么难事,但前提是你有机会拿到对方的shadow文件。

6) 示例代码(测试代码):

#include <pwd.h>
#include <stddef.h>
#include <string.h>
#include <shadow.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])

{

if(argc < 2)

{

printf("no usrname input");

return 1;

}

if (geteuid() != 0)

{

fprintf(stderr, "must be setuid root");

return -1;

}

struct spwd *shd= getspnam(argv[1]);

if(shd != NULL)

{

static char crypt_char[80];

strcpy(crypt_char, shd->sp_pwdp);

char salt[13];

int i=0,j=0;

while(shd->sp_pwdp[i]!='\0')

{

salt[i]=shd->sp_pwdp[i];

if(salt[i]=='$')

{

j++;

if(j==3)

{

salt[i+1]='\0';

break;

}

}

i++;

}

if(j<3)

perror("file error or user cannot use.");

if(argc==3)

{

printf("salt: %s, crypt: %s\n", salt, crypt(argv[2], salt));

printf("shadowd passwd: %s\n", shd->sp_pwdp);

}

}

return 0;

}

编译: gcc passwd.c -lcrypt -o passwd

运行: ./passwd root 123

结果: salt: $1$Bg1H/4mz$, crypt: $1$Bg1H/4mz$X89TqH7tpi9dX1B9j5YsF.

shadowd passwd: $1$Bg1H/4mz$X89TqH7tpi9dX1B9j5YsF.

shadow文件中密码的加密方式的更多相关文章

  1. linux的PAM认证和shadow文件中密码的加密方式

    它是一种统一的认证方案.PAM 让您能随时改变您的认证方法以及需求,并且不需要重新编译任何代码就封装了所有本地认证方法.具体见 PAM 网站. 对于 PAM 您只需要做: 对您的密码采用不同于 DES ...

  2. 生成/etc/shadow文件中的密码

    shadow文件的格式就不说了.就说说它的第二列--密码列. 通常,passwd直接为用户指定密码就ok了.但在某些情况下,要为待创建的用户事先指定密码,还要求是加密后的密码,例如kickstart文 ...

  3. 手动生成/etc/shadow文件中的密码

    shadow文件的格式就不说了.就说说它的第二列——密码列. 通常,passwd直接为用户指定密码就ok了.但在某些情况下,要为待创建的用户事先指定密码,还要求是加密后的密码,例如kickstart文 ...

  4. Centos7系统kvm虚机忘记密码进不去, 通过宿主机修改/etc/shadow文件改密码,重启后系统起不来故障排错

    问题描述 某天, 因为其他项目组交接问题, kvm里面的堡垒机系统用户root密码登录不上,然后他通过宿主机修改/etc/shadow文件修改密码,但是修改完后重启系统后发现kvm宿主机连接不上虚机了 ...

  5. SpringBoot项目配置文件中密码的加密

    作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/15565862.html 版权声明:本文为博主原创文章,转载请附上博文链接! 公众号:追梦1819 ...

  6. Liferay 6.2 改造系列之二十四:修改liferay密码的加密方式

    为了便于后期与Cas集成过程中使用数据库用户的方便,将liferay密码的加密方式改为SHA. 在/portal-master/portal-impl/src/portal.properties配置文 ...

  7. MyBatis mapper文件中的变量引用方式#{}与${}的差别

    MyBatis mapper文件中的变量引用方式#{}与${}的差别 #{},和 ${}传参的区别如下:使用#传入参数是,sql语句解析是会加上"",当成字符串来解析,这样相比于$ ...

  8. ASP.NET中MD5的加密方式很简单

    在ASP.NET中MD5的加密方式很简单,代码如下: FormsAuthentication.HashPasswordForStoringInConfigFile(str, "MD5&quo ...

  9. ][mybatis]MyBatis mapper文件中的变量引用方式#{}与${}的差别

    转自https://blog.csdn.net/szwangdf/article/details/26714603 MyBatis mapper文件中的变量引用方式#{}与${}的差别 默认情况下,使 ...

随机推荐

  1. GetModuleFileNameEx遍历获取64bit程序路径失败的一种解决方法(Win7-64-bit)

    问题: 32位程序在64位系统上调用GetModuleFileNameEx()遍历获取64位进程的全路径失败,得到的路径都为空. 根据官方的说法: For the best results use t ...

  2. CCF_ 201512-4_送货

    一道拖了很久了题,用bool开的vis不会爆内存,dfs回溯的话会超时,于是有了一个很巧妙的dfs. #include<iostream> #include<cstring> ...

  3. 基于 H5和 3D WebVR 的可视化虚拟现实培训系统

    前言 2019 年 VR, AR, XR, 5G, 工业互联网等名词频繁出现在我们的视野中,信息的分享与虚实的结合已经成为大势所趋,5G 是新一代信息通信技术升级的重要方向,工业互联网是制造业转型升级 ...

  4. react项目中引用amap(高德地图)坑

    最近在写一个react项目,用到了需要定位的需求,于是乎自己决定用高德地图(AMap),但是react官方文档的案列很少,大多都是原生JS的方法. 在调用amap的 Geocoder Api 时,一直 ...

  5. php curl 检测网页是否被百度收录

    <?php /* * 检测百度是否收录网页 curl模式 * @ param string $url传入的url* return int (1 收录 0 不收录) */ function che ...

  6. MS SqlServer 的日期格式化函数 Convert

    MS SqlServer 的日期格式化函数:Convert(data_type[(length)], expression [, style])参数:data_type[(length)]代表转换的数 ...

  7. Kubernetes 部署 Nginx Ingress Controller 之 nginxinc/kubernetes-ingress

    更新:这里用的是 nginxinc/kubernetes-ingress ,还有个 kubernetes/ingress-nginx ,它们的区别见 Differences Between nginx ...

  8. [Redis-CentOS7]Redis事务操作(六)

    事务操作 隔离操作: 事务中所有的命令都会序列化,按顺序执行,不会被其他命令打扰 原子操作: 事务中所有的命令要么全部执行,要么全部不执行 添加事务并执行 127.0.0.1:6379> MUL ...

  9. HDU 4994 博弈。

    F - 6 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status ...

  10. 动态规划------背包问题(c语言)

    /*背包问题: 背包所能容纳重量为10:共五件商品,商品重量用数组m存储m[5]={2,2,6,5,4}, 每件商品的价值用数组n存储,n[5]={6,3,5,4,6};求背包所能装物品的最大价值. ...