High severityNVD Advisory· Published Aug 23, 2013· Updated Apr 29, 2026
CVE-2013-1909
CVE-2013-1909
Description
The Python client in Apache Qpid before 2.2 does not verify that the server hostname matches a domain name in the subject's Common Name (CN) or subjectAltName field of the X.509 certificate, which allows man-in-the-middle attackers to spoof SSL servers via an arbitrary valid certificate.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
qpid-pythonPyPI | < 0.22 | 0.22 |
Affected products
17cpe:2.3:a:apache:qpid:*:*:*:*:*:*:*:*+ 15 more
- cpe:2.3:a:apache:qpid:*:*:*:*:*:*:*:*range: <=0.20
- cpe:2.3:a:apache:qpid:0.10:*:*:*:*:*:*:*
- cpe:2.3:a:apache:qpid:0.11:*:*:*:*:*:*:*
- cpe:2.3:a:apache:qpid:0.12:*:*:*:*:*:*:*
- cpe:2.3:a:apache:qpid:0.13:*:*:*:*:*:*:*
- cpe:2.3:a:apache:qpid:0.14:*:*:*:*:*:*:*
- cpe:2.3:a:apache:qpid:0.15:*:*:*:*:*:*:*
- cpe:2.3:a:apache:qpid:0.16:*:*:*:*:*:*:*
- cpe:2.3:a:apache:qpid:0.17:*:*:*:*:*:*:*
- cpe:2.3:a:apache:qpid:0.18:*:*:*:*:*:*:*
- cpe:2.3:a:apache:qpid:0.19:*:*:*:*:*:*:*
- cpe:2.3:a:apache:qpid:0.5:*:*:*:*:*:*:*
- cpe:2.3:a:apache:qpid:0.6:*:*:*:*:*:*:*
- cpe:2.3:a:apache:qpid:0.7:*:*:*:*:*:*:*
- cpe:2.3:a:apache:qpid:0.8:*:*:*:*:*:*:*
- cpe:2.3:a:apache:qpid:0.9:*:*:*:*:*:*:*
- cpe:2.3:o:redhat:enterprise_mrg:2.0:*:*:*:*:*:*:*
Patches
17d8f51791c49NO-JIRA: add SSL test that verifies hostname in certificate
2 files changed · +74 −2
qpid/messaging/endpoints.py+5 −0 modified@@ -122,6 +122,10 @@ def __init__(self, url=None, **options): @param ssl_certfile: file with client's public (eventually priv+pub) key (PEM format) @type ssl_trustfile: str @param ssl_trustfile: file trusted certificates to validate the server + @type ssl_skip_hostname_check: bool + @param ssl_skip_hostname_check: disable verification of hostname in + certificate. Use with caution - disabling hostname checking leaves you + vulnerable to Man-in-the-Middle attacks. @rtype: Connection @return: a disconnected Connection @@ -170,6 +174,7 @@ def __init__(self, url=None, **options): self.ssl_keyfile = options.get("ssl_keyfile", None) self.ssl_certfile = options.get("ssl_certfile", None) self.ssl_trustfile = options.get("ssl_trustfile", None) + self.ssl_skip_hostname_check = options.get("ssl_skip_hostname_check", False) self.client_properties = options.get("client_properties", {}) self.options = options
qpid/messaging/transports.py+69 −2 modified@@ -53,7 +53,7 @@ def close(self): try: from ssl import wrap_socket, SSLError, SSL_ERROR_WANT_READ, \ - SSL_ERROR_WANT_WRITE + SSL_ERROR_WANT_WRITE, CERT_REQUIRED, CERT_NONE except ImportError: ## try the older python SSL api: @@ -69,6 +69,15 @@ def __init__(self, conn, host, port): ssl_certfile = conn.ssl_certfile if ssl_certfile and not ssl_keyfile: ssl_keyfile = ssl_certfile + + # this version of SSL does NOT perform certificate validation. If the + # connection has been configured with CA certs (via ssl_trustfile), then + # the application expects the certificate to be validated against the + # supplied CA certs. Since this version cannot validate, the peer cannot + # be trusted. + if conn.ssl_trustfile: + raise SSLError("This version of Python does not support verification of the peer's certificate.") + self.ssl = ssl(self.socket, keyfile=ssl_keyfile, certfile=ssl_certfile) self.socket.setblocking(1) @@ -95,7 +104,39 @@ class tls(SocketTransport): def __init__(self, conn, host, port): SocketTransport.__init__(self, conn, host, port) - self.tls = wrap_socket(self.socket, keyfile=conn.ssl_keyfile, certfile=conn.ssl_certfile, ca_certs=conn.ssl_trustfile) + if conn.ssl_trustfile: + validate = CERT_REQUIRED + else: + validate = CERT_NONE + + self.tls = wrap_socket(self.socket, keyfile=conn.ssl_keyfile, + certfile=conn.ssl_certfile, + ca_certs=conn.ssl_trustfile, + cert_reqs=validate) + + if validate == CERT_REQUIRED and not conn.ssl_skip_hostname_check: + match_found = False + peer_cert = self.tls.getpeercert() + if peer_cert: + peer_names = [] + if 'subjectAltName' in peer_cert: + for san in peer_cert['subjectAltName']: + if san[0] == 'DNS': + peer_names.append(san[1].lower()) + if 'subject' in peer_cert: + for sub in peer_cert['subject']: + while isinstance(sub, tuple) and isinstance(sub[0],tuple): + sub = sub[0] # why the extra level of indirection??? + if sub[0] == 'commonName': + peer_names.append(sub[1].lower()) + for pattern in peer_names: + if _match_dns_pattern( host.lower(), pattern ): + #print "Match found %s" % pattern + match_found = True + break + if not match_found: + raise SSLError("Connection hostname '%s' does not match names from peer certificate: %s" % (host, peer_names)) + self.socket.setblocking(0) self.state = None @@ -146,5 +187,31 @@ def close(self): # this closes the underlying socket self.tls.close() + def _match_dns_pattern( hostname, pattern ): + """ For checking the hostnames provided by the peer's certificate + """ + if pattern.find("*") == -1: + return hostname == pattern + + # DNS wildcarded pattern - see RFC2818 + h_labels = hostname.split(".") + p_labels = pattern.split(".") + + while h_labels and p_labels: + if p_labels[0].find("*") == -1: + if p_labels[0] != h_labels[0]: + return False + else: + p = p_labels[0].split("*") + if not h_labels[0].startswith(p[0]): + return False + if not h_labels[0].endswith(p[1]): + return False + h_labels.pop(0) + p_labels.pop(0) + + return not h_labels and not p_labels + + TRANSPORTS["ssl"] = tls TRANSPORTS["tcp+tls"] = tls
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
12- svn.apache.org/viewvcnvdPatchWEB
- issues.apache.org/jira/browse/QPID-4918nvdPatchWEB
- secunia.com/advisories/53968nvdVendor Advisory
- secunia.com/advisories/54137nvdVendor Advisory
- github.com/advisories/GHSA-3g2p-7c6p-vj8cghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2013-1909ghsaADVISORY
- qpid.apache.org/releases/qpid-0.22/release-notes.htmlnvdWEB
- rhn.redhat.com/errata/RHSA-2013-1024.htmlnvdWEB
- github.com/apache/qpid-python/commit/7d8f51791c4949404d78f1083f465b7b4c8e954bghsaWEB
- github.com/pypa/advisory-database/tree/main/vulns/qpid-python/PYSEC-2013-25.yamlghsaWEB
- web.archive.org/web/20140722191407/http://secunia.com/advisories/53968ghsaWEB
- web.archive.org/web/20140722194233/http://secunia.com/advisories/54137ghsaWEB
News mentions
0No linked articles in our index yet.