<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	>

<channel>
	<title>NomadNet, Inc. Blog &#187; Software Development</title>
	<atom:link href="http://nomadnetinc.com/blog/category/technical/softwaredev/feed" rel="self" type="application/rss+xml" />
	<link>http://nomadnetinc.com/blog</link>
	<description>Software in a World of Information</description>
	<pubDate>Mon, 31 May 2010 13:46:23 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>And Now A Brief Word From Our Author</title>
		<link>http://nomadnetinc.com/blog/2009/03/09/and-now-a-brief-word-from-our-author</link>
		<comments>http://nomadnetinc.com/blog/2009/03/09/and-now-a-brief-word-from-our-author#comments</comments>
		<pubDate>Mon, 09 Mar 2009 15:21:01 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Non-Technical]]></category>

		<category><![CDATA[Software Development]]></category>

		<category><![CDATA[Technical]]></category>

		<category><![CDATA[blogging]]></category>

		<category><![CDATA[passwords]]></category>

		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=414</guid>
		<description><![CDATA[Just two quick updates today:
1.  A Correction To Last Tuesday&#8217;s Post
In Off the Record: Passwords, I recommended the use of SHA1 rather than MD5 hashes when storing passwords.  Since then, I have encountered a persuasive argument in favor of abandoning both of them and using bcrypt instead, as it&#8217;s designed to be less [...]]]></description>
			<content:encoded><![CDATA[<p>Just two quick updates today:</p>
<h3>1.  A Correction To Last Tuesday&#8217;s Post</h3>
<p>In <a href='http://nomadnetinc.com/blog/2009/03/03/off-the-record-passwords/'>Off the Record: Passwords</a>, I recommended the use of SHA1 rather than MD5 hashes when storing passwords.  Since then, I have encountered a persuasive argument in favor of abandoning both of them and using bcrypt instead, as it&#8217;s designed to be <i>less</i> time-efficient, thus dramatically reducing the number of potential passwords that a brute-force attack can attempt in a given amount of time.</p>
<p>As this can make your passwords much more secure against attackers while still keeping single-hash generation running at a reasonable pace, I have revised that post to recommend the use of bcrypt over SHA1 where available.</p>
<h3>2.  I&#8217;m Not Disappearing</h3>
<p>New posts to this blog have slowed down substantially over the last couple weeks because the stockpile which I prepared prior to launching the blog have all been published and my new writing process, which I expect to work out much better in the long run, is taking longer than the old one to produce completed posts, ready to publish.  If all goes as it appears that it will, the rate of new posts should pick up again by the end of next week if not sooner.</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/03/09/and-now-a-brief-word-from-our-author/feed</wfw:commentRss>
		</item>
		<item>
		<title>Off the Record: Passwords</title>
		<link>http://nomadnetinc.com/blog/2009/03/03/off-the-record-passwords</link>
		<comments>http://nomadnetinc.com/blog/2009/03/03/off-the-record-passwords#comments</comments>
		<pubDate>Tue, 03 Mar 2009 16:46:40 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Software Development]]></category>

		<category><![CDATA[Technical]]></category>

		<category><![CDATA[forms]]></category>

		<category><![CDATA[passwords]]></category>

		<category><![CDATA[security]]></category>

		<category><![CDATA[software development]]></category>

		<category><![CDATA[war stories]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=132</guid>
		<description><![CDATA[In 1999, I accepted a programming job with a company selling voicemail service.  When it came time for the boss to demo the company&#8217;s product for me in full, he wanted to show me some feature that needed my PIN to be entered.  Rather than having me enter it, he turned to his [...]]]></description>
			<content:encoded><![CDATA[<p>In 1999, I accepted a programming job with a company selling voicemail service.  When it came time for the boss to demo the company&#8217;s product for me in full, he wanted to show me some feature that needed my PIN to be entered.  Rather than having me enter it, he turned to his computer, brought up my account information, and read the PIN off the screen.</p>
<p>Although I didn&#8217;t say a word, I just about died on the spot.  Although he wasn&#8217;t aware of it, <i>he now knew the PIN for my bank account!</i></p>
<p>Granted, I should have known better than to reuse a PIN (and I do know better now!), but it&#8217;s a very common practice nonetheless, especially as the number of PINs and passwords that each of us needs to keep track of seems to be increasing daily.</p>
<h3>Back To The Present</h3>
<p>More recently, there has been discussion on the debian-user mailing list of ways to log the passwords entered on unsuccessful login attempts.  While this seems innocuous at first glance, and an effective way of seeing what passwords are being tried by brute-force attackers, it will also catch passwords entered incorrectly by legitimate users.  These mistyped passwords will generally only be off by a letter or two, thus giving anyone with access to these logs the ability to much more easily guess the correct version.</p>
<p>Despite the potential advantages in being able to revise your password requirements to improve their strength against the latest dictionary attacks, the issue of password reuse remains.  These kinds of system logs are generally locked down well enough that they&#8217;re only accessible to system administrators whose legitimate powers are broad enough that knowing other users&#8217; passwords will not allow them to do any additional damage locally beyond what they can already do using their own account, but granting them knowledge of others&#8217; passwords also potentially allows them to impersonate the user on <i>other</i> systems.</p>
<p>Trusting them with this information is not necessary for them to perform their legitimate duties.  It allows them to do additional harm, but does not expand their powers for good.  Therefore, it should be kept from them and any security-conscious sysadmin or developer should recognize this.  (Personally, I have, on several occasions, cut off users who were about to tell me their passwords and explained that I would not allow them to do so.)</p>
<h3>Avoiding Password Leakage</h3>
<p>To maintain secrecy, user-entered passwords should <i>never</i> be recorded in plaintext.  I can&#8217;t think of any situations in which there would be a legitimate need to be able to recover an actual user password, but, should such a case exist, there are plenty of good, reversible encryption methods which can be used to store it, safe from prying eyes or casual glances.</p>
<p>The proper and generally-accepted method of dealing with passwords is to pass them through a non-reversible cryptographic hashing function, such as <strike>SHA1<sup>1</sup></strike> bcrypt<sup>2</sup>, then storing the hash rather than the password itself.  Use of reversible encryption would still leave the password vulnerable to anyone with access to the encryption key and the will to use it.  A <strike>SHA1</strike> bcrypt hash allows you to determine whether the entered password matches the correct password without ever knowing (or being able to know) what the correct password is.</p>
<h3>Afterword: Honeypots and Testing</h3>
<p>I did mention, above, that there are potential benefits to being able to see what passwords are being attempted by attackers.  If this information is needed, it can be obtained without compromising the security of your actual users&#8217; passwords by setting up a honeypot system with no valid user accounts (or at least none which accept password-based logins over the network).  Since no legitimate logins will be attempted, you can safely record the passwords without giving away information about legitimate users&#8217; accounts.</p>
<p>The other situation in which I&#8217;ve seen it suggested that it is appropriate to record passwords is when testing or debugging software under development to ensure that input (including the password) is being received and processed correctly.  Safeguarding actual user credentials is again easily done by means of not having any actual user data (or at least not any actual passwords) in the testing environment.</p>
<p>&nbsp;</p>
<hr width=75%>
<sup>1</sup> MD5 has been widely used for many years, but weaknesses are finally being found in it, so SHA1 is now considered a better choice for this purpose.</p>
<p><sup>2</sup> Shortly after making this post, I ran across <a href='http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/'>this article, which makes an excellent case for using bcrypt</a> rather than MD5 or SHA1.  If a bcrypt library is available in the environment where you&#8217;re operating, use it.  If it&#8217;s not available, see if you can get it added.</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/03/03/off-the-record-passwords/feed</wfw:commentRss>
		</item>
		<item>
		<title>Email Address Validation</title>
		<link>http://nomadnetinc.com/blog/2009/02/25/email-address-validation</link>
		<comments>http://nomadnetinc.com/blog/2009/02/25/email-address-validation#comments</comments>
		<pubDate>Wed, 25 Feb 2009 16:00:13 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Software Development]]></category>

		<category><![CDATA[Technical]]></category>

		<category><![CDATA[data collection]]></category>

		<category><![CDATA[email]]></category>

		<category><![CDATA[forms]]></category>

		<category><![CDATA[software development]]></category>

		<category><![CDATA[user interface]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=219</guid>
		<description><![CDATA[In Validation Vexation, I wrote a bit about ways that validation rules for user-entered data can go awry by being too narrowly-defined.  This post adds three more principles for dealing with data validation which are primarily focused on the results of the validation rather than the rules used to do it.  The examples [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href='http://nomadnetinc.com/blog/2009/02/23/validation-vexation/'>Validation Vexation</a>, I wrote a bit about ways that validation rules for user-entered data can go awry by being too narrowly-defined.  This post adds three more principles for dealing with data validation which are primarily focused on the results of the validation rather than the rules used to do it.  The examples used are rather specific to handling email addresses, but the principles themselves still apply much more broadly.</p>
<h3>Incorrect Validation Is Worse Than No Validation</h3>
<p>A recurrent question I&#8217;ve seen on a couple different programming sites is &#8220;What regular expression can I use to validate an email address?&#8221;  They&#8217;ve gotten a lot of responses explaining ways to examine an email address and reject it if it&#8217;s &#8220;invalid&#8221;.  The only problem is that every one of them that tried to be more restrictive than just checking for the presence of an &#8220;@&#8221; was wrong.</p>
<p>The most common flaw was failing to accept &#8220;+&#8221; in the local-part of an address, causing many perfectly valid, deliverable email addresses to be rejected.  There were also several which failed on top-level domains (TLDs) which were four or more characters long, such as <i>.info</i> or <i>.museum</i>.</p>
<p>On the flip side, there were users accustomed to using disposable email addresses of the form <i>username+foo@domain.com</i> or with addresses automatically generated from their surname of <i>O&#8217;Malley</i> - including the apostrophe - complaining about sites refusing to accept their &#8220;invalid&#8221; (but syntactically correct and perfectly functional) email addresses.</p>
<p>Rejecting these addresses may only shut out a percent or two of the world, but is that really an acceptable cost to pay in an attempt to shut out truly bogus addresses?  Particularly given that&#8230;</p>
<h3>Valid Does Not Imply Correct</h3>
<p>Let&#8217;s say that you&#8217;ve managed to find yourself a perfect validation algorithm which is 100% accurate at determining whether email addresses are syntactically valid, even for the O&#8217;Malleys.  You&#8217;re getting only good email addresses, right?</p>
<p>Wrong.</p>
<p><i>abcde@fghi.jkl</i> is syntactically valid, but utterly bogus.  There isn&#8217;t even a .jkl TLD!</p>
<p>&#8220;OK,&#8221; you say, &#8220;I&#8217;ll just add a DNS lookup to my perfect validator so that it rejects domains that don&#8217;t exist or don&#8217;t have a mail exchanger (MX) record defined.&#8221;</p>
<p>Still no good.  <i>dave.sherohman@whitehouse.gov</i> is syntactically valid. It points to a domain that exists and accepts mail.  It&#8217;s still no good.</p>
<p>&#8220;No problem.  I&#8217;ll connect to the mail server and validate that the user account exists.&#8221;</p>
<p>I can still give you a bad email address.  Try <i>president@whitehouse.gov</i> on for size.  The account exists, but it&#8217;s certainly not mine.</p>
<h3>If There&#8217;s Any Chance Of An Incorrect Rejection, Don&#8217;t Pre-Validate</h3>
<p>The <i>only</i> way to authoritatively validate the correctness of an email address is to send email to the address and request that the user respond to it in some manner to confirm receipt.</p>
<p>You may still benefit from doing a preliminary validation to avoid the trouble of sending out mail that could never possibly be received, but this pre-validation cannot reasonably be considered authoritative and should, therefore, only be used to filter out the most blatantly incorrect cases.  Attempting to make it more restrictive will only introduce an unnecessary risk of rejecting genuine, correct, deliverable addresses.</p>
<p>The cost of performing the authoritative validation is low and the cost of rejecting an address which is incorrectly flagged as invalid by a flawed pre-validation is high, so don&#8217;t pre-validate beyond the point at which you are absolutely, 100% certain that it will not fail anything which might pass the authoritative validation.</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/02/25/email-address-validation/feed</wfw:commentRss>
		</item>
		<item>
		<title>Looking Beyond the Obvious</title>
		<link>http://nomadnetinc.com/blog/2009/02/16/looking-beyond-the-obvious</link>
		<comments>http://nomadnetinc.com/blog/2009/02/16/looking-beyond-the-obvious#comments</comments>
		<pubDate>Mon, 16 Feb 2009 16:21:59 +0000</pubDate>
		<dc:creator>Dave Sherohman</dc:creator>
		
		<category><![CDATA[Software Development]]></category>

		<category><![CDATA[Technical]]></category>

		<category><![CDATA[case study]]></category>

		<category><![CDATA[debugging]]></category>

		<category><![CDATA[lessons learned]]></category>

		<category><![CDATA[software development]]></category>

		<category><![CDATA[war stories]]></category>

		<guid isPermaLink="false">http://nomadnetinc.com/blog/?p=136</guid>
		<description><![CDATA[Near its end, the CyberPenguin case study mentions the discovery of &#8220;some small accounting inaccuracies&#8221;.  To be exact, users were occasionally being double-charged for sessions.
If you&#8217;ve done much software development, that statement alone should be enough to have you thinking &#8220;concurrency issue&#8221; or, more specifically, &#8220;race condition&#8221;.  Given that the application involved both [...]]]></description>
			<content:encoded><![CDATA[<p>Near its end, the <a href='http://nomadnetinc.com/CyberPenguin/'>CyberPenguin case study</a> mentions the discovery of &#8220;some small accounting inaccuracies&#8221;.  To be exact, users were occasionally being double-charged for sessions.</p>
<p>If you&#8217;ve done much software development, that statement alone should be enough to have you thinking &#8220;concurrency issue&#8221; or, more specifically, &#8220;race condition&#8221;.  Given that the application involved both a web-based management interface and a once-a-minute scheduled task to handle accounting, the obvious point of conflict was for the problems to result when an operator submitted an update through the web interface while the accounting task was running.</p>
<p>So off I went to ensure that such a conflict wouldn&#8217;t cause issues, then sent the revised code off to the client.  He reported back the next day that it hadn&#8217;t had any effect.</p>
<p>After looking harder at the code, I came up with a way that this conflict could conceivably have still occurred under some contrived circumstance, eliminated that possibility, and sent it off.  Still no improvement.</p>
<p>We went through maybe half a dozen rounds of this before I ran out of ways that the web application and accounting task could conflict, no matter how far I stretched the bounds of probability, and finally took a closer look at the application&#8217;s logs.  Once I started looking at them as a whole, instead of just records of single users, I quickly noticed that these mischarges came in clusters, affecting several users at once, not random individuals.  These clusters also tended to hit right on the hour.</p>
<p>Checking in with the client, it turned out that the specific times when the problems occurred matched up with the times when the per-minute rates changed.</p>
<p>To keep the accounting simple, the application deals with rate changes by closing out each active user&#8217;s session, charging it at the old rate, and then opening a new session at the new rate.  With larger numbers of users logged in, this process was taking more than a minute to complete.  The conflict wasn&#8217;t between the web interface and the scheduled accounting task, it was between two (or more&#8230;) copies of the accounting task!  This also explained why I was never able to reproduce the problem in my own development and testing environment, as I had never simulated enough concurrent users in my tests to produce the problem.</p>
<p>Once the correct culprit had been identified, it was a simple enough matter to resolve by adding a check to prevent multiple instances of the accounting task from running concurrently.</p>
<p>The moral of the story:</p>
<p>Even if the cause of an issue seems clearly obvious, don&#8217;t forget to fully examine the system to verify that you&#8217;re solving the right problem before you spend too much time solving the wrong one.</p>
 &nbsp;  &nbsp;  &nbsp; ]]></content:encoded>
			<wfw:commentRss>http://nomadnetinc.com/blog/2009/02/16/looking-beyond-the-obvious/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
