Wednesday, 13 June 2012

Safe from XSS?

For last year Ruxcon's CTF (even if I ended up not using it) and for PentesterLab's training, I wanted to build something around the exploitation of Cross Site Scripting... I just wanted a typical client to browse a website automatically and get XSS'ed... But it's not as easy as it looks since pop-ups will block the execution flow.

I first thought of something around Browser automation with Watir or Selenium, unfortunately, if an alert is triggered your browser is blocked and you need to manually click the pop-up. You can find your way around by killing the browser but if you have 50 people trying to XSS your victim, you won't run all their payloads... That just doesn't work and is not reliable enough :/

You can probably write a small JavaScript interpreter but it's a lot of work and you won't get something as good as a browser...

You can disable alert, prompt and confirm in the page served, but the CTF players will find a way around this...

The good solution came from Surf from suckless.org. Surf is a browser composed of only 1000 lines of C. It's really easy to modify it and to make it do whatever you want. If you have some time, you should probably read its source code, it will give you a good inside on how Webkit works.

To avoid the pop-ups created by the browser, we will need to handle the following events:
  • script-alert
  • script-confirm
  • script-prompt



To do that, we can create a dummy function scriptalert:
static gboolean * scriptalert (WebKitWebView *v, WebKitWebFrame *f, Client *c){
  printf("%s\n", c);
  return TRUE;
}


And connect the events to this function:
  g_signal_connect(G_OBJECT(c->view), "script-alert", G_CALLBACK(scriptalert), c);
  g_signal_connect(G_OBJECT(c->view), "script-confirm", G_CALLBACK(scriptalert), c);
  g_signal_connect(G_OBJECT(c->view), "script-prompt", G_CALLBACK(scriptalert), c);


And that's it, we now have a browser which won't pop-up a new window and can be used as a XSS victim for CTFs or cool exercises...

The nice thing is that the handling of cookies can be easily modify by patching the newrequest or the setcookie functions...

As a side note, it's really easy to have an automatic logging of all requests and responses by adding the following code to the setup function:

  SoupLogger *logger;  
  [...]
  logger = soup_logger_new(static_cast<SoupLoggerLogLevel>(SOUP_LOGGER_LOG_BODY),-1);
  soup_session_add_feature(s,logger);

  

No comments: