High severityNVD Advisory· Published May 5, 2014· Updated May 6, 2026
CVE-2013-6418
CVE-2013-6418
Description
PyWBEM 0.7 and earlier uses a separate connection to validate X.509 certificates, which allows man-in-the-middle attackers to spoof a peer via an arbitrary certificate.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
pywbemPyPI | < 0.8.1 | 0.8.1 |
Affected products
1Patches
1f7599379b26afixed TOCTOU error when validating peer's certificate
2 files changed · +109 −60
trunk/cim_http.py+81 −49 modified@@ -28,6 +28,7 @@ data and interpret the result. ''' +from M2Crypto import SSL, Err import sys, string, re, os, socket, getpass from stat import S_ISSOCK import cim_obj @@ -74,8 +75,26 @@ def parse_url(url): return host, port, ssl +def get_default_ca_certs(): + """ + Try to find out system path with ca certificates. This path is cached and + returned. If no path is found out, None is returned. + """ + if not hasattr(get_default_ca_certs, '_path'): + for path in ( + '/etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt', + '/etc/ssl/certs', + '/etc/ssl/certificates'): + if os.path.exists(path): + get_default_ca_certs._path = path + break + else: + get_default_ca_certs._path = None + return get_default_ca_certs._path + def wbem_request(url, data, creds, headers = [], debug = 0, x509 = None, - verify_callback = None): + verify_callback = None, ca_certs = None, + no_verification = False): """Send XML data over HTTP to the specified url. Return the response in XML. Uses Python's build-in httplib. x509 may be a dictionary containing the location of the SSL certificate and key @@ -105,10 +124,49 @@ def __init__(self, host, port=None, strict=None): class HTTPSConnection(HTTPBaseConnection, httplib.HTTPSConnection): def __init__(self, host, port=None, key_file=None, cert_file=None, - strict=None): + strict=None, ca_certs=None, verify_callback=None): httplib.HTTPSConnection.__init__(self, host, port, key_file, cert_file, strict) - + self.ca_certs = ca_certs + self.verify_callback = verify_callback + + def connect(self): + "Connect to a host on a given (SSL) port." + self.sock = socket.create_connection((self.host, self.port), + self.timeout, self.source_address) + if self._tunnel_host: + self.sock = sock + self._tunnel() + ctx = SSL.Context('sslv23') + if self.cert_file: + ctx.load_cert(self.cert_file, keyfile=self.key_file) + if self.ca_certs: + ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, + depth=9, callback=verify_callback) + if os.path.isdir(self.ca_certs): + ctx.load_verify_locations(capath=self.ca_certs) + else: + ctx.load_verify_locations(cafile=self.ca_certs) + try: + self.sock = SSL.Connection(ctx, self.sock) + # Below is a body of SSL.Connection.connect() method + # except for the first line (socket connection). We want to preserve + # tunneling ability. + self.sock.addr = (self.host, self.port) + self.sock.setup_ssl() + self.sock.set_connect_state() + ret = self.sock.connect_ssl() + if self.ca_certs: + check = getattr(self.sock, 'postConnectionCheck', + self.sock.clientPostConnectionCheck) + if check is not None: + if not check(self.sock.get_peer_cert(), self.host): + raise Error('SSL error: post connection check failed') + return ret + except ( Err.SSLError, SSL.SSLError, SSL.SSLTimeoutError + , SSL.Checker.WrongHost), arg: + raise Error("SSL error: %s" % arg) + class FileHTTPConnection(HTTPBaseConnection, httplib.HTTPConnection): def __init__(self, uds_path): httplib.HTTPConnection.__init__(self, 'localhost') @@ -117,64 +175,36 @@ def connect(self): self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self.sock.connect(self.uds_path) - host, port, ssl = parse_url(url) + host, port, use_ssl = parse_url(url) key_file = None cert_file = None - if ssl: - - if x509 is not None: - cert_file = x509.get('cert_file') - key_file = x509.get('key_file') - - if verify_callback is not None: - addr_ind = 0 - # Temporary exception store - addr_exc = None - # Get a list of arguments for socket(). - addr_list = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM) - for addr_ind in xrange(len(addr_list)): - family, socktype, proto, canonname, sockaddr = addr_list[addr_ind] - try: - from OpenSSL import SSL - ctx = SSL.Context(SSL.SSLv3_METHOD) - ctx.set_verify(SSL.VERIFY_PEER, verify_callback) - ctx.set_default_verify_paths() - # Add the key and certificate to the session - if cert_file is not None and key_file is not None: - ctx.use_certificate_file(cert_file) - ctx.use_privatekey_file(key_file) - s = SSL.Connection(ctx, socket.socket(family, socktype, proto)) - s.connect((host, port)) - s.do_handshake() - s.shutdown() - s.close() - addr_exc = None - break - except (socket.gaierror, socket.error), arg: - # Could not perform connect() call, store the exception object for - # later use. - addr_exc = arg - continue - except socket.sslerror, arg: - raise Error("SSL error: %s" % (arg,)) - - # Did we try all the addresses from getaddrinfo() and no successful - # connection performed? - if addr_exc: - raise Error("Socket error: %s" % (addr_exc),) + if use_ssl and x509 is not None: + cert_file = x509.get('cert_file') + key_file = x509.get('key_file') numTries = 0 localAuthHeader = None tryLimit = 5 + if isinstance(data, unicode): + data = data.encode('utf-8') data = '<?xml version="1.0" encoding="utf-8" ?>\n' + data + if not no_verification and ca_certs is None: + ca_certs = get_default_ca_certs() + elif no_verification: + ca_certs = None + local = False - if ssl: - h = HTTPSConnection(host, port = port, key_file = key_file, - cert_file = cert_file) + if use_ssl: + h = HTTPSConnection(host, + port = port, + key_file = key_file, + cert_file = cert_file, + ca_certs = ca_certs, + verify_callback = verify_callback) else: if url.startswith('http'): h = HTTPConnection(host, port = port) @@ -216,6 +246,8 @@ def connect(self): h.putheader('PegasusAuthorization', 'Local "%s"' % locallogin) for hdr in headers: + if isinstance(hdr, unicode): + hdr = hdr.encode('utf-8') s = map(lambda x: string.strip(x), string.split(hdr, ":", 1)) h.putheader(urllib.quote(s[0]), urllib.quote(s[1]))
trunk/cim_operations.py+28 −11 modified@@ -27,7 +27,7 @@ from types import StringTypes from xml.dom import minidom import cim_obj, cim_xml, cim_http, cim_types -from cim_obj import CIMClassName, CIMInstanceName, CIMInstance, CIMClass, NocaseDict +from cim_obj import CIMClassName, CIMInstanceName, CIMInstance, CIMClass from datetime import datetime, timedelta from tupletree import dom_to_tupletree, xml_to_tupletree from tupleparse import parse_cim @@ -78,27 +78,40 @@ class WBEMConnection(object): the request before it is sent, and the reply before it is unpacked. - verify_callback is used to verify the server certificate. - It is passed to OpenSSL.SSL.set_verify, and is called during the SSL - handshake. verify_callback should take five arguments: A Connection - object, an X509 object, and three integer variables, which are in turn - potential error number, error depth and return code. verify_callback - should return True if verification passes and False otherwise. + verify_callback is used to verify the server certificate. It is passed to + M2Crypto.SSL.Context.set_verify, and is called during the SSL handshake. + verify_callback should take five arguments: An SSL Context object, an X509 + object, and three integer variables, which are in turn potential error + number, error depth and return code. verify_callback should return True if + verification passes and False otherwise. The value of the x509 argument is used only when the url contains 'https'. x509 must be a dictionary containing the keys 'cert_file' and 'key_file'. The value of 'cert_file' must consist of the filename of an certificate and the value of 'key_file' must consist of a filename containing the private key belonging to the public key that is part of the certificate in cert_file. + + ca_certs specifies where CA certificates for verification purposes are + located. These are trusted certificates. Note that the certificates have to + be in PEM format. Either it is a directory prepared using the c_rehash tool + included with OpenSSL or an pemfile. If None, default system path will be + used. + + no_verification allows to disable peer's verification. This is insecure and + should be avoided. If True, peer's certificate is not verified and ca_certs + argument is ignored. """ def __init__(self, url, creds = None, default_namespace = DEFAULT_NAMESPACE, - x509 = None, verify_callback = None): + x509 = None, verify_callback = None, ca_certs = None, + no_verification = False): self.url = url self.creds = creds self.x509 = x509 self.verify_callback = verify_callback + self.ca_certs = ca_certs + self.no_verification = no_verification self.last_request = self.last_reply = '' self.default_namespace = default_namespace self.debug = False @@ -164,7 +177,9 @@ def imethodcall(self, methodname, namespace, **params): resp_xml = cim_http.wbem_request(self.url, req_xml.toxml(), self.creds, headers, x509 = self.x509, - verify_callback = self.verify_callback) + verify_callback = self.verify_callback, + ca_certs = self.ca_certs, + no_verification = self.no_verification) except cim_http.AuthError: raise except cim_http.Error, arg: @@ -321,7 +336,9 @@ def is_embedded(obj): resp_xml = cim_http.wbem_request(self.url, req_xml.toxml(), self.creds, headers, x509 = self.x509, - verify_callback = self.verify_callback) + verify_callback = self.verify_callback, + ca_certs = self.ca_certs, + no_verification = self.no_verification) except cim_http.Error, arg: # Convert cim_http exceptions to CIMError exceptions raise CIMError(0, str(arg)) @@ -811,7 +828,7 @@ def InvokeMethod(self, MethodName, ObjectName, **params): # Convert zero or more PARAMVALUE elements into dictionary - output_params = NocaseDict() + output_params = {} for p in result: if p[1] == 'reference':
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
16- sourceforge.net/p/pywbem/code/627/nvdVendor Advisory
- github.com/advisories/GHSA-f9q5-46qg-74x4ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2013-6418ghsaADVISORY
- seclists.org/oss-sec/2013/q4/531nvdWEB
- sourceforge.net/p/pywbem/code/627ghsaWEB
- sourceforge.net/p/pywbem/mailman/message/31757312ghsaWEB
- www.oracle.com/technetwork/topics/security/bulletinjan2016-2867206.htmlnvdWEB
- bugzilla.redhat.com/show_bug.cginvdWEB
- github.com/pypa/advisory-database/tree/main/vulns/pywbem/PYSEC-2014-93.yamlghsaWEB
- github.com/pywbem/pywbem/commit/f7599379b26a685d772b2620a16316130f46c474ghsaWEB
- web.archive.org/web/20161110005052/http://secunia.com/advisories/58327ghsaWEB
- web.archive.org/web/20200228040356/http://www.securityfocus.com/bid/64544ghsaWEB
- www.suse.com/support/update/announcement/2014/suse-su-20140580-1.htmlnvdWEB
- secunia.com/advisories/58327nvd
- sourceforge.net/p/pywbem/mailman/message/31757312/nvd
- www.securityfocus.com/bid/64544nvd
News mentions
0No linked articles in our index yet.