Linux 使用者認證(crypt方式)

來源:互聯網
上載者:User

最近做的一些開發和Linux使用者有密切的關係,以前沒有做過相關的學習,僅僅停留在使用shell下的useradd,
passwd命令,但對使用者的認證及密碼的管理基本沒有瞭解。在這裡做個小結。

1. 第一個重要檔案/etc/passwd

例:/etc/passwd中的一行

rwan:x:1000:1000:Robin:/home/rwan:/bin/bash

包含七個欄位,各個欄位間用冒號隔開(使用者名稱:密碼:使用者id:組id:使用者描述:使用者家目錄:使用者的登入shell)

POSIX.1 定義了兩個介面擷取使用者口令檔案

#include <pwd.h>struct passwd *getpwuid(uid_t uid); //通過uid擷取密碼項struct passwd *getpwnam(const char *name); //通過使用者名稱擷取密碼項struct passwd{     char *pw_name; //使用者名稱     char *pw_passwd; //使用者密碼     uid_t pw_uid; //使用者id     uid_t pw_gid; //使用者組id     char *pw_gecos; //使用者描述     char *pw_dir; //使用者家目錄     char *pw_shell; //使用者登入shell};

要查看整個口令檔案,POSIX.1介面則不能滿足要求,需使用下列介面

#include <pwd.h>struct passwd *getpwent(); //返回口令記錄的下一項void setpwent(); //定位到開頭,即從第一項開始讀void endpwent(); //讀取結束,關閉

問題:為什麼/etc/passwd中的所有密碼都是個x?

在最早的Unix系統中,使用者密碼確實存放在/etc/passwd,但為了安全,後來把密碼存放在/etc/shadow中,

因為/etc/paasswd對所有使用者都是可讀的,如果密碼放在這裡,會被暴力破解,而/etc/shadow只有root使用者可讀寫和

shadow組使用者可讀(這裡不同發行版可能不同,Fedora中/etc/shadow只有root可唯讀,此處測試在Ubuntu下)。

root@localhost:/home/rwan# ls -l /etc/passwd-rw-r--r-- 1 root root 1371 2009-08-29 05:05 /etc/passwdroot@localhost:/home/rwan# ls -l /etc/shadow-rw-r----- 1 root shadow 878 2009-08-29 05:05 /etc/shadow

 2.第二個重要檔案/etc/shadow

例:/etc/shadow中的一行

rwan:$1$TA.EyKcB$GMnqWwkKY9cr8667xIwXE0:14574:0:99999:7:::

包含九項內容(使用者登入名稱:加密口令:之後的幾項用於控制口令改動頻率及賬戶活動狀態情況)。

而在/etc/shadow中大致有三種情形,密碼項為*,!,或一個字串,分別表示禁止賬戶登入,密碼未設定,及加密後的密碼。

使用useradd添加一個新使用者,就會發現該使用者的的密碼項為!

例:添加一個無密碼使用者

root@localhost:/home/rwan# useradd testroot@localhost:/home/rwan# cat /etc/passwd |grep testtest:x:1001:1002::/home/test:/bin/shroot@localhost:/home/rwan# cat /etc/shadow | grep testtest:!:14574:0:99999:7:::Linux中提供了類似讀取/etc/passwd的介面#include <shadow.h>struct spwd* getspnam(const char *name);struct spwd* getspent();void setspent();void endspent();struct spwd{      char *sp_namp; //使用者名稱      char *sp_pwdp; //密碼     ……}

3. 登入過程中如何進行密碼比對

為了提高安全性,Linux引入了salt,所謂的salt,即為一個隨機數,引入的時候為一個12-bit的數值,

當使用者佈建密碼時,會隨機產生一個salt,與使用者的密碼一起加密,得到一個加密的字串(salt以明文形式包含在該字串中),

儲存到密碼檔案中,這樣就將攻擊的難度擴大了212即4096倍。crypt將使用者的key和salt一起適應某種演算法進行加密(散列)
#inclue <stdlib.h>
char *crypt(const char *key, const char *salt);

crypt中可以使用多種加密(散列)機制,包括最初的DES,還有後來為提高安全性引入的md5,blowfish,sha-256,sha-512.

crypt為支援不同的方式,將salt進行格式化,格式為:

$id$salt$encoded (這也是儲存在密碼檔案中的格式)

這裡不同id代表不同的演算法,不同演算法salt的長度也不同。

Id

Method

實際加密後的密碼長度

1

         MD5(12個salt字元)

22

2a

Blowfish

 

5

SHA-256(12個salt字元)

43

6

SHA-512(12個salt字元)

86

例:一個小程式

首先給剛才建立的使用者test設定密碼123456,

root@localhost:/home/rwan# passwd testroot@localhost:/home/rwan# cat /etc/shadow | grep testtest:$1$svja5yi5$nGAXQLRtqM454THCcBv/50:14574:0:99999:7:::可以看到,Ubuntu採用的是Md5認證,salt = $1$svja5yi5$, 密鑰 = nGAXQLRtqM454THCcBv/50可以用下面的程式來實驗。#include <stdio.h>#include <stdlib.h>#include <string.h>void main(){    char *salt = "$1$svja5yi5";    printf("user test's secrect key = %s /n",crypt("123456", salt));}root@localhost:/home/rwan# gcc -o user.o user.c -lcryptroot@localhost:/home/rwan# ./user.ouser test's secrect key = $1$svja5yi5$nGAXQLRtqM454THCcBv/50 

 

呵呵。不錯吧。和/etc/shadow中的一模一樣吧,廢話,不一樣的話,出大問題了。

那麼Linux是如何認證使用者密碼的,應該是使用者輸入密碼後,login程式從/etc/shadow中獲得該使用者的salt,

並計算密鑰,和/etc/shadow中的比對,有了上面的struct spwd* getspnam(const char *name)函數,想類比寫個也不難。

4.更多思考

既然/etc/shadow只有root可寫,那為什麼普通使用者可以修改自己的密碼?

這裡有一個suid的概念,什麼意思呢?

root@localhost:/home/rwan# ls -l /usr/bin/passwd-rwsr-xr-x 1 root root 29104 2006-12-19 15:35 /usr/bin/passwd

所有使用者對passwd命令均有可執行許可權,注意裡面的那個s,是說如果你有執行許可權,那麼運行該程式的時間,會以檔案屬主的許可權執行。

5.別走開,我們可以走的更遠

學習下怎麼製造salt吧。

以下代碼摘自busybox。

#include <stdio.h>#include <unistd.h>static int i64c(int i){    i &= 0x3f;    if (i == 0)        return '.';    if (i == 1)        return '/';    if (i < 12)        return ('0' - 2 + i);    if (i < 38)        return ('A' - 12 + i);    return ('a' - 38 + i);}int crypt_make_salt(char *p, int cnt, int x){    x += getpid() + time(NULL);    do {        /* x = (x*1664525 + 1013904223) % 2^32 generator is lame         * (low-order bit is not "random", etc...),         * but for our purposes it is good enough */        x = x*1664525 + 1013904223;        /* BTW, Park and Miller's "minimal standard generator" is         * x = x*16807 % ((2^31)-1)         * It has no problem with visibly alternating lowest bit         * but is also weak in cryptographic sense + needs div,         * which needs more code (and slower) on many CPUs */        *p++ = i64c(x >> 16);        *p++ = i64c(x >> 22);    } while (--cnt);    *p = '/0';    return x;}void main() {    int rnd = rnd; //use uninitialized data to generate random digital    char salt[sizeof("$N$XXXXXXXX")];    strcpy(salt, "$1$");    rnd = crypt_make_salt(salt + 3, 4, rnd);    printf("slat = %s/n", salt);    printf("secret key = %s/n", crypt("123456", salt));}root@localhost:/home/rwan# gcc -o user2.o user2.c -lcryptroot@localhost:/home/rwan# ./user2.oslat = $1$rTWCKgPtsecret key = $1$rTWCKgPt$pIvnCsr3wAOw8XrJ9SQug1

思想:目的是產生8個隨機字元作為salt。對著ASCII表,去理解吧。

因為ASCII碼中有很多字元時不可列印字元,為了讓加密過的密碼看起來像普通的字串,系統使用了一種叫base64的編碼,

將散列後的結果轉化為可列印字元。base64的基本思想,base64的字元集為A-Za-z0-9/.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.