shadow文件中密碼的加密方式


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.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM