Hello again.

In a not so recent web application security audit I’ve encountered an interesting email validation library. The target application, which shall remain unnamed, used golang’s net/mail#ParseAddress package to validate POSTed email addresses in their signup process for their validity.

Although the target application validates email addresses and avoided an XSS vulnerability in the rendering of said email addresses, I thought this would be a great opportunity for me to build a small lab environment to demonstrate what could’ve happened when the email address would have been rendered on the frontend without further validation or sanitization.

Your turn, lab time!

If you want to give it a shot before I spoil the beans, head over to cydave/rfc5322fun and set up the lab:

1
2
3
git clone https://github.com/cydave/rfc5322fun.git && cd rfc5322fun
docker build . -t rfc5322fun
docker run -p127.0.0.1:8080:8080 --rm -it docker.io/library/rfc5322fun

The beans

Now, whether or not you played with the lab and found a solution, here are the beans.

The RFC’s Appendix A.5. White Space, Comments, and Other Oddities reads:

White space, including folding white space, and comments can be inserted between many of the tokens of fields. Taking the example from A.1.3, white space and comments can be inserted into all of the fields.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
 From: Pete(A nice \) chap) <pete(his account)@silly.test(his host)>
 To:A Group(Some people)
      :Chris Jones <c@(Chris's host.)public.example>,
          joe@example.org,
   John <jdoe@one.test> (my dear friend); (the end of the group)
 Cc:(Empty list)(start)Hidden recipients  :(nobody(that I know))  ;
 Date: Thu,
       13
         Feb
           1969
       23:32
                -0330 (Newfoundland Time)
 Message-ID:              <testabcd.1234@silly.test>

 Testing.

Email addresses can contain comments! According to the ABNF notation, this allows for most characters one would need to forge a simple XSS payload:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
   FWS             =   ([*WSP CRLF] 1*WSP) /  obs-FWS
                                          ; Folding white space

   ctext           =   %d33-39 /          ; Printable US-ASCII
                       %d42-91 /          ;  characters not including
                       %d93-126 /         ;  "(", ")", or "\"
                       obs-ctext

   ccontent        =   ctext / quoted-pair / comment

   comment         =   "(" *([FWS] ccontent) [FWS] ")"

   CFWS            =   (1*([FWS] comment) [FWS]) / FWS

The payload

Tinkering for a few seconds, we come up with a very simplistic XSS payload in our email address that, according to net/mail#ParseAddress is perfectly valid:

xss@example.com(<img src='x' onerror='alert(document.location)'>)

‘Til next time.