python / python/cpython

CRLF Injection vulnerability in "email.mime.multipart" > "MIMEMultipart" > "add_header()"

Ouverte
#100,612 0 commentaires 1 réaction 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

topic-email type-bug type-security
Langage dominant
Python
Étoiles
77.2k
Forks
36k
Métriques de merge des PR
Métriques de PR en attente

Description

Summary

I found CRLF Injection ( File Content Injection / (Potential) Tampering file extension ) Vulnerability in email.mime.multipart > class MIMEMultipart > add_header().

This problem is caused by the lack of escaping of "filename" in Multipart > Mail.
Normally, the following three characters are escaped

  • \r --> \\r
  • \n --> \\n
  • " --> \"
    However, the method in question does not escape \r\n
    ( " (double-quote) is escaped. " --> \" )

Therefore, if a crafted file name is inserted, CRLF Injection will occur in the Content-Disposition header of multipart body.

My calculated CVSS:
Score: 3.1 (Low)
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:L/A:N


PoC:

OS: macOS Monterey (v12.6.1)
Python ver: v3.10.3
PoC Code:
(please edit filepath)

from email.mime.application import MIMEApplication
def main():
  filepath = "/Users/XXXXXXXXXX/Desktop/example.txt"
  # If \r\n (CRLF) is present, the file will fail to load (on mac OS).
  with open(filepath, "rb") as f:
    mb = MIMEApplication(f.read())
  disposition_filename = "malicious_test.sh\r\n.txt"
  # If \r\n (CRLF) is present, the contents of the file can be Injected.
  mb.add_header("Content-Disposition", "attachment", filename=disposition_filename)
  print(mb)
if __name__ == '__main__':
  main()

Output:

Content-Type: application/octet-stream
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="malicious_test.sh
.txt"
IyEvYmluL2Jhc2gKCmVjaG8gImhlbGxvIg==

Injected Line:

Content-Disposition: attachment; filename="malicious_test.sh
.txt"


Affect

This problem is very limited.
The reason for this is that if [ \r, \n ] are included when a file is opened, an Exception will be thrown.

with open(filepath, "rb") as f:

However, it is not always safe to do so, since the file name may be given by an external parameter, DB, etc.
In addition, data can be added to the header content within Multipart, allowing for a variety of attacks.

It may be possible to insert multiple Content-Dispositions, falsify the filename, or inject malicious shell code after making the file .sh .


Reference:

As far as I can tell, the following service systems escape [ \r \n " ] to [ \\r \\n \" ]


The Python PSRT team has agreed to published this information.

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par le chemin email.mime.multipart MIMEMultipart.add_header() et reproduisez la PoC fournie avec un filename contenant CRLF. Suivez la manière dont le filename est sérialisé dans l’en-tête Content-Disposition, puis ajoutez une couverture de régression pour le comportement signalé ; le travail est terminé lorsqu’un CRLF forgé ne peut pas créer de lignes d’en-tête supplémentaires et que le comportement MIME existant reste intact.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
security
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
38/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.