CVE-2019-16056 (Python, published 2019-09-06T18:15Z)
Description: value: An issue was discovered in Python through 2.7.16, 3.x through 3.5.7, 3.6.x through 3.6.9, and 3.7.x through 3.7.4. The email module wrongly parses email addresses that contain multiple @ characters. An application that uses the email module and implements some kind of checks on the From/To headers of a message could be tricked into accepting an email address that should be denied. An attack may be the same as in CVE-2019-11340; however, this CVE applies to Python more generally.
Severity: MEDIUM (CVSS v3 base score: 7.5)
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/python/cpython
Files changed:
Lib/email/_header_value_parser.py
Lib/email/_parseaddr.py
Lib/test/test_email/test__header_value_parser.py
Lib/test/test_email/test_email.py
Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst
Commit message: bpo-34155: Dont parse domains containing @ (GH-13079)



Before:
    
        >>> email.message_from_string('From: a@malicious.org@important.com', policy=email.policy.default)['from'].addresses
        (Address(display_name='', username='a', domain='malicious.org'),)
    
        >>> parseaddr('a@malicious.org@important.com')
        ('', 'a@malicious.org')
    
    After:
    
        >>> email.message_from_string('From: a@malicious.org@important.com', policy=email.policy.default)['from'].addresses
        (Address(display_name='', username='', domain=''),)
    
        >>> parseaddr('a@malicious.org@important.com')
        ('', 'a@')




https://bugs.python.org/issue34155

Vulnerable code:
        return EMPTYSTRING.join(aslist) + self.getdomain()

Fixed code:
    if value and value[0] == '@':
        raise errors.HeaderParseError('Invalid Domain')
        domain = self.getdomain()
        if not domain:
            # Invalid domain, return an empty address instead of returning a
            # local part to denote failed parsing.
            return EMPTYSTRING
        return EMPTYSTRING.join(aslist) + domain
            elif self.field[self.pos] == '@':
                # bpo-34155: Don't parse domains with two `@` like
                # `a@malicious.org@important.com`.
                return EMPTYSTRING
    def test_get_addr_spec_multiple_domains(self):
        with self.assertRaises(errors.HeaderParseError):
            parser.get_addr_spec('star@a.star@example.com')

        with self.assertRaises(errors.HeaderParseError):
            parser.get_addr_spec('star@a@example.com')

        with self.assertRaises(errors.HeaderParseError):
            parser.get_addr_spec('star@172.17.0.1@example.com')

    def test_parseaddr_multiple_domains(self):
        self.assertEqual(
            utils.parseaddr('a@b@c'),
            ('', '')
        )
        self.assertEqual(
            utils.parseaddr('a@b.c@c'),
            ('', '')
        )
        self.assertEqual(
            utils.parseaddr('a@172.17.0.1@c'),
            ('', '')
        )

Fix parsing of invalid email addresses with more than one ``@`` (e.g. a@b@c.com.) to not return the part before 2nd ``@`` as valid email address. Patch by maxking & jpic.