Posts Tagged 'Tips'

May 29, 2013

Tips from the Abuse Department: To Catch a Predator

We've all seen the emails exclaiming, "THE KING HAS SENT YOU 1,000,000$ US DOLLARS," or "I NEED A PERSONAL ASSISTANT PAYING 500$ A WEEK." Do people actually fall for these? The answer is YES, many do. They think, "What risk is there replying to this email and possibly getting $1,000,000 or even a fraction of that?" As it turns out, there's a lot of risk.

As the senior manager of SoftLayer's abuse department, I know all about these kinds of scams, and I thought I'd reply to one of those emails to show what the interaction usually looks like and explain how the scam works.

---------------------------------------------
From: "Freddy Scammer" <scammer@address>
To: "Freddy Scammer" <scammer@address>
Subject: PA URGENTLY NEEDED

Hi, I am looking for a Personal Assistant, Kindly let me know if you are interested, and i can send you more details. Thank you

Freddy Scammer
---------------------------------------------

First, notice that my address email address isn't listed in the TO field or even the CC field. I must be BCC'd along with many others. I've changed the scammer's fake name to a more fitting name, and I'll use masculine pronouns when I talk about "him." According to our friends over at 419scam.org, this guy has been flagged as a scammer using the same name and email address. The name he provided actually belongs to a company that produces lamps as well as an American historian who focuses on colonization, decolonization and African history.

In the initial message, you'll see that there's no "all or nothing" proposition. Just like any scam, the scammer requests and provides information slowly to reel in a victim.

I replied back:

---------------------------------------------
From: <MY-EMAIL-ADDRESS>
To: <scammer@address>
Subject: RE: PA URGENTLY NEEDED

Doing What?
---------------------------------------------

I wanted to keep it short to see if I could get him to tell me more. He didn't disappoint:

---------------------------------------------
From: Freddy Scammer <scammer@address>
To: <MY-EMAIL-ADDRESS>
Subject: Re: PA URGENTLY NEEDED

Hello

Thanks for your reply, I got your email through the Chamber of Commerce directory. I am looking for someone who can handle my business errands during his or her spare time. I need your service because I am constantly traveling abroad on a missionary trip to build homes for orphaned children and doing other business as we are franchise company into alot of things.

Responsibilities:
1. Receive my mail and drop them off. {Your location doesn't matter as long as you have a post office nearby}
2. Pay my bills.
3. pay our workers on a regular basis

I would have love to meet with you to discuss this job in more detail, but I am currently away on a missionary trip. If you decide to accept the position, please read the employment requirements listed below.
REQUIREMENTS:
A. You are an honest and trustworthy citizen.
B. You need to be able to check your email regular and answer calls.

The pay is $500 weekly and you are entitled to other additional incentives after 1 month if you are hardworking. First, If I were to mail you a payment to
pay people that are needed to and your payment for your service, where would you want it mailed to?

Secondly, how would you like your name to appear on the payment? Note, payment would come in form of Check.

Provide me with the following details below to get started.

Full Name:
Complete Address(No PO Box allowed):
City:
State:
Country:
Zip Code:
Home Phone:
Cell Phone:
Age:
Occupation(If any):
Alternative Email if available:

Awaiting your prompt reply.
---------------------------------------------

Sounds easy enough right? Well it is easy. Who couldn't use an extra $500 a week! But there are a few problems here. If this sounds a lot like a "money mule" (or money laundering) type of situation, that's because it is! A money mule is a person who transfers money acquired illegally (e.g., stolen) in person, through a courier service, or electronically, on behalf of others. The mule is paid for their services, typically a small part of the money transferred.

Money mules are often dupes recruited on-line for what they think is legitimate employment, not aware that the money they are transferring is the product of crime. The money is transferred from the mule's account to the scam operator, typically in another country. Similar techniques are used to transfer illegal merchandise.

After a quick Google search for a few of the sentences in his message, I found out that this guy is low-balling me! He's offering $600 a week in other listings ... I'm hurt! I replied to see if I could get him off script:

---------------------------------------------
From: <MY-EMAIL-ADDRESS>
To: <scammer@address>
Subject: RE: PA URGENTLY NEEDED

So all I have to do is receive packages and re-ship them to where you tell me to,, also receive payments and cash it out and re-pay workers? How will I be paying them, what method? How often will I have to mail packages out and how big are they, who will pay for shipping?
---------------------------------------------

He was quick to respond:

---------------------------------------------
From: Freddy Scammer <scammer@address>
To: <MY-EMAIL-ADDRESS>
Subject: Re: PA URGENTLY NEEDED

Your going to be receiving payment mostly and it has already been paid for, for the shipping . All you have to do is receive and go ahead and cash it ....... Then i will tell you what to do with the money or whoever to pay with it. got me?
---------------------------------------------

Color me amazed. All I have to do is receive a check and cash it?! What luck!

---------------------------------------------
From: <MY-EMAIL-ADDRESS>
To: <scammer@address>
Subject: RE: PA URGENTLY NEEDED
Ok seems easy enough. But I only have a PO BOX, why would this be a problem? I currently don't have a permanent address as I'm staying with a friend trying to get back on my feet and I'm not on the house lease so I can't receive mail here. Is that going to be a problem?
---------------------------------------------

Now none of this is true, but I knew that this would throw Freddy off of his game. Most scammers don't allow a post office box because they don't want to be scammed ... What's to prevent the "victim" from renting a P.O. Box for a month, getting the check, cashing it and cancelling that P.O. Box? That possibility is a risk that scammers don't like to take. There have even been reports that in some instances, the scammers will send goons to your house if you don't hold up your end of the deal.

This whole underground world that you can get quickly and easily sucked into is exciting isn't it?

---------------------------------------------
From: Freddy Scammer <scammer@address>
To: <MY-EMAIL-ADDRESS>
Subject: Re: PA URGENTLY NEEDED

I'm afraid a PO BOX will not suffice, you can perhaps use a family members address and we can start the payments as soon as you send me the info. Please reply with the most urgent intent as I only have a few positions left as my assistant.
---------------------------------------------

At this point, I didn't bother emailing back. It's pretty obvious how easy it could be for someone down on their luck financially (or just bored) to get sucked into this type of scam. What's actually happening here is that the scammer wants to send money from a compromised account to the victim's legit account and then have the victim withdraw 90%-95% of the money and send it to another account that the bad guy has legitimate access to (probably over-seas). The victim would get to keep 5% for their troubles. Often the checks that are sent won't clear, so a victim thinks the funds are in his/her account ... Money is forwarded to the scammer from the victim's legitimate account and it clears before the funds from the scammer's deposited check disappear.

In some instances, scammers will buy high-priced items online with stolen credit card numbers and have those items shipped to the victim's house. The victim will then ship them to a different address. The bad guy has nothing to lose, and the victim takes all the risk.

The challenge with pursuing these scammers from a legal perspective is that they are often based in regions and areas out of the jurisdiction of our law enforcement authorities. As a result, they usually aren't caught, and they just move along to their next unsuspecting victim.

If you receive a "too good to be true" email from someone you don't know, let me spoil the surprise for you: It's not true.

-Dody

Categories: 
March 7, 2013

Script Clip: HTML5 Audio Player with jQuery Controls

HTML5 and jQuery provide mind-blowing functionality. Projects that would have taken hours of development and hundreds of lines of code a few years ago can now be completed in about the time it'll take you to read this paragraph. If you wanted to add your own audio player on a web page in the past, what would it have involved? Complicated elements? Flash (*shudders*)? It was so complicated that most developers just linked to the audio file, and the user just downloaded the file to play it locally. With HTML5, an embedded, cross-browser audio player can be added to a page with five lines of code, and if you want to get really fancy, you can easily use jQuery to add some custom controls.

If you've read any of my previous blogs, you know that I love when I find little code snippets that make life as a web developer easier. My go-to tools in that pursuit are HTML5 and jQuery, so when I came across this audio player, I knew I had to share. There are some great jQuery plugins to play music files on a web page, but they can be major overkill for a simple application if you have to include comprehensive controls and themes. Sometimes you just want something simple without all of that overhead:

Oooh... Ahhh...

That song — Pop Bounce by SoftLayer's very own Chris Interrante — is written in five simple lines of HTML5 code:

<audio style="width:550px; margin: 0 auto; display:block;" controls>
  <source src="http://cdn.softlayer.com/innerlayer/Interrante-PopBounce.ogg" type="audio/ogg">
  <source src="http://cdn.softlayer.com/innerlayer/Interrante-PopBounce.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>

If IE 9+, Chrome 6+, Firefox 3.6+, Safari 5+ and Opera 10+ would all agree on supported file formats for the <audio> tag, the code snippet would be even smaller. I completely geek out over it every time I look at it and remember the days of yore. As you can see, the HTML5 application has some simple default controls: Play, Pause, Scan to Time, etc. As a developers, I couldn't help but look for a to spice it up a little ... What if we want to fire an event when the user plays, pauses, stops or takes any other action with the audio file? jQuery!

Make sure your jQuery include is in the <head> of your page:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>

Now let's use jQuery to script separate "Play" and "Pause" links ... And let's have those links fire off an alert when they are pressed:

$(document).ready(function(){
  $("#play-button").click(function(){
   $("#audioplayer")[0].play();
   alert('You have played the audio file!');
  })    
 
  $("#pause-button").click(function(){
   $("#audioplayer")[0].pause();
   alert('You have paused the audio file!');
  })    
})

With that script in the <head> as well, the HTML on our page will look like this:

<div class=:"audioplayer">
  <audio id="audioplayer" name="audioplayer" controls loop>
    <source src="http://cdn.softlayer.com/innerlayer/Interrante-PopBounce.ogg" type="audio/ogg">
    <source src="http://cdn.softlayer.com/innerlayer/Interrante-PopBounce.mp3" type="audio/mpeg">
  Your browser does not support the audio element.
  </audio>
 
  <a id="play-button" href="#">Play!</a>
  <a id="pause-button" href="#">Pause!</a>
</div>

Want proof that it works that simply? Boom.

You can theme it any way you like; you can add icons instead of the text ... The world is your oyster. The bonus is that you're using one of the lightest media players on the Internet! If you decide to get brave (or just more awesome), you can explore additional features. You're using jQuery, so your possibilities are nearly limitless. If you want to implement a "Stop" feature (which returns the audio back to the beginning when "Stop" is pressed), you can get creative:

$("#stop-button").click(function(){
    $("#audioplayer")[0].currentTime = 0; // return the audio file back to the beginning
}

If you want to include some volume controls, those can be added in a snap as well:

$("#volumeUp").click(function(){
    $("#audioplayer")[0].volume +=0.1;
}
 
$("#volumeDown").click(function(){
    $("#audioplayer")[0].volume -=0.1;
}

Try it out and let me know what you think. Your homework is to come up with some unique audio player functionality and share it here!

-Cassandra

February 14, 2013

Tips and Tricks – Building a jQuery Plugin (Part 2)

jQuery plugins don't have to be complicated to create. If you've stumbled upon this blog in pursuit of a guide to show you how to make a jQuery plugin, you might not believe me ... It seems like there's a chasm between the "haves" of jQuery plugin developers and the "have nots" of future jQuery developers, and there aren't very many bridges to get from one side to the other. In Part 1 of our "Building a jQuery Plugin" series, we broke down how to build the basic structure of a plugin, and in this installment, we'll be adding some usable functionality to our plugin.

Let's start with the jQuery code block we created in Part 1:

(function($) {
    $.fn.slPlugin = function(options) {
            var defaults = {
                myVar: "This is", // this will be the default value of this var
                anotherVar: "our awesome",
                coolVar: "plugin!",
            };
            var options = $.extend(defaults, options);
            this.each(function() {
                ourString = myVar + " " + anotherVar + " " + coolVar;
            });
            return ourString;
    };
}) (jQuery);

We want our plugin to do a little more than return, "This is our awesome plugin!" so let's come up with some functionality to build. For this exercise, let's create a simple plugin that allows truncates a blob of text to a specified length while providing the user an option show/hide the rest of the text. Since the most common character length limitation on the Internet these days is Twitter's 140 characters, we'll use that mark in our example.

Taking what we know about the basic jQuery plugin structure, let's create the foundation for our new plugin — slPlugin2:

(function($) {
    $.fn.slPlugin2 = function(options) {
 
        var defaults = {
            length: 140,
            moreLink: "read more",
            lessLink: "collapse",
            trailingText: "..."
        };
 
        var options = $.extend(defaults, options);
    };
})(jQuery);

As you can see, we've established four default variables:

  • length: The length of the paragraph we want before we truncate the rest.
  • moreLength: What we append to the paragraph when it is truncated. This will be the link the user clicks to expand the rest of the text.
  • lessLink: What we append to the paragraph when it is expanded. This will be the link the user clicks to collapse the rest of the text.
  • trailingText: The typical ellipses to append to the truncation.

In our jQuery plugin example from Part 1, we started our function with this.each(function() {, and for this example, we're going to add a return for this to maintain chainability. By doing so, we're able to manipulate the segment with methods. For example, if we started our function with this.each(function() {, we'd call it with this line:

$('#ourParagraph').slPlugin2();

If we start the function with return this.each(function() {, we have the freedom to add further manipulation:

$('#ourParagraph').slPlugin2().bind();

With such a simple change, we're able to add method calls to make one massive dynamic function.

Let's flesh out the actual function a little more. We'll add a substantial bit of code in this step, but you should be able to follow along with the changes via the comments:

(function($) {
    $.fn.slPlugin2 = function(options) {
 
        var defaults = {
            length: 140, 
            moreLink: "read more",
            lessLink: "collapse",
            trailingText: "..."
        };
 
        var options = $.extend(defaults, options);
 
        // return this keyword for chainability
        return this.each(function() {
            var ourText = $(this);  // the element we want to manipulate
            var ourHtml = ourText.html(); //get the contents of ourText!
            // let's check if the contents are longer than we want
            if (ourHtml.length > options.length) {
                var truncSpot = ourHtml.indexOf(' ', options.length); // the location of the first space (so we don't truncate mid-word) where we will end our truncation.
 
   // make sure to ignore the first space IF the text starts with a space
   if (truncSpot != -1){
       // the part of the text that will not be truncated, starting from the beginning
       var firstText = ourHtml.substring(0, truncSpot);
 
       // the part of the text that will be truncated, minus the trailing space
       var secondText = ourHtml.substring(truncSpot, ourHtml.legnth -1);
                }
            }
        })
    };
})(jQuery);

Are you still with us? I know it seems like a lot to take in, but each piece is very straightforward. The firstText is the chunk of text that will be shown: The first 140 characters (or whatever length you define). The secondText is what will be truncated. We have two blobs of text, and now we need to make them work together:

(function($) {
    $.fn.slPlugin2 = function(options) {
 
        var defaults = {
            length: 140, 
            moreLink: "read more",
            lessLink: "read less",
            trailingText: "..."
        };
 
        var options = $.extend(defaults, options);
 
        // return this keyword for chainability
        return this.each(function() {
            var ourText = $(this);  // the element we want to manipulate
            var ourHtml = ourText.html(); //get the contents of ourText!
            // let's check if the contents are longer than we want
            if (ourHtml.length > options.length) {
                var truncSpot = ourHtml.indexOf(' ', options.length); // the location of the first space (so we don't truncate mid-word) where we will end our truncation.
 
   // make sure to ignore the first space IF the text starts with a space
   if (truncSpot != -1){
       // the part of the text that will not be truncated, starting from the beginning
       var firstText = ourHtml.substring(0, truncSpot);
 
       // the part of the text that will be truncated, minus the trailing space
       var secondText = ourHtml.substring(truncSpot, ourHtml.legnth -1);
 
       // perform our truncation on our container ourText, which is technically more of a "rewrite" of our paragraph, to our liking so we can modify how we please. It's basically saying: display the first blob then add our trailing text, then add our truncated part wrapped in span tags (to further modify)
       ourText.html(firstText + options.trailingText + '<span class="slPlugin2">' + secondText + '</span>');
 
       // but wait! The secondText isn't supposed to show until the user clicks "read more", right? Right! Hide it using the span tags we wrapped it in above.
       ourText.find('.slPlugin2').css("display", "none");
                }
            }
        })
    };
})(jQuery);

Our function now truncates text to the specified length, and we can call it from our page simply:

<script src="jquery.min.js"></script>
<script src="jquery.slPlugin2.js"></script>
<script type="text/javascript">
$(document).ready(function() {  
    $('#slText').slPlugin2();  
});
</script>

Out of all the ways to truncate text via jQuery, this has to be my favorite. It's feature-rich while still being fairly easy to understand. As you might have noticed, we haven't touched on the "read more" and "read less" links or the expanding/collapsing animations yet, but we'll be covering those in Part 3 of this series. Between now and when Part 3 is published, I challenge you to think up how you'd add those features to this plugin as homework.

-Cassandra

December 30, 2012

Risk Management: Event Logging to Protect Your Systems

The calls start rolling in at 2am on Sunday morning. Alerts start firing off. Your livelihood is in grave danger. It doesn't come with the fanfare of a blockbuster Hollywood thriller, but if a server hosting your critical business infrastructure is attacked, becomes compromised or fails, it might feel like the end of the world. In our Risk Management series, and we've covered the basics of securing your servers, so the next consideration we need to make is for when our security is circumvented.

It seems silly to prepare for a failure in a security plan we spend time and effort creating, but if we stick our heads in the sand and tell ourselves that we're secure, we won't be prepared in the unlikely event of something happening. Every attempt to mitigate risks and stop threats in their tracks will be circumvented by the one failure, threat or disaster you didn't cover in your risk management plan. When that happens, accurate event logging will help you record what happened, respond to the event (if it's still in progress) and have the information available to properly safeguard against or prevent similar threats in the future.

Like any other facet of security, "event logging" can seem overwhelming and unforgiving if you're looking at hundreds of types of events to log, each with dozens of variations and options. Like we did when we looked at securing servers, let's focus our attention on a few key areas and build out what we need:

Which events should you log?
Look at your risk assessment and determine which systems are of the highest value or could cause the most trouble if interrupted. Those systems are likely to be what you prioritized when securing your servers, and they should also take precedence when it comes to event logging. You probably don't have unlimited compute and storage resources, so you have to determine which types of events are most valuable for you and how long you should keep records of them — it's critical to have your event logs on-hand when you need them, so logs should be retained online for a period of time and then backed up offline to be available for another period of time.

Your goal is to understand what's happening on your servers and why it's happening so you know how to respond. The most common audit-able events include successful and unsuccessful account log-on events, account management events, object access, policy change, privilege functions, process tracking and system events. The most conservative approach actually involves logging more information/events and keeping those logs for longer than you think you need. From there, you can evaluate your logs periodically to determine if the level of auditing/logging needs to be adjusted.

Where do you store the event logs?
Your event logs won't do you any good if they are stored in a space that is insufficient for the amount of data you need to collect. I recommend centralizing your logs in a secure environment that is both readily available and scalable. In addition to the logs being accessible when the server(s) they are logging are inaccessible, aggregating and organize your logs in a central location can be a powerful tool to build reports and analyze trends. With that information, you'll be able to more clearly see deviations from normal activity to catch attacks (or attempted attacks) in progress.

How do you protect your event logs?
Attacks can come from both inside and out. To avoid intentional malicious activity by insiders, separation of duties should be enforced when planning logging. Learn from The X Files and "Trust no one." Someone who has been granted the 'keys to your castle' shouldn't also be able to disable the castle's security system or mess with the castle's logs. Your network engineer shouldn't have exclusive access to your router logs, and your sysadmin shouldn't be the only one looking at your web server logs.

Keep consistent time.
Make sure all of your servers are using the same accurate time source. That way, all logs generated from those servers will share consistent time-stamps. Trying to diagnose an attack or incident is exceptionally more difficult if your web server's clock isn't synced with your database server's clock or if they're set to different time zones. You're putting a lot of time and effort into logging events, so you're shooting yourself in the foot if events across all of your servers don't line up cleanly.

Read your logs!
Logs won't do you any good if you're not looking at them. Know the red flags to look for in each of your logs, and set aside time to look for those flags regularly. Several SoftLayer customers — like Tech Partner Papertrail — have come up with innovative and effective log management platforms that streamline the process of aggregating, searching and analyzing log files.

It's important to reiterate that logging — like any other security endeavor — is not a 'one size fits all' model, but that shouldn't discourage you from getting started. If you aren't logging or you aren't actively monitoring your logs, any step you take is a step forward, and each step is worth the effort.

Thanks for reading, and stay secure, my friends!

-Matthew

December 27, 2012

Using SoftLayer Object Storage to Back Up Your Server

Before I came to my senses and moved my personal servers to SoftLayer, I was one of many victims of a SolusVM exploit that resulted in the wide-scale attack of many nodes in my previous host's Chicago data center. While I'm a firm believer in backing up my data, I could not have foreseen the situation I was faced with: Not only was my server in one data center compromised with all of its data deleted, but my backup server in one of the host's other data centers was also attacked ... This left me with old, stale backups on my local computer and not much else. I quickly relocated my data and decided that I should use SoftLayer Object Storage to supplement and improve upon my backup and disaster recovery plans.

With SoftLayer Object Storage Python Client set up and the SoftLayer Object Storage Backup script — slbackup.py — in hand, I had the tools I needed to build a solid backup infrastructure easily. On Linux.org, I contributed an article about how to perform MySQL backups with those resources, so the database piece is handled, but I also need to back up my web files, so I whipped up another quick bash script to run:

#!/bin/bash
 
# The path the backups will be dumped to
DUMP_DIR="/home/backups/"
 
# Path to the web files to be backed up
BACKUP_PATH="/var/www/sites /"
 
# Back up folder name (mmddyyyy)
BACKUP_DIR="`date +%m%d%Y`"
 
# Backup File Name
DUMP_FILE="`date +%m_%d_%Y_%H_%M_%S`_site_files"
 
# SL container name
CONTAINER="site_backups"
 
# Create backup dir if doesn't exist
if [ ! -d $DUMP_DIR$BACKUP_DIR ]; then
        mkdir -p $DUMP_DIR$BACKUP_DIR
fi
 
tar -zcvpf $DUMP_DIR$BACKUP_DIR/$DUMP_FILE.tar.gz $BACKUP_PATH
 
# Make sure the archive exists
if [ -f $DUMP_DIR$BACKUP_DIR/$DUMP_FILE.tar.gz ]; then
        /root/slbackup.py -s $DUMP_DIR$BACKUP_DIR/ -o "$CONTAINER" -r 30
 
        # Remove the backup stored locally
        rm -rf $DUMP_DIR$BACKUP_DIR
 
        # Success
        exit 0
else
        echo "$DUMP_DIR$BACKUP_DIR/$DUMP_FILE.tar.gz does not exist."
        exit 1
fi

It's not the prettiest bash script, but it gets the job done. By tweaking a few variables, you can easily generate backups for any important directory of files and push them to your SoftLayer Object Storage account. If you want to change the retention time of your backups to be longer or shorter, you can change the 30 after the –r in the line below to the number of days you want to keep each backup:

/root/slbackup.py -s $DUMP_DIR$BACKUP_DIR/ -o "$CONTAINER" -r 30

I created a script for each website on my server, and I set a CRON (crontab –e) entry to run each one on Sundays staggered by 5 minutes:

5 1 * * 0  /root/bin/cron/CRON-site1.com_web_files > /dev/null
10 1 * * 0  /root/bin/cron/CRON-site2.com_web_files > /dev/null
15 1 * * 0  /root/bin/cron/CRON-site3.com_web_files > /dev/null 

If you're looking for an easy way to automate and solidify your backups, this little bit of code could make life easier on you. Had I taken the few minutes to put this script together prior to the attack I experienced at my previous host, I wouldn't have lost any of my data. It's easy to get lulled into "backup apathy" when you don't need your backups, but just because nothing *has* happened to your data doesn't mean nothing *can* happen to your data.

Take it from me ... Be over-prepared and save yourself a lot of trouble.

-Ronald

November 27, 2012

Tips and Tricks - Building a jQuery Plugin (Part 1)

I've written several blogs detailing the use of different jQuery plugins (like Select2, LazyLoad and equalHeights), and in the process, I've noticed an increasing frustration among the development community when it comes to building jQuery plugins. The resources and documentation I've found online have not as clear and easy as they could be, so in my next few posts, I'll break down the process to make jQuery plugin creation simple and straightforward. In this post, we'll cover the basic structure of a plugin and where to insert your own functionality, and in Part 2, we'll pick a simple task and add on to our already-made structure.

Before I go any further, it's probably important to address a question you might be asking yourself: "Why would I want to make my own plugin?" The best reason that comes to my mind is portability. If you've ever created a large-scale project, take a look back into your source code and note how many of the hundreds of lines of jQuery code you could put into a plugin to reuse on a different project. You probably invested a lot of time and energy into that code, so it doesn't make sense to reinvent the wheel if you ever need that functionality again. If that's not enough of a reason for you, I can also tell you that if you develop your own jQuery plugin, you'll level-up in cool points, and the jQuery community will love you.

For this post, let's create a jQuery plugin that simply returns, "This is our awesome plugin!" Our first step involves putting together the basic skeleton used by every plugin:

(function($) {
    $.fn.slPlugin = function() {
 
            // Awesome plugin stuff goes here
    };
}) (jQuery);

This is your template — your starting point. Practice it. Remember it. Love it. The "slPlugin" piece is what I chose to name this plugin. It's best to name your plugin something unique ... I always run a quick Google search to ensure I don't duplicate the name of a plugin I (or someone else) might need to use in a project alongside my plugin. In this case, we're calling the example plugin slPlugin because SoftLayer is awesome, and I like naming my plugins after awesome things. I'll save this code in a file called jquery.slPlugin.js.

Now that we have our plugin's skeleton, let's add some default values for variables:

(function($) {
    $.fn.slPlugin = function(options) {
            var defaults = {
                myVar: "default", // this will be the default value of this var
                anotherVar: 0,
                coolVar: "this is cool",                
            };
            var options = $.extend(defaults, options);
    };
}) (jQuery);

Let's look at the changes we made between the first example and this one. You'll notice that in our second line we added "options" to become $.fn.slPlugin = function(options) {. We do this because our function is now accepting arguments, and we need to let the function know that. The next difference you come across is the var defaults blurb. In this section, we're providing default values for our variables. If you don't define values for a given variable when you call the plugin, these default values will be used.

Now let's have our plugin return the message we want to send:

(function($) {
    $.fn.slPlugin = function(options) {
            var defaults = {
                myVar: "This is", // this will be the default value of this var
                anotherVar: "our awesome",
                coolVar: "plugin!",
            };
            var options = $.extend(defaults, options);
            this.each(function() {
                ourString = myVar + " " + anotherVar + " " + coolVar;
            });
            return ourString;
    };
}) (jQuery);

We've defined our default values for our variables, concatenated our variables and we've added a return under our variable declaration. If our jQuery plugin is included in a project and no values are provided for our variables, slPlugin will return, "This is our awesome plugin!"

It seems rather rudimentary at this point, but we have to crawl before we walk. This introductory post is laying the groundwork of coding a jQuery plugin, and we'll continue building on this example in the next installment of this series. As you've seen with the LazyLoad, equalHeights and Select2, there are much more complicated things we can do with our plugin, and we'll get there. Sneak Preview: In the next installment, we'll be creating and implementing a truncation function for our plugin ... Get excited!

-Cassandra

November 21, 2012

Risk Management: The Importance of Redundant Backups

You (should) know the importance of having regular backups of your important data, but to what extent does data need to be backed up to be safe? With a crowbar and shove, thieves broke into my apartment and stole the backups I've used for hundreds of gigabytes of home videos, photo files and archives of past computers. A Dobro RAID enclosure and an external drive used by Apple Time Machine were both stolen, and if I didn't have the originals on my laptop or a redundant offsite backup, I would have lost all of my data. My experience is not uncommon, and it's a perfect example of an often understated principle that everyone should understand: You need redundant backups.

It's pretty simple: You need to back up your data regularly. When you've set up that back up schedule, you should figure out a way to back up your data again. After you've got a couple current backups of your files, you should consider backing up your backups off-site. It seems silly to think of backing up backups, but if anything happens — failed drives, theft, fire, flood, etc. — those backups could be lost forever, and if you've ever lost a significant amount of data due to a hard drive failure or experience like mine, you know that backups are worth their weight in gold.

Admittedly, there is a point of diminishing return when it comes to how much redundancy is needed — it's not worth the time/effort/cost to back up your backups ad infinitum — so here are the best practices I've come up with over the course of my career in the information technology industry:

  • Plan and schedule regular backups to keep your archives current. If your laptop's hard drive dies, having backups from last June probably won't help you as much as backups from last night.
  • Make sure your data exists on three different mediums. It might seem unnecessary, but if you're already being intentional about backing up your information, take it one step further to replicate those backups at least one more time.
  • Something might happen to your easy onsite backups, so it's important to consider off-site backups as well. There are plenty of companies offering secure online backups for home users, and those are generally easy to use (even if they can be a little slow).
  • Check your backups regularly. Having a backup is useless if it's not configured to back up the correct data and running on the correct schedule.
  • RAID is not a backup solution. Yes, RAID can duplicate data across hard drives, but that doesn't mean the data is "backed up" ... If the RAID array fails, all of the hard drives (and all of the data) in the array fail with it.

It's important to note here that "off-site" is a pretty relative term when it comes to backups. Many SoftLayer customers back up a primary drive on their server to a secondary drive on the same server (duplicating the data away from the original drive), and while that's better than nothing, it's also a little risky because it's possible that the server could fail and corrupt both drives. Every backup product SoftLayer offers for customers is off-site relative to the server itself (though it might be in the same facility), so we also make it easy to have your backup in another city or on a different continent.

As I've mentioned already, once you set up your backups, you're not done. You need to check your backups regularly for failures and test them to confirm that you can recover your data quickly in the event of a disaster. Don't just view a file listing. Try extracting files or restore the whole backup archive. If you're able to run a full restore without the pressure of an actual emergency, it'll prove that you're ready for the unexpected ... Like a fire drill for your backups.

Setting up a backup plan doesn't have to be scary or costly. If you don't feel like you could recover quickly after losing your data, spend a little time evaluating ways to make a recovery like that easy. It's crazy, but a big part of "risk management," "disaster recovery" and "business continuity" is simply making sure your data is securely backed up regularly and available to you when you need it.

Plan, prepare, back up.

-Lyndell

November 14, 2012

Risk Management: Securing Your Servers

How do you secure your home when you leave? If you're like most people, you make sure to lock the door you leave from, and you head off to your destination. If Phil is right about "locks keeping honest people honest," simply locking your front door may not be enough. When my family moved into a new house recently, we evaluated its physical security and tried to determine possible avenues of attack (garage, doors, windows, etc.), tools that could be used (a stolen key, a brick, a crowbar, etc.) and ways to mitigate the risk of each kind of attack ... We were effectively creating a risk management plan.

Every risk has different probabilities of occurrence, potential damages, and prevention costs, and the risk management process helps us balance the costs and benefits of various security methods. When it comes to securing a home, the most effective protection comes by using layers of different methods ... To prevent a home invasion, you might lock your door, train your dog to make intruders into chew toys and have an alarm system installed. Even if an attacker can get a key to the house and bring some leftover steaks to appease the dog, the motion detectors for the alarm are going to have the police on their way quickly. (Or you could violate every HOA regulation known to man by digging a moat around the house, filling with sharks with laser beams attached to their heads, and building a medieval drawbridge over the moat.)

I use the example of securing a house because it's usually a little more accessible than talking about "server security." Server security doesn't have to be overly complex or difficult to implement, but its stigma of complexity usually prevents systems administrators from incorporating even the simplest of security measures. Let's take a look at the easiest steps to begin securing your servers in the context of their home security parallels, and you'll see what I'm talking about.

Keep "Bad People" Out: Have secure password requirements.

Passwords are your keys and your locks — the controls you put into place that ensure that only the people who should have access get it. There's no "catch all" method of keeping the bad people out of your systems, but employing a variety of authentication and identification measures can greatly enhance the security of your systems. A first line of defense for server security would be to set password complexity and minimum/maximum password age requirements.

If you want to add an additional layer of security at the authentication level, you can incorporate "Strong" or "Two-Factor" authentication. From there, you can learn about a dizzying array of authentication protocols (like TACACS+ and RADIUS) to centralize access control or you can use active directory groups to simplify the process of granting and/or restricting access to your systems. Each layer of authentication security has benefits and drawbacks, and most often, you'll want to weigh the security risk against your need for ease-of-use and availability as you plan your implementation.

Stay Current on your "Good People": When authorized users leave, make sure their access to your system leaves with them.

If your neighbor doesn't return borrowed tools to your tool shed after you gave him a key when he was finishing his renovation, you need to take his key back when you tell him he can't borrow any more. If you don't, nothing is stopping him from walking over to the shed when you're not looking and taking more (all?) of your tools. I know it seems like a silly example, but that kind of thing is a big oversight when it comes to server security.

Employees are granted access to perform their duties (the principle of least privilege), and when they no longer require access, the "keys to the castle" should be revoked. Auditing who has access to what (whether it be for your systems or for your applications) should be continual.

You might have processes in place to grant and remove access, but it's also important to audit those privileges regularly to catch any breakdowns or oversights. The last thing you want is to have a disgruntled former employee wreak all sorts of havoc on your key systems, sell proprietary information or otherwise cost you revenue, fines, recovery efforts or lost reputation.

Catch Attackers: Monitor your systems closely and set up alerts if an intrusion is detected.

There is always a chance that bad people are going to keep looking for a way to get into your house. Maybe they'll walk around the house to try and open the doors and windows you don't use very often. Maybe they'll ring the doorbell and if no lights turn on, they'll break a window and get in that way.

You can never completely eliminate all risk. Security is a continual process, and eventually some determined, over-caffeinated hacker is going to find a way in. Thinking your security is impenetrable makes you vulnerable if by some stretch of the imagination, an attacker breaches your security (see: Trojan Horse). Continuous monitoring strategies can alert administrators if someone does things they shouldn't be doing. Think of it as a motion detector in your house ... "If someone gets in, I want to know where they are." When you implement monitoring, logging and alerting, you will also be able to recover more quickly from security breaches because every file accessed will be documented.

Minimize the Damage: Lock down your system if it is breached.

A burglar smashes through your living room window, runs directly to your DVD collection, and takes your limited edition "Saved by the Bell" series box set. What can you do to prevent them from running back into the house to get the autographed posted of Alf off of your wall?

When you're monitoring your servers and you get alerted to malicious activity, you're already late to the game ... The damage has already started, and you need to minimize it. In a home security environment, that might involve an ear-piercing alarm or filling the moat around your house even higher so the sharks get a better angle to aim their laser beams. File integrity monitors and IDS software can mitigate damage in a security breach by reverting files when checksums don't match or stopping malicious behavior in its tracks.

These recommendations are only a few of the first-line layers of defense when it comes to server security. Even if you're only able to incorporate one or two of these tips into your environment, you should. When you look at server security in terms of a journey rather than a destination, you can celebrate the progress you make and look forward to the next steps down the road.

Now if you'll excuse me, I have to go to a meeting where I'm proposing moats, drawbridges, and sharks with laser beams on their heads to SamF for data center security ... Wish me luck!

-Matthew

November 6, 2012

Tips and Tricks - Pure CSS Sticky Footers

By now, if you've seen my other blog posts, you know that I'm fascinated with how much JavaScript has evolved and how much you can do with jQuery these days. I'm an advocate of working smarter, not harder, and that maxim knows no coding language limits. In this post, I want to share a pure CSS solution that allows for "sticky" footers on a web page. In comparing several different techniques to present this functionality, I found that all of the other routes were overkill when it came to processing time and resource usage.

Our objective is simple: Make the footer of our web page stay at the bottom even if the page's content area is shorter than the user's browser window.

This, by far, is one of my *favorite* things to do. It makes the web layout so much more appealing and creates a very professional feel. I ended up kicking myself the very first time I tried to add this functionality to a project early in my career (ten years ago ... already!?) when I found out just how easy it was. I take solace in knowing that I'm not alone, though ... A quick search for "footer stick bottom" still yields quite a few results from fellow developers who are wrestling with the same frustrating experience I did. If you're in that boat, fear no more! We're going to your footers in shape in a snap.

Here's a diagram of the problem:

CSS Footer

Unfortunately, a lot of people try to handle it with setting a fixed height to the content which would push the footer down. This may work when YOU view it, but there are several different browser window heights, resolutions and variables that make this an *extremely* unreliable solution (notice the emphasis on the word "extremely" ... this basically means "don't do it").

We need a dynamic solution that is able to adapt on the fly to the height of a user's browser window regardless if the resize it, have Firebug open, use a unique resolution or just have a really, really weird browser!

Let's take a look at what the end results should look like:

CSS Footer

To make this happen, let's get our HTML structure in place first:

<div id="page">
 
      <div id="header"> </div>
 
      <div id="main"> </div>
 
      <div id="footer"> </div>
 
</div>

It's pretty simple so far ... Just a skeleton of a web page. The page div contains ALL elements and is immediately below the

tags in the page code hierarchy. The header div is going to be our top content, the main div will include all of our content, and the footer div is all of our copyrights and footer links.

Let's start by coding the CSS for the full page:

Html, body {
      Padding: 0;
      Margin: 0;
      Height: 100%;
}

Adding a 100% height allows us to set the height of the main div later. The height of a div can only be as tall as the parent element encasing it. Now let's see how the rest of our ids are styled:

#page {
      Min-height: 100%;
      position:relative;
}
 
#main {
      Padding-bottom: 75px;   /* This value is the height of your footer */
}
 
#footer {
      Position: absolute;
      Width: 100%;
      Bottom: 0;
      Height: 75px;  /* This value is the height of your footer */
}

These rules position the footer "absolutely" at the bottom of the page, and because we set #page to min-height: 100%, it ensures that #main is exactly the height of the browser's viewing space. One of the best things about this little trick is that it's compliant with all major current browsers — including Firefox, Chrome, Safari *AND* Internet Explorer (after a little tweak). For Internet Explorer to not throw a fit, we need concede that IE doesn't recognize min-height as a valid property, so we have to add Height: 100%; to #page:

#page {
      Min-height: 100%;  /* for all other browsers */
      height: 100%;  /* for IE */
      position:relative;
}

If the user does not have a modern, popular browser, it's still okay! Though their old browser won't detect the magic we've done here, it'll fail gracefully, and the footer will be positioned directly under the content, as it would have been without our little CSS trick.

I can't finish this blog without mentioning my FAVORITE perk of this trick: Should you not have a specially designed mobile version of your site, this trick even works on smart phones!

-Cassandra

October 25, 2012

Tips from the Abuse Department: Save Your Sinking Ship

I often find that the easiest way to present a complex process is with a relatable analogy. By replacing esoteric technical details with a less intimidating real-world illustration, smart people don't have to be technically savvy to understand what's going on. When it comes to explaining abuse-related topics, I find analogies especially helpful. One that I'm particularly keen on in explaining Abuse tickets in the context of a sinking ship.

How many times have you received an Abuse ticket and responded to the issue by suspending what appears to be the culprit account? You provide an update in the ticket, letting our team know that you've "taken care of the problem," and you consider it resolved. A few moments later, the ticket is updated on our end, and an abuse administrator is asking follow-up questions: "How did the issue occur?" "What did you do to resolve the issue?" "What steps are being taken to secure the server in order to prevent further abuse?"

Who cares how the issue happened if it's resolved now, right? Didn't I respond quickly and address the problem in the ticket? What gives? Well, dear readers, it's analogy time:

You're sailing along in a boat filled with important goods, and the craft suddenly begins to take on water. It's not readily apparent where the water is coming from, but you have a trusty bucket that you fill with the water in the boat and toss over the side. When you toss out all the water onboard, is the problem fixed? Perhaps. Perhaps not.

You don't see evidence of the problem anymore, but as you continue along your way, your vessel might start riding lower and lower in the water — jeopardizing yourself and your shipment. If you were to search for the cause of the water intake and take steps to patch it, the boat would be in a much better condition to deliver you and your cargo safely to your destination.

In the same way that a hull breach can sink a ship, so too can a security hole on your server cause problems for your (and your clients') data. In the last installment of "Tips from the Abuse Department," Andrew explained some of the extremely common (and often overlooked) ways servers are compromised and used maliciously. As he mentioned in his post, Abuse tickets are, in many cases, the first notification for many of our customers that "something's wrong."

At a crucial point like this, it's important to get the water out of the boat AND prevent the vessel from taking on any more water. You won't be sailing smoothly unless both are done as quickly as possible.

Let's look at an example of what thorough response to an Abuse ticket might look like:

A long-time client of yours hosts their small business site on one of your servers. You are notified by Abuse that malware is being distributed from a random folder on their domain. You could suspend the domain and be "done" with the issue, but that long-time client (who's not in the business of malware distribution) would suffer. You decide to dig deeper.

After temporarily suspending the account to stop any further malware distribution, you log into the server and track down the file and what permissions it has. You look through access logs and discover that the file was uploaded via FTP just yesterday from an IP in another country. With this IP information, you search your logs and find several other instances where suspicious files were uploaded around the same time, and you see that several FTP brute force attempts were made against the server.

You know what happened: Someone (or something) scanned the server and attempted to break into the domain. When the server was breached, malware was uploaded to an obscure directory on the domain where the domain owners might not notice it.

With this information in hand, you can take steps to protect your clients and the server itself. The first step might be to implement a password policy that would make guessing passwords very difficult. Next, you might add a rule within your FTP configuration to block continued access after a certain number of failed logins. Finally, you would clean the malicious content from the server, reset the compromised passwords, and unsuspend the now-clean site.

While it's quite a bit more work than simply identifying the domain and account responsible for the abuse and suspending it, the extra time you spent investigating the cause of the issue will prevent the same issue from happening after your client "fixes" the problem by deleting the files/directories. Invariably, they'd get compromised again in the same way when the domain is restored, and you'd hear from the Abuse department again.

Server security goes hand in hand with systems administration, and even though it's not a very fun part of the job, it is a 24/7 responsibility that requires diligence and vigilance. By investing time and effort into securing your servers and fixing your hull breach rather than just bailing water overboard, your customers will see less downtime, you'll be using your server resources more efficiently, and (best of all) you won't have the Abuse team hounding you about more issues!

-Garrett

P.S. I came up with a brilliant analogy about DNS and the postal service, so that might be a topic for my next post ...

Subscribe to tips