[prev in list] [next in list] [prev in thread] [next in thread]
List: oss-security
Subject: [oss-security] Potential security bugs in "eapmd5pass" software (3 CVE IDs)
From: Dhiru Kholia <dhiru.kholia () gmail ! com>
Date: 2017-07-31 15:51:55
Message-ID: 20170731154955.GA19657 () lonestar
[Download RAW message or body]
Summary
-------
This report describes 4 bugs in the eapmd5pass software package as shipped with
Kali Linux. Bug 1 is a regular functionality related bug. The other 3 bugs are
memory safety bugs that can be triggered remotely.
I found these bugs with the help of libFuzzer.
The worst case security impact of these three memory safety bugs seems to be
limited to a remote denial of service (eapmd5pass crash and loss of intended
functionality) under certain circumstances.
Reproducers are available at https://github.com/kholia/reproducers URL.
Steps to reproduce
------------------
http://www.willhackforsushi.com/?page_id=67
https://tools.kali.org/wireless-attacks/eapmd5pass
Add "-fsanitize=address" to Makefile and build eapmd5pass.
After building eapmd5pass with "make", ensure that ASan is enabled.
$ ldd ./eapmd5pass | grep asan
libasan.so.3 => /lib64/libasan.so.3 (0x00007fc7e85a5000)
Bug 1
-----
$ ./eapmd5pass -r brad.eaptest.cap -w wordlist
eapmd5pass - Dictionary attack against EAP-MD5
Error placing pcap interface in non-blocking mode.
pcap_setnonblock: No such file or directory
It seems eapmd5pass has a non-security bug which causes it to fail to process
.pcap files. Here is a patch to fix this problem,
diff --git a/eapmd5pass.c b/eapmd5pass.c
index 10b2a48..7ee51bb 100644
--- a/eapmd5pass.c
+++ b/eapmd5pass.c
@@ -684,7 +684,7 @@ int main(int argc, char *argv[])
}
/* Set non-blocking */
- if (pcap_setnonblock(p, PCAP_DONOTBLOCK, errbuf) != 0) {
+ if (!strlen(pcapfile) > 0 && pcap_setnonblock(p, PCAP_DONOTBLOCK, errbuf) != 0) {
fprintf(stderr, "Error placing pcap interface in non-blocking "
"mode.\n");
perror("pcap_setnonblock");
After applying this patch,
$ ./eapmd5pass -r brad.eaptest.cap -w wordlist
eapmd5pass - Dictionary attack against EAP-MD5
Collected all data necessary to attack password for "brad-foundstone", starting attack.
User password is "bradtest".
1 passwords in 0.00 seconds: 4424.78 passwords/second.
Bug 2
-----
$ ./eapmd5pass -r crash-4c384505c65c675a6a821f2a2f25ea967ec2a8c0 -w wordlist
==22182==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6310000147ff at pc \
0x000000403a7c bp 0x7ffe04164960 sp 0x7ffe04164950 READ of size 1 at 0x6310000147ff thread T0
#0 0x403a7b in assess_packet /fuzzing/eapmd5pass-orig/eapmd5pass.c:134
#1 0x7f13f28ec87c in pcap_offline_read (/lib64/libpcap.so.1+0x2187c)
#2 0x401c4b in main /fuzzing/eapmd5pass-orig/eapmd5pass.c:734
#3 0x7f13f20c8730 in __libc_start_main (/lib64/libc.so.6+0x20730)
#4 0x402018 in _start (/fuzzing/eapmd5pass-orig/eapmd5pass+0x402018)
The "offset" variable is -2 and "if (dot11->u1.fc.from_ds == 1 && dot11->u1.fc.to_ds == 1)" \
line is dereferencing out-of-bounds memory.
Here is a fix for ignoring invalid "offset" values,
diff --git a/eapmd5pass.c b/eapmd5pass.c
index 10b2a48..7a7d900 100644
--- a/eapmd5pass.c
+++ b/eapmd5pass.c
@@ -115,6 +115,9 @@ void assess_packet(char *user, struct pcap_pkthdr *h, u_int8_t *pkt)
dot11buf = (pkt + offset);
+ if (offset < 0)
+ return;
+
pcount++; /* Global packet counter */
if (__verbosity > 2) {
printf("Checking Frame: %ld....\n",pcount);
Affected Component: Function "assess_packet" in eapmd5pass.c
Affected Product Code Base: eapmd5pass - 1.4
Attack Type: Remote
Impact Denial of Service: true
Attack Vectors: Network: processing crafted network traffic, Local: opening a crafted .pcap \
file.
The Common Vulnerabilities and Exposures (CVE) project has assigned the ID
CVE-2017-11668 to this issue.
Summary: An out-of-bounds read flaw related to eapmd5pass.c:134 was found in
the way eapmd5pass handled processing of network packets. A remote attacker
could potentially use this flaw to crash the eapmd5pass process under certain
circumstances by generating specially crafted network traffic.
Bug 3
-----
$ ./eapmd5pass -r crash-9a3774d38a5959db160a2564c1487c57f2b336b9 -w wordlist
=================================================================
==22237==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000efe8 at pc \
0x000000403e45 bp 0x7ffd6b32b6c0 sp 0x7ffd6b32b6b0 READ of size 1 at 0x60200000efe8 thread T0
#0 0x403e44 in assess_packet /fuzzing/eapmd5pass-orig/eapmd5pass.c:211
#1 0x7f9d6c67b87c in pcap_offline_read (/lib64/libpcap.so.1+0x2187c)
#2 0x401c4b in main /fuzzing/eapmd5pass-orig/eapmd5pass.c:737
#3 0x7f9d6be57730 in __libc_start_main (/lib64/libc.so.6+0x20730)
#4 0x402018 in _start (/fuzzing/eapmd5pass-orig/eapmd5pass+0x402018)
This invalid read occurs on "if (dot2hdr->dsap != IEEE8022_SNAP ||
dot2hdr->ssap != IEEE8022_SNAP)" line. The packet length is too small, and it
isn't validated before the packet is consumed.
Here is a patch to fix this problem,
index 10b2a48..b125e53 100644
--- a/eapmd5pass.c
+++ b/eapmd5pass.c
@@ -115,6 +115,13 @@ void assess_packet(char *user, struct pcap_pkthdr *h, u_int8_t *pkt)
dot11buf = (pkt + offset);
+ /* Check minimum packet length */
+ if (offset + sizeof(struct dot11hdr) > h->caplen)
+ return;
+
pcount++; /* Global packet counter */
if (__verbosity > 2) {
printf("Checking Frame: %ld....\n",pcount);
Affected Component: Function "assess_packet" in eapmd5pass.c
Note: Similar validation checks should be added at other places in this function.
The Common Vulnerabilities and Exposures (CVE) project has assigned the ID
CVE-2017-11669 to this issue. This issue is different from CVE-2017-11668 (Bug
2).
Summary: An out-of-bounds read flaw related to eapmd5pass.c:211 was found in
the way eapmd5pass handled processing of network packets. A remote attacker
could potentially use this flaw to crash the eapmd5pass process under certain
circumstances by generating specially crafted network traffic.
Bug 4
-----
$ ./eapmd5pass -r crash-1717d491a7b9beba422fe919d524ab973fbe7266 -w wordlist
==23135==ERROR: AddressSanitizer: negative-size-param: (size=-1)
#0 0x7f9185d1b31b (/lib64/libasan.so.3+0x5f31b)
#1 0x402a4f in extract_eapusername /fuzzing/eapmd5pass-orig/eapmd5pass.c:459
#2 0x403f25 in extract_eapusername /fuzzing/eapmd5pass-orig/eapmd5pass.c:441
#3 0x403f25 in assess_packet /fuzzing/eapmd5pass-orig/eapmd5pass.c:284
#4 0x7f9185a9987c in pcap_offline_read (/lib64/libpcap.so.1+0x2187c)
#5 0x401c4b in main /fuzzing/eapmd5pass-orig/eapmd5pass.c:744
#6 0x7f9185275730 in __libc_start_main (/lib64/libc.so.6+0x20730)
#7 0x402018 in _start (/fuzzing/eapmd5pass-orig/eapmd5pass+0x402018)
This crash occurs in "memcpy(em->username, (eap+5), usernamelen)" line.
"usernamelen" is negative at this point in the execution flow. This bug can be
reliably used to crash eapmd5pass (non-ASan and ASan builds) remotely.
Here is a patch to fix this problem,
diff --git a/eapmd5pass.c b/eapmd5pass.c
index 10b2a48..b643d9b 100644
--- a/eapmd5pass.c
@@ -444,6 +454,9 @@ int extract_eapusername(uint8_t *eap, int len, struct eapmd5pass_data *em)
/* 5 bytes for EAP header information without identity information */
usernamelen = (eaplen - 5);
+ if (usernamelen < 0)
+ return 1;
+
usernamelen = (eaplen > sizeof(em->username))
? sizeof(em->username) : usernamelen;
memcpy(em->username, (eap+5), usernamelen);
Affected Component: Function "extract_eapusername" in eapmd5pass.c
The Common Vulnerabilities and Exposures (CVE) project has assigned the ID
CVE-2017-11670 to this issue.
Summary: An out-of-bounds read and write flaw was found in the way eapmd5pass
handled network traffic. A remote attacker could potentially use this flaw to
crash the eapmd5pass process by generating specially crafted network traffic.
--
Dhiru
["combined-fixes.diff" (text/plain)]
diff --git a/eapmd5pass.c b/eapmd5pass.c
index 10b2a48..d959a9c 100644
--- a/eapmd5pass.c
+++ b/eapmd5pass.c
@@ -115,6 +115,13 @@ void assess_packet(char *user, struct pcap_pkthdr *h, u_int8_t *pkt)
dot11buf = (pkt + offset);
+ if (offset < 0)
+ return;
+
+ /* Check minimum packet length */
+ if (offset + sizeof(struct dot11hdr) > h->caplen)
+ return;
+
pcount++; /* Global packet counter */
if (__verbosity > 2) {
printf("Checking Frame: %ld....\n",pcount);
@@ -197,6 +204,9 @@ void assess_packet(char *user, struct pcap_pkthdr *h, u_int8_t *pkt)
poffset += DOT2HDR_LEN;
plen -= DOT2HDR_LEN;
+ if (poffset + sizeof(struct ieee8022) > h->caplen)
+ return;
+
if (plen <= 0) {
if (__verbosity > 2) {
printf("\tDiscarding frame with partial 802.2 header.\n");
@@ -444,6 +454,9 @@ int extract_eapusername(uint8_t *eap, int len, struct eapmd5pass_data *em)
/* 5 bytes for EAP header information without identity information */
usernamelen = (eaplen - 5);
+ if (usernamelen < 0)
+ return 1;
+
usernamelen = (eaplen > sizeof(em->username))
? sizeof(em->username) : usernamelen;
memcpy(em->username, (eap+5), usernamelen);
@@ -684,7 +697,7 @@ int main(int argc, char *argv[])
}
/* Set non-blocking */
- if (pcap_setnonblock(p, PCAP_DONOTBLOCK, errbuf) != 0) {
+ if (!strlen(pcapfile) > 0 && pcap_setnonblock(p, PCAP_DONOTBLOCK, errbuf) != 0) {
fprintf(stderr, "Error placing pcap interface in non-blocking "
"mode.\n");
perror("pcap_setnonblock");
@@ -702,7 +715,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "Unable to determine offset from "
"radiotap header (%d).\n", offset);
usage();
- return(-1);
+ goto bailout;
}
break;
@@ -721,7 +734,7 @@ int main(int argc, char *argv[])
default:
fprintf(stderr, "Unrecognized datalink type %d.\n", datalink);
usage();
- return(-1);
+ goto bailout;
}
/* Loop for each packet received */
@@ -736,7 +749,7 @@ int main(int argc, char *argv[])
if (ret != 0) {
/* Error reading from packet capture file */
fprintf(stderr, "pcap_dispatch: %s\n", pcap_geterr(p));
- return -1;
+ goto bailout;
}
} else { /* live packet capture */
@@ -767,6 +780,8 @@ int main(int argc, char *argv[])
printf("Total packets observed: %ld\n", pcount);
}
+bailout:
+
pcap_close(p);
if (em.recovered_pass > 0) {
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic