Wednesday, September 26, 2012

My Favorite Exploit


XSS (Cross Site Scripting) is my personal favorite security hole. It's everywhere, on almost every site, and it's fun to exploit! I used to spend my evening scouring the top 500 sites on alexa for XSS vulnerabilities just for fun. In addition to that I did most of my testing manually. There are tools built to automate most XSS vulnerability tests, but that's no fun. This hacking spree taught me the foundations of JavaScript and web development in general. By developing intricate tunnel exploit schemes I learned so much about how the web operates at the user level and how bugs enable hackers to get in.

My endeavours got my name here: Google Security Hall Of Fame

Which led me to create this: http://gallery.zolmeister.com/ (click the page)

That page is my XSS gallery. The images are the websites favicons, with size relative to their ranking. I have saved nearly every one of the XSS vulnerabilities I have found by hand, which is now over 200. Most of the sites are ones that were unhelpful or just pissed me off in general and so I took a few minutes to find an XSS vulnerability in them (I almost never report these vulnerabilities). Some however (the big icons) are ones where I started at the top of a list of most popular sites and moved my way down, collecting vulnerabilities along the way. It's pretty scary actually, knowing that even the most high profile sites are vulnerable.

Saturday, September 8, 2012

How not to write a massively multi-player game

Welcome to Page Explorer!

Click here to join! (no longer up)
Click here (again) to join! (yes, bug)
Now hit the CAPS LOCK key (to toggle view state)
After you have joined here are the controls:

  • Ctrl = Jump
  • arrow keys = move
  • Down = Descend a level
  • Ctrl + up = pull up
  • CAPS LOCK = toggle game (visible/hidden)
  • T = chat (just start typing and the text will appear top-left, then enter to submit)
Want to explore somewhere else? Drag this link: Page Explorer to your bookmarks bar, then click on it when your on the site you want to join (may have to click it twice, also chrome blocks it in https pages).

"Wow this is so cool! How can I get the source?" - on github!

Alright, lets break it down!
A few words of warning before I begin, this game is one of my most poorly written and broken games of all. This was a great learning experience in what not to do with a game, and I hope that you will learn something too.

First let me explain how this app works on a general level.
  1. User injects script onto page
  2. script loads all the assets
  3. all assets load
  4. script connects using Socket.io to the master Node.js server
  5. The server puts the user in a room based on the website they're on
  6. users position, name, and animation state are sent to the server
  7. server relays info to all clients in room
  8. GO TO 6
This part actually makes sense, and what makes Page Explorer cool is that you can run it on any page you want. This also happens to be what makes it fail, due to different page layouts of the same site from different users makes them appear to float in mid air and other such bugs which are largely out of my control.

Ok lets start at the beginning of the code (or rather the first part that I wrote and where things wen't horribly wrong). I decided to write a skeletal animation system. Those look like this:
Basically a bunch of nodes connected to each other. This allows me to draw the player once and animate him freely. If you're confused, this video might help: http://www.youtube.com/watch?v=34cBGjCKkgU

The first step in skeletal animation is creating a skeletal map (here is where I messed up). Here is what mine looks like:

The issue here is that everything is absolute positioned instead of being relative to one another. The correct way to do it would have been to use a Polar system (angle, distance) instead of a Cartesian system (x,y).

 var skeleton=[{  
   "name": "root",  
   "rot": 0,  
   "x": 279,  
   "y": 266,  
   "skin": {},  
   "parent": -1,  
   "id": 0,  
   "children": [6, 7, 8]  
 }, {  
   "name": "head",  
   "rot": 0,  
   "x": 282,  
   "y": 150,  
   "skin": {  
     "self": {  
       "name":"head",  
       "x":0,  
       "y":-20  
     },  
     "bone": "neck"  
   },  
   "parent": 6,  
   "id": 1,  
   "children": []  
 },...  

My next step was creating an editor, in order to create everything (ie, draw the bones and connections and add skins etc.). Problem was that I was lazy. I ended up hard-coding the base skeletal system and the animation system involved saving a skeletal state to localstorage when done. There was no "undo" button, and I couldn't edit multiple animations at a time. To get it into my code I copy pasted the giant list of skeletal positions into my source. This is where spending just a bit more time in creating a good editor would have saved me tons of work. (I could post the source for my editor but i'd rather not... it's hideous).

My next mistake was in separating the user (you) from everybody else. I had to duplicate everything (physics, drawing, etc) in my code (that's bad - never duplicate code). This also caused me to keep all of the game code related to the player in one file (main.js - 651 lines) and then duplicate it in another file (socket.js - 173 lines). Yes, main.js should not contain all the code that it does and it was an absolute pain to debug.

My animation sequence seems ok at first, but it is definitely broken. Here is what it looks like:

 function movePlay(){  
   if(playQueue.length<2){  
     playing=false;  
   }  
   else if(sameFrame(playQueue[1],playQueue[0])){  
     playQueue.splice(0,1);  
     updatedQueue();  
   }  
   else{  
     for(var i in playQueue[0]){  
       var curS=playQueue[0][i];  
       var tarS=playQueue[1][i];//have to align within 60 frames  
       var xDistance=curS.x-tarS.x;  
       var yDistance=curS.y-tarS.y;  
       var rotDistance=curS.rot-tarS.rot;  
       var framesLeft=10-currentFrame%10;  
       if(curS.x!=tarS.x)  
         curS.x+=xDistance/framesLeft*-1;  
       if(curS.y!=tarS.y)  
         curS.y+=yDistance/framesLeft*-1;  
       if(curS.rot!=tarS.rot)  
         curS.rot+=rotDistance/framesLeft*-1;  
       if(framesLeft<1){  
         curS.y=tarS.y;  
         curS.x=tarS.x;  
         curS.rot=tarS.rot;  
       }  
     }  
   }  
 }  

The basis for this animation function is that it takes at least 2 frames (states of skeletons) and then motion-tweens them by one step when it's called. The issue (if it wasn't obvious) is that it doesn't support speed-change in tweens. This means that lets say I wanted the player to punch really fast (1 frame fist back, next frame fist forward), it would play really slow because my play-rate (10 steps - var framesLeft=10-currentFrame%10;) is constant. From one frame to the next is always the same amount of time. Instead, it should be set by the editor and be a value in the animation sequence (# steps the animation should take).

Another issue (which I didn't realize till too late) was my abundant use of global variables (maybe my separate var.js file should have given me a hint).

 player.height=500;  
 player.width=500;  
 var playC=player.getContext("2d");  
 var selectedBone;  
 var assetsList=["head", "left arm", "left foot", "left forearm", "left hand",   
 "left leg", "left thigh","neck","right arm","right foot","right forearm",  
 "right hand","right leg","right thigh","spine", "joint","joint2","none",  
 "hat1","hat2","hat3","hat4","hat5","hat6"];  
 var keysPressed=[];  
 var assetCount=0;  
 var assetCallback;  
 var assets={};  
 var playQueue=[];  
 var name=localStorage.name||prompt("name?");  
 localStorage.name=name;  
 var chats=[];  
 var hidden=true;  
 var chatting=false;  
 var currentChat="";  
 var passingThrough=false;  
 var others={};  
 var myHat=Math.floor(Math.random()*6)+1  
 var bgCtx=bgCanvas.getContext("2d");  
 var currentFrame=0;  
 var locked=false;  
 var showBone=false;  
 var jumping=true;  
 var climbing=false;  
 var grav=1;  
 var deltaTime=0;  
 var blocks=[];  
 var lastTimestamp=Date.now();  
 var me={  
   x:0,  
   y:0,  
   width:100,  
   height:100,  
   dir:"right"  
 }  

The solution to this is simple enough. I should have created a Game class which had these values associated with it, as well as separating values that control game state (ie. passingThrough, chatting, hidden etc.) from values controlling player state (jumping, climbing etc.).

Well, I hope that you found something useful in all that I did wrong. Bottom line is Don't Half-Ass Your Code. Do it right from the start (never say "I'll fix it later" or "I'll get back to it eventually" - especially in the beginning).

Cheers!

Tuesday, June 26, 2012

Javascript Golfing



 +

  
What is Javascript Golfing?
Well, Javascript golfing is the process of writing the smallest amount of javascript code to do something awesome. It tests your ability to reduce, reuse, and recycle for the purpose of achieving the tiniest footprint possible. Also, it's fun!
Note: All of these games and more can be found here: Games.Zolmeister.com

First attempt, Snake:
My first attempt at golfing was inspired by MXSnake (back when I didn't even know it was called golfing). Here is my version: tinySnake (686 bytes). Kind of large, not too pretty and nothing really special, except my key events which I think are quite unique.

 onkeydown=function(a){  
 q=a.which-38;  
 q%2?n=0:n=q-1;  
 q%2?e=q:e=0  
 }  

I realized that the key presses should be directly tied to the movement variables of the snake, so I used the keyCode itself to set the movement (I think it could be done even more elegantly, but it's a start).

Second attempt, Pong:
My second attempt at golfing was inspired by an article on hacker-news I read about, where someone made tron in 219 bytes(!). Instead of trying to best them though, I made Pong (451 bytes) instead. (Screen is blank until you hit a key, W and A for p1 movement and UP and DOWN for p2 movement) Sadly I don't have the original non-compressed code, but my technique for compression mimicked the tron game.

Third Attempt, Two Towers:


After feeling good about my pong implementation, I decided I wanted to make something new and original. I settled on a game where the player spawns objects to attack an enemy base. Another constraint I wanted to have was to keep it below 1KB (it's 1008 bytes currently), so that it could be compared to the applications at http://js1k.com (definitely check this out, there are some truly amazing apps people created). This time I did not lose the original non-compressed source:

 //chrome auto-generates accessors for objects with ids  
 <body><canvas id=c width=700></canvas>Buy:  
 <script>  
 C=c.getContext('2d')  
 money=time=level=1//multiple assignments in one statement reduces the use of semicolons  
 upgrade=.99  
 R=Math.random;//assign common functions to variables  
 enemies=[{size:50, x:650, speed:-1/1e99}]//use e for large values (1e3=1000) - saved 1 byte  
 friendlies=[{size:50, x:70, speed:0}]//use unique variable names for easy hand-minification  
 C.fillRect(0,0,c.width,c.height);  
 part1="<button onclick='";  
 part2="</button>"  
 doc=document  
 for(i=3;i<10;i++)  
      doc.write(part1+"buy("+i+")'>$"+i*10+part2);  
 //using ~~ instead of parseInt helps a lot  
 doc.write(" Upgrade: "+part1+"upgradeValue=~~(200/upgrade-200)*10+100;money-upgradeValue<0?i:(upgrade-=.05,money-=upgradeValue);this.innerHTML=upgradeValue'>"+upgrade*100+part2);  
 //keep functions to a minimum (the word function is expensive)  
 //the function below gets removed and the whole thing inserted in an onclick event  
 function buy(n){  
      n=n/upgrade*10  
      money-=n*upgrade;  
      money<0?money+=n:friendlies.push({size:~~(Math.pow(n,2)/250)+5,x:100,speed:60/n});  
 }  
 function animation(){  
      if(R()<.03)//AI code (random is your friend)  
           enemies.push({size:~~(R()*level)+7, x:650, speed:-(level-R())})  
   C.clearRect(0,0,700,300);  
   C.fillText("$"+~~money,9,9)  
   //concat both friendlies and enemies for updating the objects (drawing and moving)  
      g=[].concat(enemies,friendlies)  
      for (i in enemies){  
       for (j in friendlies){  
            //during minification, && and || can usually be replaced by & and | respectively  
        if(friendlies[j].x+friendlies[j].size>=enemies[i].x-enemies[i].size && enemies[i].size>0 && friendlies[j].size>0){  
         --friendlies[j].size<0?friendlies[j].size++:i;  
         enemies[i].size==1?money+=enemies[i].size:i;  
         --enemies[i].size<0?enemies[i].size++:i;  
         enemies[i].x-=enemies[i].speed;  
         friendlies[j].x-=friendlies[j].speed;  
         }  
       }}  
      for (i in g){  
                g[i].x+=g[i].speed  
                //I used negative speed values to differenciate between enemies and friendlies  
                C.fillStyle=g[i].speed<0?'#F10':'#10F';  
                C.save()  
                time+=.01  
                C.translate(g[i].x,150-g[i].size)  
                C.rotate(time*(g[i].speed<0?-1:1))  
                C.font=g[i].size+'pt txt';  
                //thanks http://js1k.com/2010-first/demo/750 for the inspiration to use unicode  
                C.fillText(String.fromCharCode(1161),g[i].size/2,g[i].size/2)  
                C.restore()  
           }  
      //inline if statements are better if doing one action  
      //friendlies[0].size==0?history.go():i;  
      //function are special  
      friendlies[0].size==0&&history.go();  
      //regular ifs are more eficient for more than 1 call  
      if(enemies[0].size==0)friendlies=[friendlies[0]],enemies[0].size=50,level++,money+=500;  
       money+=.25;  
       time+=.1  
 }  
 //put the function inside of quotes in the interval call later to save space  
 setInterval(animation,50)  
 </script>  

Finally, here are some tips for golfing:

Look at other peoples code. They come up with interesting tricks like this one (to remap the canvas calls to have shorter names):
 for($ in C=c.getContext('2d'))C[$[0]+$[6]]=C[$];  
-Source: Bouncing Beholder (This game is crazy-good, worth reading through the source)
Check out this tutorial on stackexchange.
Use a tool like jscrush after you hand-minify your code (and check that closure compiler won't help).
Good Luck!

Saturday, April 14, 2012

Zoggle

Welcome to my guide to Zoggle. Zoggle is not affiliated with Boggle.
Zoggle is available...
On my website Zoggle. (Works on iOS - add to home screen)
On Google+.

How to play:
The objective of the game is to score as many points as possible. Points are scored based on the length of the words.
Length : Points
3,4      = 1
5         = 2
6         = 3
7         = 5
8+       = 11

Words are made by connecting letters Horizontally, Vertically, or Diagonally (illustrated below).


Zoggle is a webapp that takes this game to a whole new level by having all players play at the the same time in the same game in real-time. This creates a whole host of tough problems to solve.

Problem #1, Real-Time Gaming Data In The Browser:
This wasn't actually a problem I had because I already had a solution in mind. The key to solving this problem is to use Node.js (with the Express.js web framework) and Websockets (socket.io), hosted on Amazon EC2.
Problem #2, The Board Solving Algorithm:
The computer generates a random board of letters in a 2-dimensional grid. The next step is to figure out all of the words possible for that given grid. For reference I looked at this page. My solution ended up being slower than the python implementation (200ms vs 80ms), but it was still fast enough to be production worthy.
The basic steps to my algorithm:
1. Reduce the size of the dictionary to only contain words possibly made by the grid. This basically consisted of removing all words that contained a letter not on the board. This took my dictionary from 100k, to ~2k.
2. Flood fill the board grid starting at the the first letter of the dictionary words to see if they can be made. Flood fill works by recursively "filling" adjacent grid cells. All this means is that I make sure that for example the 2nd filled grid cell contains the 2nd letter of the dictionary word, otherwise return.
Flood Fill Graphic:


Here is the code for checking to see if a word can fit on the grid:
function fitWord(x, y, cboard, tarWord, cword) {
  if (x >= boardWidth || x < 0 || y >= boardHeight || y < 0)// out of bounds
    return;
  if (cboard[x][y] == "")// visited space
    return;
  if (tarWord.indexOf(cword) == -1)
    return;
  var board = copyTwoDimentionalArray(cboard);
  var let = board[x][y];
  cword += let;
  if (cword == tarWord) {
    wordFit = true;
    return;
  }
  board[x][y] = "";
  fitWord(x + 1, y + 1, board, tarWord, cword);
  fitWord(x + 1, y - 1, board, tarWord, cword);
  fitWord(x - 1, y + 1, board, tarWord, cword);
  fitWord(x - 1, y - 1, board, tarWord, cword);
  fitWord(x, y + 1, board, tarWord, cword);
  fitWord(x, y - 1, board, tarWord, cword);
  fitWord(x + 1, y, board, tarWord, cword);
  fitWord(x - 1, y, board, tarWord, cword);
  return;
}

Problem #3, Cross-Platform CSS:
Since this is a custom webapp, and did not want to re-code (port) the game to iOS and Android, I had to change CSS to accommodate them. There are ways to do this with CSS only, however I found those ways to be inconsistent and unreliable. Instead I opted to detect via JavaScript.
navigator.userAgent.indexOf("Android") != -1
And then add the required CSS
var mobileCss=document.createElement("link");
  mobileCss.setAttribute("rel","stylesheet");
  mobileCss.setAttribute("href","/stylesheets/mobile.css");
  document.body.appendChild(mobileCss);
So far this has worked reliably for me. I did however achieve separate CSS for portrait mode vs landscape mode via CSS.
@media screen and (orientation:portrait)
@media screen and (orientation:landscape)
Problem #4, Touch detection on Android & iPhone:
Turns out that window.onmousemove doesn't work on mobile devices. Instead I had to use window.ontouchmove and re-write my board highlight detection to use elementFromPoint.
document.addEventListener("touchmove",function(e){
  e.preventDefault();
  var j = document.elementFromPoint(e.touches[0].pageX, e.touches[0].pageY);
    currentWord += j.innerText;
    currentWordUsed.push(j);
    j.parentNode.parentNode.setAttribute("class",
        "tileHighlight");
}, false);

Problem #5, CSS3 on Android:
Android, while it claims to support CSS3 in reality does not. It only supports animation of one property at a time. This can be seen at the end of a Zoggle game, where the game will fade out before it gets moved to the side. This is because it would get all choppy otherwise.
Special Notes:
Socket.io Configuration
io.configure('production', function() {
  io.enable('browser client minification'); // send minified client
  io.enable('browser client etag'); // apply etag caching logic based on version
  io.set('connect timeout',2000);//if connection fails, fall back in 2 seconds
  io.enable('browser client gzip'); // gzip the file
  io.set('log level', 1); // reduce logging
  io.set('transports', [ // enable all transports (optional if you want
              // flashsocket)
  'websocket', 'flashsocket', 'htmlfile', 'xhr-polling', 'jsonp-polling' ]);
});
app.js Caching
var cacheTime = 1000 * 60 * 60 * 1 * 1;// 1 hour
  app.use(express.static(__dirname + '/public', {
    maxAge : cacheTime
  }));

Custom 404
myapp/node_modules/express/node_modules/connect/lib/http.js
It specifies what express is doing with the 404 cases:

res.setHeader('Content-Type', 'text/plain');
res.end('Cannot ' + req.method + ' ' + req.url);
I changed this code to something like this:

res.setHeader('Content-Type', 'text/html');
res.render('errors/404', { title: 'Page not found'});