How SnapABug works – and what they should do

I just saw the SnapABug website, and was quite impressed, until I actually tried to submit a bug. Unrestricted access to my computer, why would I grant that to an unknown applet? And why do you even require unrestricted access to all files etc. on my computer to create a screenshot?

Well, I delved into the application and found the answers – they could of course have done with a more restrictive permission.

First I found the JavaScript file. The interesting part here was to find, that they actually inserted a java-applet in the corner of the application (in the startWebCapture-function):

startWebCapture:function() {
    	document.getElementById('SnapABug_Applet').style.display = 'block';
    	document.getElementById('SnapABug_Applet').innerHTML = 
	    '<applet style="position:absolute;background-position-x:0px;background-position-y:0px;display:inline;font-size:2px;width:300px;height:2px;" name="SnapABug_Applet" code="webCaptureApplet.WebCaptureApplet.class" codebase="' + baseURL + '/" archive="sWebCaptureApplet.jar" width="200" height="2" mayscript>'
        + '<param name="h" value="' + this.getWindowHeight() + '">'
        + '<param name="w" value="' + this.getWindowWidth() + '">'
        + '<param name="c" value="' + caseId + '">'
        + '<param name="d" value="300">'
        + '</applet>';
    }

This applet (JAR file) is passed the viewport size and a case ID (used for sending the screenshot directly to the server). The source for this applet is easily accessible using e.g. JD.

The interesting part here is how they actually find the offset of the viewport. Getting a screenshot of all the available screen devices is quite easily managed through the GraphicsEnvironment class iterating through all screen GraphicsDevice‘s to make it work on multi-screen setups. But finding the browser-window on the screenshot bitmap is a bit tricky – the browser chrome can look in all different sorts of ways, the only thing that we can be sure of is, that the viewport is rectangular and has the size given to the applet by JavaScript. If we could find just one of the corners of the viewport… Well, they solve this in a very low-tech way by via the above JavaScript embedding the Java Applet in the top-left corner at 2*200px and then in the paint(Graphics g)-function of the applet draw a certain pattern in that area:

  ...
  BigInteger bi = new BigInteger("11010100110010110011", 2);
  ...
  public void paint(Graphics g)
  {
    System.out.println("paint: drawing corner");
    drawCornerCode(g);
  ...
  private void drawCornerCode(Graphics g)
  {
    g.clearRect(0, 0, 100, 10);
    for (int i = 0; i < 20; ++i) {
      if (this.bi.testBit(19 - i))
        g.setColor(Color.black);
      else {
        g.setColor(Color.white);
      }
      g.drawLine(i * 3, 0, i * 3, 10);
      g.drawLine(i * 3 + 1, 0, i * 3 + 1, 10);
      g.drawLine(i * 3 + 2, 0, i * 3 + 2, 10);
    }
  }

This draws a black and white striped pattern in the top left corner of the browser which functions somewhat like a bar code. Then, when JavaScript asks the applet to create a screenshot, the applet runs through every pixel of every screen and sees, if from that pixel the bar code follows:

      for (int j = 0; (j < devices.length) && (!(detected)); ++j) {
        GraphicsDevice device = devices[j];
        GraphicsConfiguration config = device.getDefaultConfiguration();
        Rectangle bounds = config.getBounds();
        ...
          screenshot = rbt.createScreenCapture(bounds);
        ...
        for (int y = 0; (y < screenshot.getHeight()) && (!(detected)); ++y) {
          for (int x = 0; (x < screenshot.getWidth() - 21) && (!(detected)); x += 2)
          {
            if (screenshot.getRGB(x, y) != Color.black.getRGB()) {
              continue;
            }
            for (int i = 0; i < 20; ++i) {
              if (((this.bi.testBit(19 - i)) && (screenshot.getRGB(x + i * 3, y) == Color.black.getRGB())) || (
                (!(this.bi.testBit(19 - i))) && (screenshot.getRGB(x + i * 3, y) == Color.white.getRGB())))
              {
                detected = true;
              } else {
                detected = false;
                break;
              }
            }
            if (detected) {
              System.out.println("detected x: " + x + " y: " + y);
              detectedX = x;
              detectedY = y;
            }
          }

This is actually quite brilliant, but of course not a revolution – just a smart simple way of using what’s available.

What is the problem then? Unrestricted access is the problem! I never allow unrestricted access to any applet unless I can’t do without it and trust the publisher. For this tool, neither criteria is fulfilled. After having checked the source code, I have allowed the applet, but not before – unrestricted access is simply way more than they should ever have. They need access for two things:

  1. AWTPermission – access to the screens (which also gives access to create frameless windows and access to the visible state of all other programs running).
  2. SocketPermission – access to cross-domain posting of the final image.

Of these permissions, only the first one is really necessary. The latter could be solved by requiring implementers to have a script locally on their own domain, that could process submitted images or simply forward them.

If the applet only asked permission to these two – or even better only AWTPermission – it would be way more trustworthy. As Sun says about the AllPermission:

java.security.AllPermission specifies all permissions in the system for all possible targets and actions. This permission should be used only during testing because it grants permission to run with all security restrictions disabled as if there were no security manager.

Only during testing! Never in deployed applets from an unknown company expecting major adoption across third-party websites. The permission, that I particularly don’t like any applet not needing it to have is FilePermission. They should not be able to read any files on my computer or write any – they don’t need it!

If it does get implemented on many sites, this jar file will then be very very interesting to phishers and scammers, as they could use this (if they replaced the file with their own) to infiltrate many computers with key-loggers, malware and anything else. This is not the case, as the applet is digitally signed, so modifying would require re-signing it, which would require re-authorizing it by end users.

But nevertheless – a very interesting feedback mechanism, that definitely has potential.

Source-code published under fair use. All rights belong to Timzon and only published here as-is without any warranty, obligations or any claims of copyright on my behalf.

No related posts.

Category: Java, Security 8 comments »

8 Responses to “How SnapABug works – and what they should do”

  1. TimZon

    Hej,

    Thank you for very detailed analysis of our solution.

    We decided to implement a signed applet because we cannot expect each user of our application to change their policy settings.
    This is beyond what the average (non-technical) person could or would do, signing the applet was the easier and most user friendly solution.
    Our identity is clearly stated on the applet certificate (also verified by the certificate issuer) and as you attested our code is not malicious in any way.
    As far, I we know, once an applet is signed it is automatically granted AllPermissions, unless there is a specific client-side policy in place for that Applet.
    If you know of another way to limit permissions while still providing a certifiable and simple solution for the end user, we would love to learn about it.

    If a more restrictive environment is necessary, SnapABug permissions can be limited as follow:
    grant {
    permission java.awt.AWTPermission “accessClipboard”;
    permission java.awt.AWTPermission “accessEventQueue”;
    permission java.awt.AWTPermission “createRobot”;
    permission java.awt.AWTPermission “readDisplayPixels”;
    permission java.net.SocketPermission “snapabug.appspot.com”, “connect”;
    permission java.lang.RuntimePermission “modifyThread”;
    permission java.lang.RuntimePermission “modifyThreadGroup”;
    };

    Thanks,
    The TimZon team.

  2. semanticist

    Do any browsers actually show what permissions are being requested to the user? I have never seen an applet request anything other than “unrestricted access” to my computer.

  3. Barklund

    Please see my follow-up post Why signed applet trust is a stupid question (and why SnapABug is not to blame).

  4. My daily readings 04/21/2010 « Strange Kite

    [...] How SnapABug works – and what they should do | Barklund.org [...]

  5. Ondrej Medek

    It there any opensource alternative for this applet? Thanks.

  6. Barklund

    @Ondrej: No, not as far as I know, but it is quite simple to re-create the desired functionality based on the above description.

    I have however also suggested another use-case for this kind of applet as outlined in this post, so if you do create one, you might want to keep that idea in mind as well :)

  7. Randy

    There is an easier way for the applet to get the dimensions of the browser window to capture that image.
    The javascript code can just get the x and y coordinates of the browser and the height and width, then pass that value (of the browser) to the applet.

  8. Matt Bearman

    You may be interested to to see my website feedback app (BugMuncher) which allows users to take screenshots of websites using only JavaScript, no flash, canvas, or applets.

    This means no need to grant permissions and no security/privacy implications.

    I’d love to hear what you think.

    Thanks,
    Matt Bearman
    BugMuncher Founder


Leave a Reply



Back to top

     

Get Adobe Flash playerPlugin by wpburn.com wordpress themes