Vulnerabilities > CVE-2017-2801 - Out-of-bounds Read vulnerability in Botan Project Botan 2.0.1

047910
CVSS 7.5 - HIGH
Attack vector
NETWORK
Attack complexity
LOW
Privileges required
NONE
Confidentiality impact
PARTIAL
Integrity impact
PARTIAL
Availability impact
PARTIAL
network
low complexity
botan-project
CWE-125
nessus

Summary

A programming error exists in a way Randombit Botan cryptographic library version 2.0.1 implements x500 string comparisons which could lead to certificate verification issues and abuse. A specially crafted X509 certificate would need to be delivered to the client or server application in order to trigger this vulnerability.

Vulnerable Configurations

Part Description Count
Application
Botan_Project
1

Common Weakness Enumeration (CWE)

Common Attack Pattern Enumeration and Classification (CAPEC)

  • Overread Buffers
    An adversary attacks a target by providing input that causes an application to read beyond the boundary of a defined buffer. This typically occurs when a value influencing where to start or stop reading is set to reflect positions outside of the valid memory location of the buffer. This type of attack may result in exposure of sensitive information, a system crash, or arbitrary code execution.

Nessus

  • NASL familyDebian Local Security Checks
    NASL idDEBIAN_DLA-915.NASL
    descriptionA bug in X509 DN string comparisons could result in out of bound reads. This could result in information leakage, denial of service, or potentially incorrect certificate validation results. For Debian 7
    last seen2020-03-17
    modified2017-04-26
    plugin id99672
    published2017-04-26
    reporterThis script is Copyright (C) 2017-2020 and is owned by Tenable, Inc. or an Affiliate thereof.
    sourcehttps://www.tenable.com/plugins/nessus/99672
    titleDebian DLA-915-1 : botan1.10 security update
    code
    #%NASL_MIN_LEVEL 80502
    #
    # (C) Tenable Network Security, Inc.
    #
    # The descriptive text and package checks in this plugin were
    # extracted from Debian Security Advisory DLA-915-1. The text
    # itself is copyright (C) Software in the Public Interest, Inc.
    #
    
    include("compat.inc");
    
    if (description)
    {
      script_id(99672);
      script_version("3.7");
      script_set_attribute(attribute:"plugin_modification_date", value:"2020/03/12");
    
      script_cve_id("CVE-2017-2801");
    
      script_name(english:"Debian DLA-915-1 : botan1.10 security update");
      script_summary(english:"Checks dpkg output for the updated packages.");
    
      script_set_attribute(
        attribute:"synopsis", 
        value:"The remote Debian host is missing a security update."
      );
      script_set_attribute(
        attribute:"description", 
        value:
    "A bug in X509 DN string comparisons could result in out of bound
    reads. This could result in information leakage, denial of service, or
    potentially incorrect certificate validation results.
    
    For Debian 7 'Wheezy', these problems have been fixed in version
    1.10.5-1+deb7u3.
    
    We recommend that you upgrade your botan1.10 packages.
    
    NOTE: Tenable Network Security has extracted the preceding description
    block directly from the DLA security advisory. Tenable has attempted
    to automatically clean and format it as much as possible without
    introducing additional issues."
      );
      script_set_attribute(
        attribute:"see_also",
        value:"https://lists.debian.org/debian-lts-announce/2017/04/msg00034.html"
      );
      script_set_attribute(
        attribute:"see_also",
        value:"https://packages.debian.org/source/wheezy/botan1.10"
      );
      script_set_attribute(attribute:"solution", value:"Upgrade the affected packages.");
      script_set_cvss_base_vector("CVSS2#AV:N/AC:L/Au:N/C:P/I:P/A:P");
      script_set_cvss_temporal_vector("CVSS2#E:U/RL:OF/RC:C");
      script_set_cvss3_base_vector("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H");
      script_set_cvss3_temporal_vector("CVSS:3.0/E:U/RL:O/RC:C");
      script_set_attribute(attribute:"exploitability_ease", value:"No known exploits are available");
      script_set_attribute(attribute:"exploit_available", value:"false");
    
      script_set_attribute(attribute:"plugin_type", value:"local");
      script_set_attribute(attribute:"cpe", value:"p-cpe:/a:debian:debian_linux:botan1.10-dbg");
      script_set_attribute(attribute:"cpe", value:"p-cpe:/a:debian:debian_linux:libbotan-1.10-0");
      script_set_attribute(attribute:"cpe", value:"p-cpe:/a:debian:debian_linux:libbotan1.10-dev");
      script_set_attribute(attribute:"cpe", value:"cpe:/o:debian:debian_linux:7.0");
    
      script_set_attribute(attribute:"patch_publication_date", value:"2017/04/25");
      script_set_attribute(attribute:"plugin_publication_date", value:"2017/04/26");
      script_end_attributes();
    
      script_category(ACT_GATHER_INFO);
      script_copyright(english:"This script is Copyright (C) 2017-2020 and is owned by Tenable, Inc. or an Affiliate thereof.");
      script_family(english:"Debian Local Security Checks");
    
      script_dependencies("ssh_get_info.nasl");
      script_require_keys("Host/local_checks_enabled", "Host/Debian/release", "Host/Debian/dpkg-l");
    
      exit(0);
    }
    
    
    include("audit.inc");
    include("debian_package.inc");
    
    
    if (!get_kb_item("Host/local_checks_enabled")) audit(AUDIT_LOCAL_CHECKS_NOT_ENABLED);
    if (!get_kb_item("Host/Debian/release")) audit(AUDIT_OS_NOT, "Debian");
    if (!get_kb_item("Host/Debian/dpkg-l")) audit(AUDIT_PACKAGE_LIST_MISSING);
    
    
    flag = 0;
    if (deb_check(release:"7.0", prefix:"botan1.10-dbg", reference:"1.10.5-1+deb7u3")) flag++;
    if (deb_check(release:"7.0", prefix:"libbotan-1.10-0", reference:"1.10.5-1+deb7u3")) flag++;
    if (deb_check(release:"7.0", prefix:"libbotan1.10-dev", reference:"1.10.5-1+deb7u3")) flag++;
    
    if (flag)
    {
      if (report_verbosity > 0) security_hole(port:0, extra:deb_report_get());
      else security_hole(0);
      exit(0);
    }
    else audit(AUDIT_HOST_NOT, "affected");
    
  • NASL familyDebian Local Security Checks
    NASL idDEBIAN_DSA-3939.NASL
    descriptionAleksandar Nikolic discovered that an error in the x509 parser of the Botan crypto library could result in an out-of-bounds memory read, resulting in denial of service or an information leak if processing a malformed certificate.
    last seen2020-06-01
    modified2020-06-02
    plugin id102446
    published2017-08-14
    reporterThis script is Copyright (C) 2017-2018 and is owned by Tenable, Inc. or an Affiliate thereof.
    sourcehttps://www.tenable.com/plugins/nessus/102446
    titleDebian DSA-3939-1 : botan1.10 - security update
    code
    #
    # (C) Tenable Network Security, Inc.
    #
    # The descriptive text and package checks in this plugin were  
    # extracted from Debian Security Advisory DSA-3939. The text 
    # itself is copyright (C) Software in the Public Interest, Inc.
    #
    
    include("compat.inc");
    
    if (description)
    {
      script_id(102446);
      script_version("3.6");
      script_cvs_date("Date: 2018/11/10 11:49:38");
    
      script_cve_id("CVE-2017-2801");
      script_xref(name:"DSA", value:"3939");
    
      script_name(english:"Debian DSA-3939-1 : botan1.10 - security update");
      script_summary(english:"Checks dpkg output for the updated package");
    
      script_set_attribute(
        attribute:"synopsis", 
        value:"The remote Debian host is missing a security-related update."
      );
      script_set_attribute(
        attribute:"description", 
        value:
    "Aleksandar Nikolic discovered that an error in the x509 parser of the
    Botan crypto library could result in an out-of-bounds memory read,
    resulting in denial of service or an information leak if processing a
    malformed certificate."
      );
      script_set_attribute(
        attribute:"see_also",
        value:"https://packages.debian.org/source/jessie/botan1.10"
      );
      script_set_attribute(
        attribute:"see_also",
        value:"https://www.debian.org/security/2017/dsa-3939"
      );
      script_set_attribute(
        attribute:"solution", 
        value:
    "Upgrade the botan1.10 packages.
    
    For the oldstable distribution (jessie), this problem has been fixed
    in version 1.10.8-2+deb8u2.
    
    For the stable distribution (stretch), this problem has been fixed
    prior to the initial release."
      );
      script_set_cvss_base_vector("CVSS2#AV:N/AC:L/Au:N/C:P/I:P/A:P");
      script_set_cvss_temporal_vector("CVSS2#E:U/RL:OF/RC:C");
      script_set_cvss3_base_vector("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H");
      script_set_cvss3_temporal_vector("CVSS:3.0/E:U/RL:O/RC:C");
      script_set_attribute(attribute:"exploitability_ease", value:"No known exploits are available");
      script_set_attribute(attribute:"exploit_available", value:"false");
    
      script_set_attribute(attribute:"plugin_type", value:"local");
      script_set_attribute(attribute:"cpe", value:"p-cpe:/a:debian:debian_linux:botan1.10");
      script_set_attribute(attribute:"cpe", value:"cpe:/o:debian:debian_linux:8.0");
    
      script_set_attribute(attribute:"patch_publication_date", value:"2017/08/12");
      script_set_attribute(attribute:"plugin_publication_date", value:"2017/08/14");
      script_end_attributes();
    
      script_category(ACT_GATHER_INFO);
      script_copyright(english:"This script is Copyright (C) 2017-2018 and is owned by Tenable, Inc. or an Affiliate thereof.");
      script_family(english:"Debian Local Security Checks");
    
      script_dependencies("ssh_get_info.nasl");
      script_require_keys("Host/local_checks_enabled", "Host/Debian/release", "Host/Debian/dpkg-l");
    
      exit(0);
    }
    
    
    include("audit.inc");
    include("debian_package.inc");
    
    
    if (!get_kb_item("Host/local_checks_enabled")) audit(AUDIT_LOCAL_CHECKS_NOT_ENABLED);
    if (!get_kb_item("Host/Debian/release")) audit(AUDIT_OS_NOT, "Debian");
    if (!get_kb_item("Host/Debian/dpkg-l")) audit(AUDIT_PACKAGE_LIST_MISSING);
    
    
    flag = 0;
    if (deb_check(release:"8.0", prefix:"botan1.10-dbg", reference:"1.10.8-2+deb8u2")) flag++;
    if (deb_check(release:"8.0", prefix:"libbotan-1.10-0", reference:"1.10.8-2+deb8u2")) flag++;
    if (deb_check(release:"8.0", prefix:"libbotan1.10-dev", reference:"1.10.8-2+deb8u2")) flag++;
    
    if (flag)
    {
      if (report_verbosity > 0) security_hole(port:0, extra:deb_report_get());
      else security_hole(0);
      exit(0);
    }
    else audit(AUDIT_HOST_NOT, "affected");
    

Seebug

bulletinFamilyexploit
description### Summary A programming error exists in a way Randombit Botan cryptographic library version 2.0.1 implements x500 string comparisons which could lead to certificate verification issues and abuse. A specially crafted X509 certificate would need to be delivered to the client or server application in order to trigger this vulnerability. ### Tested Versions Randombit Botan 2.0.1 ### Product URLs https://botan.randombit.net/ ### CVSSv3 Score 6.5 - CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:L ### CWE CWE-125: Out-of-bounds Read ### Details Botan is a C++ cryptographic library that implements the basis for practical systems that require TLS, PKIX certificate handling, password hashing or other cryptographic primitives. There exists a programming error in code related to x509 distinguished name parsing. Namely, an x509 DN comparison function can lead to out of bounds memory access leading to unexpected results, information disclosure or potential denial of service. The vulnerability is located in the overloaded equality comparison function `Botan::x500_name_cmp`: ``` bool x500_name_cmp(const std::string& name1, const std::string& name2) { auto p1 = name1.begin(); auto p2 = name2.begin(); while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1; [1] while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2; while(p1 != name1.end() && p2 != name2.end()) { if(Charset::is_space(*p1)) [2] { if(!Charset::is_space(*p2)) [3] return false; while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1; [4] while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2; [5] if(p1 == name1.end() && p2 == name2.end()) [6] return true; } if(!Charset::caseless_cmp(*p1, *p2)) [7] return false; ++p1; [8] ++p2; } while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1; while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2; if((p1 != name1.end()) || (p2 != name2.end())) return false; return true; } ``` First, at [1], initiall whitespaces are skipped. Then, strings are compared byte by byte in a loop while checking for whitespace at [2]. If a space occurs in the first string [2] and the second too [3], those are again skipped at [4] and [5]. Then, at [6], if both have reached an end, true is returned. If not, another comparison is made at [7] and if it passes, the pointers are increased at [8]. The vulnerability lies in the way whitespaces are handeled. If we are comparing two strings which are initially the same up to a space character, we would enter while loops at [4] and [5]. Now, if one string contains a NULL byte after that space, and the other has spaces until its end, the check at [6] won’t be true, because only the second string would point to its end. However, both are actually pointing at a NULL byte, which means the check at [7] will still hold true, and pointers are once again increased at [8]. Then when the loop rolls around, one of the pointers can point outside its allocated buffer, leading to unexpected behaviour. A specially crafted x509 certificate with specific x509 DN strings for subject and issuer fields can be created. Example strings that satisfy the above conditions are: ``` String 1: AA\x20\x00AAAAAAAAAA String 2: AA\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20 ``` Notice that both are the same length, begin with same characters up until space after which the first is terminated and the second has spaces till the end. Because of the way these pieces of certificate are copied from the x509 file to their memory buffers, the first string’s length won’t be 3, that is, it won’t be terminated at the first NULL. With careful control over X509 distinguished names contents and depending on memory layout in the target application, it could be possible to craft a certificate where equality checks could pass or fail. Also, a discrepancy between a way these malformed strings are handled in Botan and other x509 libraries could lead to other types of abuse, possibly not unlike the famed CVE-2009-2408. The vulnerability can be triggered with the supplied example x509 certificate. ### Crash Information Address sanitizer output: ``` botan/botan cert_info --ber cert1.der 2>&1| asan_symbolize -d ================================================================= ==15015==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60300000dfa3 at pc 0x7f027ec92e85 bp 0x7ffdf452fe60 sp 0x7ffdf452fe58 READ of size 1 at 0x60300000dfa3 thread T0 #0 0x7f027ec92e84 in Botan::x500_name_cmp(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) botan/./src/lib/utils/parsing.cpp:232 #1 0x7f027ec92e84 in ?? ??:0 #2 0x7f027e269f2a in Botan::operator==(Botan::X509_DN const&, Botan::X509_DN const&) botan/./src/lib/asn1/x509_dn.cpp:153 #3 0x7f027e269f2a in ?? ??:0 #4 0x7f027ed8b8f4 in Botan::X509_Certificate::force_decode() botan/./src/lib/x509/x509cert.cpp:149 #5 0x7f027ed8b8f4 in ?? ??:0 #6 0x7f027ed85263 in Botan::X509_Object::do_decode() botan/./src/lib/x509/x509_obj.cpp:235 #7 0x7f027ed85263 in ?? ??:0 #8 0x7f027ed877b1 in X509_Certificate botan/./src/lib/x509/x509cert.cpp:50 #9 0x7f027ed877b1 in ?? ??:0 #10 0x5fcc93 in Botan_CLI::Cert_Info::go() botan/./src/cli/x509.cpp:85 #11 0x5fcc93 in ?? ??:0 #12 0x520ed5 in Botan_CLI::Command::run(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) botan/./src/cli/cli.h:229 #13 0x520ed5 in ?? ??:0 #14 0x51ca4f in main botan/./src/cli/main.cpp:60 #15 0x51ca4f in ?? ??:0 #16 0x7f027d16982f in __libc_start_main /build/glibc-Qz8a69/glibc-2.23/csu/../csu/libc-start.c:291 #17 0x7f027d16982f in ?? ??:0 #18 0x42e328 in _start ??:? #19 0x42e328 in ?? ??:0 0x60300000dfa3 is located 0 bytes to the right of 19-byte region [0x60300000df90,0x60300000dfa3) allocated by thread T0 here: #0 0x4ce458 in __interceptor_malloc ??:? #1 0x4ce458 in ?? ??:0 #2 0x7f027f296e77 in operator new(unsigned long) ??:? #3 0x7f027f296e77 in ?? ??:0 #4 0x7f027e272283 in std::pair<std::__decay_and_strip<Botan::OID const&>::__type, std::__decay_and_strip<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::__type> std::make_pair<Botan::OID const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(Botan::OID const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/stl_pair.h:281 (discriminator 4) #5 0x7f027e272283 in void Botan::multimap_insert<Botan::OID, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::multimap<Botan::OID, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<Botan::OID>, std::allocator<std::pair<Botan::OID const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >&, Botan::OID const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) botan/build/include/botan/internal/stl_util.h:79 (discriminator 4) #6 0x7f027e272283 in ?? ??:0 #7 0x7f027e2671eb in Botan::X509_DN::get_attributes[abi:cxx11]() const botan/./src/lib/asn1/x509_dn.cpp:78 (discriminator 1) #8 0x7f027e2671eb in ?? ??:0 #9 0x7f027e269d49 in Botan::operator==(Botan::X509_DN const&, Botan::X509_DN const&) botan/./src/lib/asn1/x509_dn.cpp:138 (discriminator 1) #10 0x7f027e269d49 in ?? ??:0 #11 0x7f027ed8b8f4 in Botan::X509_Certificate::force_decode() botan/./src/lib/x509/x509cert.cpp:149 #12 0x7f027ed8b8f4 in ?? ??:0 #13 0x7f027ed85263 in Botan::X509_Object::do_decode() botan/./src/lib/x509/x509_obj.cpp:235 #14 0x7f027ed85263 in ?? ??:0 #15 0x7f027ed877b1 in X509_Certificate botan/./src/lib/x509/x509cert.cpp:50 #16 0x7f027ed877b1 in ?? ??:0 #17 0x5fcc93 in Botan_CLI::Cert_Info::go() botan/./src/cli/x509.cpp:85 #18 0x5fcc93 in ?? ??:0 #19 0x520ed5 in Botan_CLI::Command::run(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) botan/./src/cli/cli.h:229 #20 0x520ed5 in ?? ??:0 #21 0x51ca4f in main botan/./src/cli/main.cpp:60 #22 0x51ca4f in ?? ??:0 #23 0x7f027d16982f in __libc_start_main /build/glibc-Qz8a69/glibc-2.23/csu/../csu/libc-start.c:291 #24 0x7f027d16982f in ?? ??:0 SUMMARY: AddressSanitizer: heap-buffer-overflow (botan/libbotan-2.so.0+0xc38e84) Shadow bytes around the buggy address: 0x0c067fff9ba0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff9bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff9bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff9bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff9be0: fa fa fa fa fa fa 00 00 03 fa fa fa fd fd fd fa =>0x0c067fff9bf0: fa fa 00 00[03]fa fa fa fd fd fd fa fa fa 00 00 0x0c067fff9c00: 00 04 fa fa fd fd fd fd fa fa 00 00 00 03 fa fa 0x0c067fff9c10: fd fd fd fd fa fa 00 00 00 03 fa fa fd fd fd fd 0x0c067fff9c20: fa fa 00 00 05 fa fa fa fd fd fd fa fa fa 00 00 0x0c067fff9c30: 07 fa fa fa fd fd fd fa fa fa 00 00 01 fa fa fa 0x0c067fff9c40: 00 00 00 fa fa fa fd fd fd fa fa fa fd fd fd fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==15015==ABORTING ``` ### Mitigation Adding another check which tests if either string is at the end while the other is not, which would make them different, is enough to resolve this vulnerability: ``` diff --git a/src/lib/utils/parsing.cpp b/src/lib/utils/parsing.cpp index 8fd2ccc..ce4b02f 100644 --- a/src/lib/utils/parsing.cpp +++ b/src/lib/utils/parsing.cpp @@ -240,6 +240,11 @@ bool x500_name_cmp(const std::string& name1, const std::string& name2) if(p1 == name1.end() && p2 == name2.end()) return true; + if(p1 == name1.end() || p2 == name2.end()) + return false; } if(!Charset::caseless_cmp(*p1, *p2)) return false; ``` ### Timeline * 2017-03-16 - Vendor Disclosure * 2017-04-28 - Public Release ### CREDIT * Discovered by Aleksandar Nikolic of Cisco Talos.
idSSV:96525
last seen2017-11-19
modified2017-09-19
published2017-09-19
reporterRoot
titleRandombit Botan Library X509 Certificate Validation Bypass Vulnerability(CVE-2017-2801)

Talos

idTALOS-2017-0294
last seen2019-05-29
published2017-04-28
reporterTalos Intelligence
sourcehttp://www.talosintelligence.com/vulnerability_reports/TALOS-2017-0294
titleRandombit Botan Library X509 Certificate Validation Bypass Vulnerability