FeedBurner makes it easy to receive content updates in My Yahoo!, Newsgator, Bloglines, and other news readers.
Learn more about syndication and FeedBurner...
If you have to SSH into your servers, then your automation has failed.
The last time I had an actionable alert from CloudWatch was about a year ago...
I've found them to be about as reliable as a large government department...
I've had it happen, it sucks, learn from my mistake!
cat /dev/urandom | tr -cd "[:graph:]" | head -c ${1:-100}; echo
> lspci | grep 'VGA' 00:02.0 VGA compatible controller: Intel Corporation Device 0116 (rev 09)
> sudo update-pciids Downloaded daily snapshot dated ... > lspci | grep 'VGA' 00:02.0 VGA compatible controller: Intel Corporation 2nd Generation Core Processor Family Integrated Graphics Controller (rev 09)
sudo add-apt-repository ppa:glasen/intel-driver sudo apt-get update sudo apt-get upgrade
Section "Device"
Identifier "card0"
Driver "intel"
EndSection
sudo apt-get install linux-image-generic-lts-backport-natty linux-headers-generic-lts-backport-natty
> lspci | grep 'Ethernet\|Network' 00:19.0 Ethernet controller: Intel Corporation Device 1503 (rev 04) 02:00.0 Network controller: Intel Corporation Device 0091 (rev 34)
> sudo update-pciids Downloaded daily snapshot dated ... > lspci | grep 'Ethernet\|Network' 00:19.0 Ethernet controller: Intel Corporation 82579V Gigabit Network Connection (rev 04) 02:00.0 Network controller: Intel Corporation Centrino Advanced-N 6230 (rev 34)
tar -xvf e1000e-1.9.5.tar.gz cd e10001e-1.9.5 sudo make install sudo modprobe -r e1000e; sudo modprobe e1000e
> lsmod | grep e1000e e1000e 158424 0
tar -vxf iwlwifi-6000g2b-ucode-18.168.6.1.tgz cd iwlwifi-6000g2b-ucode-18.168.6.1/ sudo cp iwlwifi-6000g2b-6.ucode /lib/firmware/ sudo modprobe -r iwlagn sudo modprobe iwlagn
sudo apt-get install linux-backports-modules-wireless-lucid-generic
> lsmod | grep iwl iwlagn 272480 0 iwlcore 167474 1 iwlagn mac80211 298255 2 iwlagn,iwlcore cfg80211 182202 3 iwlagn,iwlcore,mac80211
sudo apt-get install linux-image-generic-lts-backport-natty linux-headers-generic-lts-backport-natty
User M: Visits the website, and has a session ID assigned to them. They either look at the GET parameters (?sid=xxxxx) or at the headers (Set-Cookie: sid=xxxxx) to determine their session ID. Once they have the ID, they craft either a direct link using the GET parameters (http://example.com/?sid=xxxxx) or they construct a non-direct link which will add the relevant headers. This link is then sent to User V.
User V: Gets an email from User M which says "Hey, check out your new look banking account! http://example.com/?sid=xxxxx" Since the link looks legitimate (example.com is the real URL) then the user clicks the link confident it's not a scam. They then login with their account.
User M: Since this user already had the same session or already knows the SID, they will now be logged in to the site as if they are user V. If you regenerate the SID, then this wouldn't be possible since user M would no longer know the correct SID.
session_regenerate_id(true);
If ($_SESSION['_USER_IP'] != $_SERVER['REMOTE_ADDR']
|| $_SESSION['_USER_AGENT'] != $_SERVER['HTTP_USER_AGENT'])
{
session_unset(); // Same as $_SESSION = array();
session_destroy();
session_start();
session_regenerate_id(true);
Log::create("Possible session hijacking attempt.", Log::NOTIFY_ADMIN)
Auth::getCurrentUser()->reAuthenticate(Auth::SESSION_SUSPICIOUS);
}
$_SESSION['_USER_IP'] = $_SERVER['REMOTE_ADDR'];
$_SESSION['_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];
If ($_SESSION['_USER_LOOSE_IP'] != long2ip(ip2long($_SERVER['REMOTE_ADDR'])
& ip2long("255.255.0.0"))
|| $_SESSION['_USER_AGENT'] != $_SERVER['HTTP_USER_AGENT']
|| $_SESSION['_USER_ACCEPT'] != $_SERVER['HTTP_ACCEPT']
|| $_SESSION['_USER_ACCEPT_ENCODING'] != $_SERVER['HTTP_ACCEPT_ENCODING']
|| $_SESSION['_USER_ACCEPT_LANG'] != $_SERVER['HTTP_ACCEPT_LANGUAGE']
|| $_SESSION['_USER_ACCEPT_CHARSET'] != $_SERVER['HTTP_ACCEPT_CHARSET'])
{
// Destroy and start a new session
session_unset(); // Same as $_SESSION = array();
session_destroy(); // Destroy session on disk
session_start();
session_regenerate_id(true);
// Log for attention of admin
Log::create("Possible session hijacking attempt.", Log::NOTIFY_ADMIN)
// Flag that the user needs to re-authenticate before continuing.
Auth::getCurrentUser()->reAuthenticate(Auth::SESSION_SUSPICIOUS);
}
// Store these values into the session so I can check on subsequent requests.
$_SESSION['_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];
$_SESSION['_USER_ACCEPT'] = $_SERVER['HTTP_ACCEPT'];
$_SESSION['_USER_ACCEPT_ENCODING'] = $_SERVER['HTTP_ACCEPT_ENCODING'];
$_SESSION['_USER_ACCEPT_LANG'] = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
$_SESSION['_USER_ACCEPT_CHARSET'] = $_SERVER['HTTP_ACCEPT_CHARSET'];
// Only use the first two blocks of the IP (loose IP check). Use a
// netmask of 255.255.0.0 to get the first two blocks only.
$_SESSION['_USER_LOOSE_IP'] = long2ip(ip2long($_SERVER['REMOTE_ADDR'])
& ip2long("255.255.0.0"));
// Manually set the cookie
setcookie("sid", // Name
session_id(), // Value
strtotime("+1 hour"), // Expiry
"/", // Path
".wblinks.com", // Domain
true, // HTTPS Only
true); // HTTP Only
// Or, in php.ini
session.cookie_lifetime = "3600"; // Expiry
session.cookie_httponly = "1"; // HTTP Only
session.cookie_secure = "1"; // HTTPS Only
session.cookie_domain = ".wblinks.com" // Domain
// Then session_start will use the above config.
session_start();
If (!isset($_SESSION['MY_SERVER_GENERATED_THIS_SESSION']))
{
session_unset();
session_destroy();
session_start();
session_regenerate_id(true);
}
$_SESSION['MY_SERVER_GENERATED_THIS_SESSION'] = true;
$_SESSION['_USER_LAST_ACTIVITY'] = time();
$_SESSION['SESSION_START_TIME'] = time();
if ($_SESSION['SESSION_START_TIME'] < (strtotime("-1 hour"))
|| $_SESSION['_USER_LAST_ACTIVITY'] < (strtotime("-20 mins")))
{
session_unset();
session_destroy();
Auth::getCurrentUser()->reAuthenticate(Auth::SESSION_EXPIRED);
}
session_start(); session_regenerate_id(true);
$nextPage = Sanitizer::sanitize($_GET['next_page']);
header("Location: $nextPage");
http://example.com/?next_page=login%0d%0aSet-Cookie:%20sessionID%3d12345678
?next_page=login\r\nSet-Cookie: sessionID=12345678
Location: login Set-Cookie: sessionID=12345678
session_unset(); session_destroy(); session_start(); session_regenerate_id(true);
unset($_COOKIE);
// This will only remove it from the superglobal and will do nothing to
// the actual client-side cookie.
setcookie("sid", "", 0);
// 0 sets the expiry time to when the browser is closed and doesn't
// immediately expire it. Don't use 0!
setcookie("sid", "", strtotime("-1 hour"));
// Sets the expiry to one hour in the past right?
// In server time yes, but cookies are stored on the client in their
// local timezone, so depending on where that is, it may not expire for a
// few more hours!
setcookie("sid", "", 1);
Auth::getCurrentUser()->reAuthenticate(Auth::ACTION_SENSITIVE_CRITICAL);
I thought I'd make a comment on your site. Check out this cool image!
<img src='http://example.com/delete_my_account.php" />
<?php
$url = parse_url($_SERVER['HTTP_REFERER']);
if ($url['host'] != "wblinks.com")
{
die("You're not coming from my site. Possible XSRF attack");
}
$_config['csrf_token_lifetime'] = "15 mins"; // How long the tokens should last.
// Generates a nonce, by base64 encoding some random binary data.
public static function generateNonce($length = 20)
{
return substr(base64_encode(openssl_random_pseudo_bytes(1000)), 0, $length);
}
// Generate a new XSRF token and store it in the user's session.
public static function getXSRFToken()
{
$nonce = Auth::generateNonce();
$tokens = Session::get("_xsrf");
$tokens[$nonce] = strtotime("+".$_config['csrf_token_lifetime']);
Session::set("_xsrf", $tokens);
return $nonce;
}
// This will determine if an fkey is valid
private static function validateXSRFToken($xsrf)
{
$tokens = Session::get("_xsrf");
if ($tokens == null) { return false; } // Sanity check
// Check that the fkey exists, and time has not expired
foreach ($tokens as $key => $expires)
{
// Remove any tokens that have expired.
if (time() > $expires)
{
unset($tokens[$key]); Session::set("_xsrf", $tokens);
continue;
}
// If key matches and isn't expired, we can use it.
if ($key == $xsrf && time() <= $expires)
{
// Key is good, remove it from use
unset($tokens[$key]); Session::set("_xsrf", $tokens);
return true;
}
}
return false;
}
// Creates the form input to use
public static function getXSRFFormInput()
{
return "<input type=\"hidden\" name=\"fkey\" value=\"".Auth::getXSRFToken()."\" />";
}
<form action="do_something.php" method="POST">
<fieldset>
<?php echo Auth::getXSRFFormInput(); ?>
<input ... />
</fieldset>
</form>
<input type="hidden" name="fkey" value="3748ab53cf129d536eca" />";
$_SESSION['_xsrf'] array(1) =>
{
["3748ab53cf129d536eca"] => int(1275675864)
}
if (count($_POST) > 0)
{
if (!Auth::validateXSRFToken($_POST["fkey"]))
{
Log::create("XSRF", "Possible XSRF attack", LOG::NOTIFY, LOG::NOTIFY_ADMIN);
// Inform user that why things broke and how to fix it.
Notification::set("Your session token expired. Please refresh and try again (don't use the back button).", NotificationType::ERROR);
// Redirect back to whichever page they came from.
header("Location:".Session::getReferer()); exit();
}
}
function connect()
{
global $DB_CONFIG;
if ($this->getHandle() != null) return; // Already connected
$pdo_string = 'mysql:dbname='.$DB_CONFIG['database'].';host='.$DB_CONFIG['hostname'];
try
{
Log::create("DB","Connecting to ".$pdo_string." as ".$DB_CONFIG['username'], Log::INFO);
$this->_handle = new PDO($pdo_string, $DB_CONFIG['username'], $DB_CONFIG['password']);
$this->getHandle()->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e)
{
Log::create("DB","Exception caught while connecting. ".$e->getMessage(),
Log::ERROR,
Log::NOTIFY_ADMIN);
header("Location: /dbdown/");
}
Log::create("DB","Connected to database", Log::INFO);
}
$this->getHandle()->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e)
{
Log::create("DB","Exception caught while connecting. ".$e->getMessage(),
Log::ERROR,
Log::NOTIFY_ADMIN);
header("Location: /dbdown/");
}

I won't name and shame where this screenshot comes from, but it's from a product that's live, out there in the wild and worryingly also deals with money (and I should point out, not associated to anything I've worked on).
Q. 2X4B?
A. 523P
Q. My password is "iamawesome"?

"You must change your password every x days"
Your password must be at least 6-8 characters long, contain uppercase and lowercase letters, and have at least two digits, but not for the first two characters. Oh, and it shouldn't contain the name of a species of dog.
"You cannot use that password because another user already has it"
"Your password cannot contain special characters, only normal letters and numbers"
Your password cannot be longer than 16 chars.
<ul> <li>SOME OPTION</li> <li>ANOTHER OPTION</li> </ul>
ul li {
text-transform: lowercase;
}
<ul> <li>Some Option</li> <li>Another Option</li> </ul>
<a href="javascript:addToBasket()">Buy Item</a>
<a href="buyitem.php?item=awesomestuff" onlick="addToBasket()">Buy Item</a>
<a href="buyitem.php?item=awesomestuff" id="buyitem-awesomestuff" class="buyitem">Buy This</a>
$(document).ready(function()
{
$("a.buyitem").click(
function()
{
var url = "buyitem.php?item=" + $(this).attr("id").substring(8);
$.get(url,
"",
function(val) { alert("Item added to cart"); },
"text"
);
return false; // So we don't follow the normal link.
}
);
});
$password_hash = hash("sha256", "iamawesome");
// 4aa4029d0d0265c566c934de4f5e0a36496c59c54b6df8a72d9c52bdf0c1a0e8
$user_entered = hash("sha256", $_POST['password']);
return ($user_entered == $password_from_db);
$salted_hash = hash($password . $random_salt);
$salted_hash = hash(hash($password) . $random_salt); $salted_hash = hash(hash($password) . hash($random_salt)); // ...etc
$salted_hash = hash($random_salt . $sitewide_salt . $password);
| username | password_hash | password_salt |
|---|---|---|
| rich | 2bae773debd80de... | ?hb-:4a-loDC90^n#=R... |
| bob | d82ff2c12d5065f... | 2g}iT'JG><,?wP6{#VG... |
$iterations = 100000;
$salted_hash = hash($random_salt . $sitewide_salt . $password);
for ($i = 0; $i < $iterations; $i++)
{
$salted_hash = hash($random_salt . $sidewide_salt . $salted_hash);
}
| username | password_hash | password_salt | hash_iterations |
|---|---|---|---|
| rich | 2bae773debd80de... | ?hb-:4a-loDC90^n#=R... | 100000 |
| bob | d82ff2c12d5065f... | 2g}iT'JG><,?wP6{#VG... | 150000 |
| username | password |
|---|---|
| rich | $100000$2bae773debd80de...$?hb-:4a-loDC90^n#=R...$ |
| bob | $150000$d82ff2c12d5065f...$2g}iT'JG><,?wP6{#VG...$ |
| username | password |
|---|---|
| rich | $5$100000$2bae773debd80de...$?hb-:4a-loDC90^n#=R...$ |
| bob | $5$150000$d82ff2c12d5065f...$2g}iT'JG><,?wP6{#VG...$ |
<link rel="stylesheet" type="text/css" media="print" href="print.css"/>
#header,
#menu,
#additional-content {
display: none !important;
}
a[href]:after {
content: " (" attr(href) ") ";
}
.blog-post {
page-break-before: always;
}