Linux PAM Authentication and password encryption in shadow files

Source: Internet
Author: User
Tags crypt md5 encryption

Pam Full name: Pluggable Authentication Modules, Chinese name is "pluggable authentication module ".
It is a unified authentication solution. Pam allows you to change your authentication methods and requirements at any time, and encapsulates all local authentication methods without re-compiling any code. For details, see
Pam website.

For Pam, you only need:

  • Use different DES encryption methods for your password (making them more robust in the face of brute force decode ).

  • Use resource quotas for all your users to prevent denial-of-service attacks (process count, memory usage, and so on ).

  • Enable shadow password at any time (see below)

  • Only allow specific users to log on from a specific place at a specific time

The above is from http://man.ddvip.com/linux/manrakelinux10server/password-security.html.

==========================================================

Let's take a look at the shadow file format:
Root @ localhost :~ # Cat/etc/shadow
Root: $1 $ bg1h/4mz $ x89tq1_tpi9dx1b9j5ysf.: 14838: 0: 99999: 7 :::
Daemon: *: 14838: 0: 99999: 7 :::
Bin: *: 14838: 0: 99999: 7 :::
SYS: *: 14838: 0: 99999: 7 :::
Sync: *: 14838: 0: 99999: 7 :::
Games: *: 14838: 0: 99999: 7 :::
MAN: *: 14838: 0: 99999: 7 :::
LP: *: 14838: 0: 99999: 7 :::
Mail: *: 14838: 0: 99999: 7 :::
News: *: 14838: 0: 99999: 7 :::
Uucp: *: 14838: 0: 99999: 7 :::
Proxy: *: 14838: 0: 99999: 7 :::
WWW-data: *: 14838: 0: 99999: 7 :::
Backup: *: 14838: 0: 99999: 7 :::
List: *: 14838: 0: 99999: 7 :::
IRC: *: 14838: 0: 99999: 7 :::
Gnats: *: 14838: 0: 99999: 7 :::
Nobody: *: 14838: 0: 99999: 7 :::
Libuuid :! : 14838: 0: 99999: 7 :::
Debian-Exim :! : 14838: 0: 99999: 7 :::
STATD: *: 14838: 0: 99999: 7 :::
Sshd: *: 14838: 0: 99999: 7 :::
Test: 14879: 0: 99999: 7 :::
Format:
{User name }:{ encrypted password string }:{ last password modification time: days from January 1, January 1, 1970 }:{ days before the password can be modified (to prevent password modification, then immediately change it back to the old password) }:{ number of days after the password must be modified }:{ Number of days before the password expires }:{ number of days after the password expires }:{ reserved}
Shadow is a readable object. Normal users do not have the read and write permissions. superusers have the read and write permissions.

If the password string is *, the System user cannot be logged in! Indicates that the user name is disabled. If the password string is empty, it indicates that there is no password, and a user's password can be cleared through the passwd-D user name.

For details about shadow, refer to shadow how-to, although this is an outdated document.

The following describes the password encryption in shadow:

Take the preceding root user as an example:
Root: $1 $ bg1h/4mz $ x89tq1_tpi9dx1b9j5ysf.: 14838: 0: 99999: 7 :::
The password field is $1 $ bg1h/4mz $ x89tq1_tpi9dx1b9j5ysf. Refer to the Linux Standard passwd. C source file and find the encryption method in the pw_encrypt function:
40 char * pw_encrypt (const char * clear, const char * salt)
41 {
42 static char cipher [128];
43 char * CP;
44
45 CP = crypt (clear, salt );
46 If (! CP ){
47 /*
48 * single unix spec: crypt () may return a null pointer,
49 * and set errno to indicate an error. The caller doesn' t
50 * expect CT us to return NULL, so...
51 */
52 perror ("crypt ");
53 exit (1 );
54}
55
56/* the GNU crypt does not return NULL if the algorithm is not
57 * supported, and return a DES encrypted password .*/
58 If (salt & Salt [0] = '$' & strlen (CP) <= 13)
59 {
..........
79 fprintf (stderr,
80_( "crypt method not supported by libcrypt? (% S) \ n "),
81 method );
82 exit (1 );
83}
84
85 if (strlen (CP )! = 13)
86 return CP;/* nonstandard crypt () in libc, better bail out */
87 strcpy (cipher, CP );
88
89 return cipher;
90}

That is to say, encryption uses plaintext passwords and crypt () to encrypt a theme called salt to generate ciphertext.
Let's take a look at the help of crypt:
Http://www.kernel.org/doc/man-pages/online/pages/man3/crypt.3.html
It can be found that the original crypt ciphertext is composed of three parts: $ID$Salt$Encrypted
Currently, when ID is 1, MD5 encryption is used, ID is 5, sha256 is used for encryption, and ID is 6 is sha512 for encryption.
By analyzing the above functions, we can see that in our shadow password, we directly put $ID$Salt$EncryptedCrypt encryption is carried in as the salt parameter.
Well, we can write a short code for testing:
# 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 ");
Struct passwd * Pwd;
Pwd = getpwnam (argv [1]);
If (Pwd = NULL)
Printf ("no username found. \ n ");
Else
{
Printf ("passwd: % s \ n", PWD-> pw_passwd );
If (strcmp (PWD-> pw_passwd, "x") = 0)
{
Printf ("shadow used. \ n ");
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;
}

Save and run GCC passwd. C-lcrypt-O passwd.

Run./passwd root 123 After compilation is successful
Among them,./passwd is the generated command, root is the account we use to test, 123 is the password of the root user in the test system, and the result is:
Passwd: x
Shadow used.
Salt: $1 $ bg1h/4mz $, crypt: $1 $ bg1h/4mz $ x89tq1_tpi9dx1b9j5ysf.
Shadowd passwd: $1 $ bg1h/4mz $ x89tq1_tpi9dx1b9j5ysf.
We can see that the ciphertext of the same result as that of the system shadow file is obtained.

Based on our running results, we can see that in the shadow of the root user, his salt is $1 $ bg1h/4mz $
We used this salt for encrypted matching. But the question is: how did the salt come from ??

Analyze the standard passwd. C,
In passwd. C, find the salt generation function: crypt_make_salt
201 char * crypt_make_salt (const char * meth, void * Arg)
202 {
203/* max result size for the Sha methods:
204 * + 3 $5 $
205 * + 17 rounds = 999999999 $
206 * + 16 salt
207 * + 1 \ 0
208 */
209 static char result [40];
210 size_t salt_len = 8;
211 const char * method;
212
213 result [0] = '\ 0 ';
214
215 if (null! = Meth)
216 method = meth;
217 else {
218 If (method = getdef_str ("encrypt_method") = NULL)
219 method = getdef_bool ("md5_crypt_enab ")? "MD5": "des ";
220}
221
222 If (! Strcmp (method, "MD5 ")){
223 Magnum (result, '1 ');

224 # ifdef use_sha_crypt
225} else if (! Strcmp (method, "sha256 ")){
226 Magnum (result, '5 ');
227 strcat (result, sha_salt_rounds (int *) Arg ));
228 salt_len = sha_salt_size ();
229} else if (! Strcmp (method, "sha512 ")){
230 Magnum (result, '6 ');
231 strcat (result, sha_salt_rounds (int *) Arg ));
232 salt_len = sha_salt_size ();
233 # endif
234} else if (0! = Strcmp (method, "des ")){
235 fprintf (stderr,
236 _ ("invalid encrypt_method value: '% s'. \ n"
237 "defaulting to Des. \ n "),
238 method );
239 result [0] = '\ 0 ';
240}
241
242 /*
243 * concatenate a pseudo do random salt.
244 */
245 assert (sizeof (result)> strlen (result) + salt_len );
246 strncat (result, gensalt (salt_len ),
247 sizeof (result)-strlen (result)-1 );
248
249 return result;
250}
Except for a large range of condition-based judgment statements, the most important one is gensalt (salt_len ).
Let's take a look at gensalt's definition:
167
168 static char * gensalt (unsigned int salt_size)
169 {
170 static char Salt [32];
171
172 Salt [0] = '\ 0 ';
173
174 assert (salt_size> = min_salt_size &&
175 salt_size <= max_salt_size );
176 seedrng ();
177 strcat (salt, l64a (random ()));
178 do {
179 strcat (salt, l64a (random ()));
180} while (strlen (SALT) <salt_size );
181 Salt [salt_size] = '\ 0 ';
182
183 return salt;
184}
Oh, the mysterious salt is just a random and visible string with a fixed length.
A random salt is generated every time the password is changed. During User Login, the plaintext password used for user login will be used to generate the ciphertext after the above demonstration steps, and then compare it with the password domain in shadow.

With the above analysis, it is not a problem to crack the password in Linux on a profiteering basis, but the premise is that you have the opportunity to get the shadow file, which seems difficult.
This article is only a technical analysis article with no other intention.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.