<?xml version="1.0" encoding="UTF-8" ?>

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
			<title>Tagged with "webdev"</title>
			<link>http://www.addedbytes.com/feeds/tag-feed/</link>
			<description></description>
			<language>en</language>
			<copyright>Added Bytes - Brighton Web Application Development 2006</copyright>
			<ttl>120</ttl>
			<item>
				<title>Why You Should Always Salt Your Hashes</title>
				<link>http://www.addedbytes.com/blog/why-you-should-always-salt-your-hashes/</link>
				<description><![CDATA[ Hashes are used almost everywhere on the web, behind the scenes, to protect your passwords. Learn why it's important to always add salt to your hashes. <h3>The Problem</h3>

<p>The recent <a href="http://igigi.baywords.com/rockyou-com-exposed-more-than-32-millions-of-passwords-in-plaintext/">RockYou.com password problems</a> have spawned plenty of debate online about the best way to store passwords and build a site securely.</p>

<p>Part of being a good, security-conscious web developer is paranoia, and it's apparent that the RockYou.com developers could have used a little more of it. They made two mistakes in their work, not one. Their first, and most obvious one, is that they had a SQL injection hole somewhere. Their second was their assumption that their measures to protect their data were enough to do so.</p>

<p>A healthy dose of paranoia would have led their developers to make the opposite assumption - that whatever they did to protect the data, sooner or later someone would be able to access it.</p>

<p>The result of this second mistake is that, rather than simply announcing a security hole has been found and closed, they have had to deal with the fact that the passwords of more than 32 million people have been exposed, in plain text, to an unknown number of people. As most people use the same password for multiple places, and most will be unaware that this has happened, we can safely assume that the access details of millions of email accounts are in the open and unchanged. That's a bad day in code-land by anyone's standards.</p>

<h3>Hashing</h3>

<p>The solution to the problem is to first assume that all data will be exposed at some point to an intruder of some sort. Once you assume that, it becomes important to ensure that the damage resulting from that exposure is minimal.</p>

<p>Which brings me on to hashes. Hashes are one-way functions that generate a representation, usually a number, of the data put in to them. They always generate the same hash from the same data, and there is no simple way to reverse the process.</p>

<p>This makes them incredibly useful for password storage. Instead of storing a user's password, you can store the hash of the password. When a user logs in again, instead of checking the password they type in against the one you have stored, you calculate the hash of the password they type in and compare that to the stored hash.</p>

<p>There are lots of different hashing algorythms, the most commonly used being MD5 and SHA1.</p>

<h3>Are Hashes Secure?</h3>

<p>Unfortunately, ensuring passwords are stored securely isn't as simple as just using storing a simple hash of a password. Two of the strengths of hashes are also their largest potential weakness: they are small to store and quick to generate.</p>

<p>To generate SHA1 and MD5 hashes of every word in English, for example, takes moments. To store that amount of data is also trivial. To generate hashes of all combinations of letters and numbers, plus a few commonly used punctuation marks, up to say 8 characters, is much slower but still doable without any special setup or equipment.</p>

<p>Tables of precalculated hashes of data like this are easily found online or easily generated. If you have a hash of some data (like a password) and you want to see what that data originally was, you can compare the hash to the entries in your precalculated table. If you find a match, you have discovered the data that was originally used to generate the hash - the password you were trying to find out.</p>

<p>So basic password hashing is, essentially, useless for the majority of users. It is a simple process to compare hashes of basic passwords to a table of precalculated hashes and thereby "dehash" passwords en masse.</p>

<p>Some people recommend nesting hashes as a way to make add complexity and therefore more security. Unfortunately, to generate tables of nested hashes is almost as easy as plain hashes by themselves, and no more secure.</p>

<h3>Add Salt!</h3>

<p>The solution is to hash more than just the user's password, and this process is called "salting". For example, instead of storing a hash of a user's password, you could store the hash of their email address and their password together.</p>

<p>This is effective because tables of hashes of generated data of more than about 10 characters start to become problematic to generate and store. At around that point, tables must be generated based upon dictionaries and known words, rather than on programatically generated lists of all possible passwords in a range.</p>

<p>The average length of "email plus password" is easily in the region of 25 characters. Not only that, but if someone worked out that you were using hashes of "email plus password", they would still need to generate a new table for every password they wanted to dehash.</p>

<p>This level of complexity, added to a reasonably strong password policy, ensures that if (or when) your user data is exposed, the work involved in extracting usable passwords from it is going to stop all but the most determined attackers. Not only that, but even they will find extraction of data in bulk prohibitively difficult.</p> <br><br>]]></description>
				<pubDate>Wed, 16 Dec 2009 10:24:32 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/blog/why-you-should-always-salt-your-hashes/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=database&amp;start=0" class="ditto_tag" rel="tag">database</a>,<a href="/feeds/tag-feed/?tags=passwords&amp;start=0" class="ditto_tag" rel="tag">passwords</a>,<a href="/feeds/tag-feed/?tags=programming&amp;start=0" class="ditto_tag" rel="tag">programming</a>,<a href="/feeds/tag-feed/?tags=security&amp;start=0" class="ditto_tag" rel="tag">security</a>,<a href="/feeds/tag-feed/?tags=webdev&amp;start=0" class="ditto_tag" rel="tag">webdev</a>
			</item>

			<item>
				<title>Writing Secure PHP, Part 4</title>
				<link>http://www.addedbytes.com/writing-secure-php/writing-secure-php-4/</link>
				<description><![CDATA[ The fourth part of the <a href="http://www.addedbytes.com/writing-secure-php/">Writing Secure PHP</a> series, covering cross-site scripting, cross-site request forgery and character encoding security issues. <p>In <a href="http://www.addedbytes.com/php/writing-secure-php/">Writing Secure PHP</a>, <a href="http://www.addedbytes.com/security/writing-secure-php-2/">Writing Secure PHP, Part 2</a> and <a href="http://www.addedbytes.com/security/writing-secure-php-3/">Writing Secure PHP, Part 3</a> I covered many of the common mistakes PHP developers make, and how to avoid some potential security problems. This article covers some of the more advanced security problems common to PHP on the web.</p>

<h3>Cross-Site Scripting (XSS)</h3>

<p>Cross-site scripting (often abbreviated to XSS) is a form of injection, where an attacker finds a way to have the target site display code they control. In its most basic form, this can be as simple as a site that allows HTML characters in usernames, where someone can specify a username like:</p>

<pre class="php">DaveChild&lt;script type="text/javascript" src="http://www.example.com/my_script.js"&gt;&lt;/script&gt;</pre>

<p>Now, whenever someone sees my username on the target site, the script I've added to my username will run. I could potentially use this to grab the person's login information, log their keystrokes - any number of nefarious activities.</p>

<p>As a developer, you can combat this type of attack by encoding or removing HTML characters (watch out for character encoding issues, as outlined next). Even better than stripping out unwanted characters is to allow a whitelist of safe characters in usernames and other fields. Be especially careful with e-commerce sites where you are listing orders in a CMS - an XSS vulnerability may allow an attacker to gain administrative access to your CMS. It is also important to turn off TRACE and TRACK support on the server, as if there is a vulnerability (and always assume that despite your best efforts there will be) these potentially allow an attacker to steal a user's cookie.</p>

<p>As a user you are also vulnerable to this sort of attack, and it is very difficult, at the moment, to make yourself safe against it. Vigilance is key, and to that end I have released a <a href="http://www.addedbytes.com/tools/xss-alarm-userscript/">userscript that warns you about third party scripts</a> (for users of GreaseMonkey, Opera or Chrome).</p>

<h3>Cross-Site Request Forgery (CSRF)</h3>

<p>Despite the similar name, CSRF is unconnected to XSS. CSRF is a form of attack where an authenticated user performs an action on a site without knowing it.</p>

<p>Let's assume that Jack is logged in to his bank, and has a cookie stored on his computer. Each time he sends an HTTP request to the bank (i.e., views a page or an image on a page) his browser sends the cookie along with the request so that the bank knows that it's him making the request.</p>

<p>Jill, meanwhile, runs a different website and has managed to get Jack to visit it. One of the items on the page is in fact loaded from the bank, for example in an iframe. The URL of the iframe or request contains instructions to the bank to transfer money from Jack's account to Jill's. Because the request is coming from Jack's computer, and includes his cookie, the bank assumes it is a legitimate request and the money is transferred.</p>

<p>This type of attack is extremely dangerous and virtually untracable. As a developer, your job is to protect against it, and the best way to do that is to remember <a href="http://www.addedbytes.com/php/writing-secure-php/">Rule Number One: Never, Ever Trust Your Users</a>. No matter how authenticated they are, do not assume every request was intended.</p>

<p>In practical PHP terms, you can combat CSRF with several relatively simple coding habits. Never let the user do anything with a GET request - always use POST. Confirm actions before performing them with a confirmation dialog on a separate page - and make sure <em>both</em> the original action button or link <em>and</em> the confirmation were clicked. Even better, have the user enter information like letters from their password on the confirmation page.</p>

<p>Add a randomly generated token to forms and verify its presence when a request is made. Use <a href="http://javascript.internet.com/page-details/break-frames.html">frame-breaking JavaScript</a>. Time-out sessions with a short timespan (think minutes, not hours). Encourage the user to log out when they've finished. Check the HTTP_REFERER header (it can be hidden, but is still worth checking as if it is a different domain to that expected it is definitely a CSRF request).</p>

<h3>Character Encoding</h3>

<p>Character encoding in PHP and associated database systems is worthy of its own series. In any one request, there may be more different character encodings in use than you might think.</p>

<p>For example, a single request and response (uploading a file to a server and writing information to a database) may involve all of the following differently items with different character encodings: the HTTP request headers, post data, PHP's default encoding, the PHP MySQL module, MySQL's default set, the set of each table being used, a file being opened and read, a new file being created and written, the response headers and the response body.</p>

<p>English-speaking developers generally don't have much cause to get embroiled in character encoding issues, and that results in a lot of developers with a serious lack of understanding of how character encodings work and fit together. For those that do have a reason to look at character encodings, usually that interest ends with the setting of the response's character set.</p>

<p>However, character sets are a fundamental part of all web development. English alone can exist in any one of a wide variety of sets, and developers are usually familiar with the most common two: ISO-8859-1 and UTF-8. Fewer are familiar with UCS-2, UTF-16 or windows-1252. Still fewer are familiar with commonly used alternative language sets (e.g, GB2312 for Chinese).</p>

<p>Which, in a very roundabout way, brings me on to the security pitfalls of character encodings. Where data is processed by PHP using one character set, but a database server uses a different character set, a character (or series of characters) deemed safe by PHP may in fact allow SQL injection against the database.</p>

<p>PHP security expert Chris Shiflett <a href="http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string">has written about this issue</a> and included an example of how it can be exploited to allow SQL injection even where input is sanitized using addslashes().</p>

<p>The solution is to always <em>always</em> use mysql_real_escape_string() rather than addslashes() (or use prepared statements / stored procedures), and to explicitly state character sets at all stages of interaction. Ideally, use the same character set throughout your system (UTF-8 is recommended) and where PHP allows you to specify a character encoding for a function (e.g., htmlspecialchars() or htmlentities()), make use of it.</p>

<p>It's not just SQL that's vulnerable as a result of character encoding bugs. Cross-site scripting is possible even where HTML characters are escaped if character sets are not handled properly. Fortunately, once again that is simple to avoid by properly setting character encodings at all stages of the process and specifying character encoding for functions where possible.</p> <br><br>]]></description>
				<pubDate>Thu, 11 Sep 2008 12:11:14 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/writing-secure-php/writing-secure-php-4/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=code&amp;start=0" class="ditto_tag" rel="tag">code</a>,<a href="/feeds/tag-feed/?tags=coding&amp;start=0" class="ditto_tag" rel="tag">coding</a>,<a href="/feeds/tag-feed/?tags=development&amp;start=0" class="ditto_tag" rel="tag">development</a>,<a href="/feeds/tag-feed/?tags=mysql&amp;start=0" class="ditto_tag" rel="tag">mysql</a>,<a href="/feeds/tag-feed/?tags=php&amp;start=0" class="ditto_tag" rel="tag">php</a>,<a href="/feeds/tag-feed/?tags=programming&amp;start=0" class="ditto_tag" rel="tag">programming</a>,<a href="/feeds/tag-feed/?tags=security&amp;start=0" class="ditto_tag" rel="tag">security</a>,<a href="/feeds/tag-feed/?tags=tips&amp;start=0" class="ditto_tag" rel="tag">tips</a>,<a href="/feeds/tag-feed/?tags=tutorial&amp;start=0" class="ditto_tag" rel="tag">tutorial</a>,<a href="/feeds/tag-feed/?tags=web&amp;start=0" class="ditto_tag" rel="tag">web</a>,<a href="/feeds/tag-feed/?tags=webdesign&amp;start=0" class="ditto_tag" rel="tag">webdesign</a>,<a href="/feeds/tag-feed/?tags=webdev&amp;start=0" class="ditto_tag" rel="tag">webdev</a>
			</item>

			<item>
				<title>Rex Swain HTTP Viewer Bookmarklet</title>
				<link>http://www.addedbytes.com/blog/rex-swain-http-viewer-bookmarklet/</link>
				<description><![CDATA[ <a href="http://www.rexswain.com/httpview.html">Rex Swain's HTTP Viewer</a> is a great tool for checking HTTP status codes, redirection, and so on. I've been unable to find a bookmarklet, though, for sending the URL I am viewing to the viewer automatically, so I put one together:<br />
<br />
<a href="javascript:(function(){url=document.location.href;document.location.href='http://www.rexswain.com/cgi-bin/httpview.cgi?url='+escape(url)+'&req=Get&ver=1.1&fmt=Auto&uag=&aen=&fwd=on';})();">Rex Swain's HTTP Viewer</a>  <br><br>]]></description>
				<pubDate>Fri, 26 Jan 2007 09:55:13 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/blog/rex-swain-http-viewer-bookmarklet/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=bookmarklet&amp;start=0" class="ditto_tag" rel="tag">bookmarklet</a>,<a href="/feeds/tag-feed/?tags=http&amp;start=0" class="ditto_tag" rel="tag">http</a>,<a href="/feeds/tag-feed/?tags=webdev&amp;start=0" class="ditto_tag" rel="tag">webdev</a>
			</item>

			<item>
				<title>RSS to iCal</title>
				<link>http://www.addedbytes.com/blog/rss-to-ical/</link>
				<description><![CDATA[ <p>I have been looking for a way to convert the BBC weather feed for my area to iCal, so I can subscribe to it. It's date-based, after all, and RSS never seemed to me to be an appropriate format for subscribing to weather information. iCal always struck me as being "better" for that purpose.</p> <p>I have been looking for a way to convert the BBC weather feed for my area to iCal, so I can subscribe to it. It's date-based, after all, and RSS never seemed to me to be an appropriate format for subscribing to weather information. iCal always struck me as being "better" for that purpose. Of course, the BBC only have an RSS feed for local weather. What I needed was a converter.</p>

<p>After some hunting, I discovered that Dean Sanvitale had written a PHP script to convert RSS feeds to iCal format. However, his site (codent.com) appears to be long since abandoned and the script is no longer available from there. Fortunately, the Wayback Machine did have a copy. Dean originally released the script under a <a href="http://creativecommons.org/licenses/by-sa/1.0/">Creative Commons License</a> which, fortunately, allows me to make the script available to download from this site (note: the script is available from this site under the same license).</p>

<p>So, if you're looking for a way to convert an RSS feed to iCal, this PHP script will do the job. Thanks Dean!</p>

<p>Source: <a href="http://www.addedbytes.com/rss2ical.txt">rss2ical.txt</a></p> <br><br>]]></description>
				<pubDate>Thu, 19 Oct 2006 11:14:16 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/blog/rss-to-ical/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=bbc&amp;start=0" class="ditto_tag" rel="tag">bbc</a>,<a href="/feeds/tag-feed/?tags=code&amp;start=0" class="ditto_tag" rel="tag">code</a>,<a href="/feeds/tag-feed/?tags=convert&amp;start=0" class="ditto_tag" rel="tag">convert</a>,<a href="/feeds/tag-feed/?tags=ical&amp;start=0" class="ditto_tag" rel="tag">ical</a>,<a href="/feeds/tag-feed/?tags=php&amp;start=0" class="ditto_tag" rel="tag">php</a>,<a href="/feeds/tag-feed/?tags=rss&amp;start=0" class="ditto_tag" rel="tag">rss</a>,<a href="/feeds/tag-feed/?tags=rss2ical&amp;start=0" class="ditto_tag" rel="tag">rss2ical</a>,<a href="/feeds/tag-feed/?tags=tools&amp;start=0" class="ditto_tag" rel="tag">tools</a>,<a href="/feeds/tag-feed/?tags=weather&amp;start=0" class="ditto_tag" rel="tag">weather</a>,<a href="/feeds/tag-feed/?tags=web&amp;start=0" class="ditto_tag" rel="tag">web</a>,<a href="/feeds/tag-feed/?tags=webdev&amp;start=0" class="ditto_tag" rel="tag">webdev</a>
			</item>

			<item>
				<title>Block Referrer Spam (Updated)</title>
				<link>http://www.addedbytes.com/blog/block-referrer-spam/</link>
				<description><![CDATA[ Referrer spam is becoming increasingly common. At best, it will only render your log files useless. At worst, it can cause your site to be dropped by search engines and your running costs to skyrocket. Here's how to block spurious referrers. <p>Log files are a useful tool for webmasters. It helps to know how people are finding your site, and what software they are using to view it, among other things. A strange decision by a small group of bloggers, though, has given unscrupulous marketers another window of opportunity to manipulate search engines to increase their traffic.</p>

<p>The decision made by these short-sighted bloggers was to display, on their site, a list of recent referrers to each page. I can't imagine any reason why a visitor might be in the least bit interested in seeing this, but nevertheless many sites now display referrers on every page.</p>

<p>As search engine spiders visit sites, they grab the contents of each page they visit. They use this snapshot in their index - meaning that although a page may change every minute or two, a search engine may be using a single copy of a page for several days, or even weeks.</p>

<p>So a referral URL that is on a page when the spiders come to visit can have quite a bit of value, if the search engine visiting uses link popularity in any way (Google uses link popularity, as do many others).</p>

<p>So marketers have started to use programs to visit pages using a fake referral header, to get their URLs listed on as many sites as possible, in the hopes that this will increase their traffic.</p>

<p>However, this renders log files almost completely useless. These fake visitors usually visit from search engines, having searched for a keyphrase relevant to their own site. They skew statistics relating to number of visitors received, the countries used to visit, the technology used to view the page, how users found the page, how long they spent on the site ... and so on.</p>

<p>A webmaster may find their search engine rankings dropping because of this, and they may find search engines have removed them completely. Many sites that use spam techniques are quickly identified and penalised, and penalties will often be applied to sites that link to them as well.</p>

<p>There are plenty of techniques available for blocking referrer spam, and everyone has their favourite. Personally, I use a combination of two techniques.</p>

<p>The first is fairly simple - my referrer log is not indexable. I don't display referrers on the pages of my site. My referral log is publicly available, but search engines are instructed to ignore it. This removes the main incentive for people to referrer-spam my site (the other reason for this type of spam - the hope that the site owner will themselves visit the spamming URL - is less common, because it has such a low response rate).</p>

<p>Second, I use an .htaccess file to block requests from whatever I've managed to identify as either a crawler designed to find URLs to spam or a spamming URL. This is a relatively simple blacklist, and though it cannot work as a long term solution to this problem, it keeps me happy for now.</p>

<p>To implement this technique on your own site, first make sure you are running Apache with mod_rewrite. If you are, create a file called ".htaccess" (just that, not .htaccess.txt or anything else) and paste the following into it:</p>

<h3>Update: 14th September 2005</h3>

<p>The list below has been expanded substantially over the last year, and now covers much more spam than before. As stated before, this is not a practical solution to the problem in the long term, as this list can only ever get longer and longer, and may become unmaintainable, or even (eventually) slow a site to a crawl as all the rules are processed. However, as of now, it is still a useful tool.</p>

<code>RewriteEngine  on

# Block Referrer Spam

# Drugs / Herbal

    RewriteCond %{HTTP_REFERER} (sleep-?deprivation) [NC,OR]
    RewriteCond %{HTTP_REFERER} (sleep-?disorders) [NC,OR]
    RewriteCond %{HTTP_REFERER} (insomnia) [NC,OR]
    RewriteCond %{HTTP_REFERER} (phentermine) [NC,OR]
    RewriteCond %{HTTP_REFERER} (phentemine) [NC,OR]
    RewriteCond %{HTTP_REFERER} (vicodin) [NC,OR]
    RewriteCond %{HTTP_REFERER} (hydrocodone) [NC,OR]
    RewriteCond %{HTTP_REFERER} (levitra) [NC,OR]
    RewriteCond %{HTTP_REFERER} (hgh-) [NC,OR]
    RewriteCond %{HTTP_REFERER} (-hgh) [NC,OR]
    RewriteCond %{HTTP_REFERER} (ultram-) [NC,OR]
    RewriteCond %{HTTP_REFERER} (-ultram) [NC,OR]
    RewriteCond %{HTTP_REFERER} (cialis) [NC,OR]
    RewriteCond %{HTTP_REFERER} (soma-) [NC,OR]
    RewriteCond %{HTTP_REFERER} (-soma) [NC,OR]
    RewriteCond %{HTTP_REFERER} (diazepam) [NC,OR]	
    RewriteCond %{HTTP_REFERER} (gabapentin) [NC,OR]
    RewriteCond %{HTTP_REFERER} (celebrex) [NC,OR]
    RewriteCond %{HTTP_REFERER} (viagra) [NC,OR]
    RewriteCond %{HTTP_REFERER} (fioricet) [NC,OR]
    RewriteCond %{HTTP_REFERER} (ambien) [NC,OR]
    RewriteCond %{HTTP_REFERER} (valium) [NC,OR]
    RewriteCond %{HTTP_REFERER} (zoloft) [NC,OR]
    RewriteCond %{HTTP_REFERER} (finasteride) [NC,OR]
    RewriteCond %{HTTP_REFERER} (lamisil) [NC,OR]
    RewriteCond %{HTTP_REFERER} (meridia) [NC,OR]
    RewriteCond %{HTTP_REFERER} (allegra) [NC,OR]
    RewriteCond %{HTTP_REFERER} (diflucan) [NC,OR]
    RewriteCond %{HTTP_REFERER} (zovirax) [NC,OR]
    RewriteCond %{HTTP_REFERER} (valtrex) [NC,OR]
    RewriteCond %{HTTP_REFERER} (lipitor) [NC,OR]
    RewriteCond %{HTTP_REFERER} (proscar) [NC,OR]
    RewriteCond %{HTTP_REFERER} (acyclovir) [NC,OR]
    RewriteCond %{HTTP_REFERER} (sildenafil) [NC,OR]
    RewriteCond %{HTTP_REFERER} (tadalafil) [NC,OR]
    RewriteCond %{HTTP_REFERER} (xenical) [NC,OR]
    RewriteCond %{HTTP_REFERER} (melatonin) [NC,OR]
    RewriteCond %{HTTP_REFERER} (xanax) [NC,OR]
    RewriteCond %{HTTP_REFERER} (herbal) [NC,OR]
    RewriteCond %{HTTP_REFERER} (drugs) [NC,OR]
    RewriteCond %{HTTP_REFERER} (lortab) [NC,OR]
    RewriteCond %{HTTP_REFERER} (adipex) [NC,OR]
    RewriteCond %{HTTP_REFERER} (propecia) [NC,OR]
    RewriteCond %{HTTP_REFERER} (carisoprodol) [NC,OR]
    RewriteCond %{HTTP_REFERER} (tramadol) [NC]
        RewriteRule .* - [F]

# Porn

    RewriteCond %{HTTP_REFERER} (porno) [NC,OR]
    RewriteCond %{HTTP_REFERER} (shemale) [NC,OR]
    RewriteCond %{HTTP_REFERER} (gangbang) [NC,OR]
    RewriteCond %{HTTP_REFERER} (-cock) [NC,OR]
    RewriteCond %{HTTP_REFERER} (-anal) [NC,OR]
    RewriteCond %{HTTP_REFERER} (-orgy) [NC,OR]
    RewriteCond %{HTTP_REFERER} (cock-) [NC,OR]
    RewriteCond %{HTTP_REFERER} (anal-) [NC,OR]
    RewriteCond %{HTTP_REFERER} (orgy-) [NC,OR]
    RewriteCond %{HTTP_REFERER} (singles-?christian) [NC,OR]
    RewriteCond %{HTTP_REFERER} (dating-?christian) [NC,OR]
    RewriteCond %{HTTP_REFERER} (cumeating) [NC,OR]
    RewriteCond %{HTTP_REFERER} (cream-?pies) [NC,OR]
    RewriteCond %{HTTP_REFERER} (cumsucking) [NC,OR]
    RewriteCond %{HTTP_REFERER} (cumswapping) [NC,OR]
    RewriteCond %{HTTP_REFERER} (cumfilled) [NC,OR]
    RewriteCond %{HTTP_REFERER} (cumdripping) [NC,OR]
    RewriteCond %{HTTP_REFERER} (krankenversicherung) [NC,OR]
    RewriteCond %{HTTP_REFERER} (cumpussy) [NC,OR]
    RewriteCond %{HTTP_REFERER} (suckingcum) [NC,OR]
    RewriteCond %{HTTP_REFERER} (drippingcum) [NC,OR]
    RewriteCond %{HTTP_REFERER} (pussycum) [NC,OR]
    RewriteCond %{HTTP_REFERER} (swappingcum) [NC,OR]
    RewriteCond %{HTTP_REFERER} (eatingcum) [NC,OR]
    RewriteCond %{HTTP_REFERER} (cum-) [NC,OR]
    RewriteCond %{HTTP_REFERER} (-cum) [NC,OR]
    RewriteCond %{HTTP_REFERER} (sperm) [NC,OR]
    RewriteCond %{HTTP_REFERER} (christian-?dating) [NC,OR]
    RewriteCond %{HTTP_REFERER} (jewish-?singles) [NC,OR]
    RewriteCond %{HTTP_REFERER} (sex-?meetings) [NC,OR]
    RewriteCond %{HTTP_REFERER} (swinging) [NC,OR]
    RewriteCond %{HTTP_REFERER} (swingers) [NC,OR]
    RewriteCond %{HTTP_REFERER} (personals) [NC,OR]
    RewriteCond %{HTTP_REFERER} (sleeping) [NC,OR]
    RewriteCond %{HTTP_REFERER} (libido) [NC,OR]
    RewriteCond %{HTTP_REFERER} (grannies) [NC,OR]
    RewriteCond %{HTTP_REFERER} (mature) [NC,OR]
    RewriteCond %{HTTP_REFERER} (enhancement) [NC,OR]
    RewriteCond %{HTTP_REFERER} (sexual) [NC,OR]
    RewriteCond %{HTTP_REFERER} (gay-?teen) [NC,OR]
    RewriteCond %{HTTP_REFERER} (teen-?chat) [NC,OR]
    RewriteCond %{HTTP_REFERER} (gay-?chat) [NC,OR]
    RewriteCond %{HTTP_REFERER} (adult-?finder) [NC,OR]
    RewriteCond %{HTTP_REFERER} (adult-?friend) [NC,OR]
    RewriteCond %{HTTP_REFERER} (friend-?finder) [NC,OR]
    RewriteCond %{HTTP_REFERER} (friend-?adult) [NC,OR]
    RewriteCond %{HTTP_REFERER} (finder-?adult) [NC,OR]
    RewriteCond %{HTTP_REFERER} (finder-?friend) [NC,OR]
    RewriteCond %{HTTP_REFERER} (discrete-?encounters) [NC,OR]
    RewriteCond %{HTTP_REFERER} (cheating-?wives) [NC,OR]
    RewriteCond %{HTTP_REFERER} (housewives) [NC,OR]
    RewriteCond %{HTTP_REFERER} (\-sex\.) [NC,OR]
    RewriteCond %{HTTP_REFERER} (xxx) [NC,OR]
    RewriteCond %{HTTP_REFERER} (snowballing) [NC]		
        RewriteRule .* - [F]

# Weight

    RewriteCond %{HTTP_REFERER} (fat-) [NC,OR]	
    RewriteCond %{HTTP_REFERER} (-fat) [NC,OR]	
    RewriteCond %{HTTP_REFERER} (diet) [NC,OR]
    RewriteCond %{HTTP_REFERER} (pills) [NC,OR]
    RewriteCond %{HTTP_REFERER} (weight) [NC,OR]
    RewriteCond %{HTTP_REFERER} (supplement) [NC]		
        RewriteRule .* - [F]	

# Gambling

    RewriteCond %{HTTP_REFERER} (texas-?hold-?em) [NC,OR]
    RewriteCond %{HTTP_REFERER} (poker) [NC,OR]
    RewriteCond %{HTTP_REFERER} (casino) [NC,OR]
    RewriteCond %{HTTP_REFERER} (blackjack) [NC]		
        RewriteRule .* - [F]

# Loans / Finance

    RewriteCond %{HTTP_REFERER} (mortgage) [NC,OR]
    RewriteCond %{HTTP_REFERER} (refinancing) [NC,OR]
    RewriteCond %{HTTP_REFERER} (cash-?advance) [NC,OR]
    RewriteCond %{HTTP_REFERER} (cash-?money) [NC,OR]
    RewriteCond %{HTTP_REFERER} (pay-?day) [NC]		
        RewriteRule .* - [F]

# User Agents

    RewriteCond %{HTTP_USER_AGENT} (Program\ Shareware|Fetch\ API\ Request) [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} (Microsoft\ URL\ Control) [NC]
        RewriteRule .* - [F]

# Misc / Specific Sites

    RewriteCond %{HTTP_REFERER} (netwasgroup\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (nic4u\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (wear4u\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (foxmediasolutions\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (liveplanets\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (aeterna-tech\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (continentaltirebowl\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (chemsymphony\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (infolibria\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (globaleducationeurope\.net) [NC,OR]
    RewriteCond %{HTTP_REFERER} (soma\.125mb\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (mitglied\.lycos\.de) [NC,OR]
    RewriteCond %{HTTP_REFERER} (foxmediasolutions\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (jroundup\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (feathersandfurvanlines\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (conecrusher\.org) [NC,OR]
    RewriteCond %{HTTP_REFERER} (sbj-broadcasting\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (edthompson\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (codychesnutt\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (artsmallforsenate\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (axionfootwear\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (protzonbeer\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (candiria\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (bigsitecity\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (coresat\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (istarthere\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (amateurvoetbal\.net) [NC,OR]
    RewriteCond %{HTTP_REFERER} (alleghanyeda\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (xadulthosting\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (datashaping\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (zick\.biz) [NC,OR]
    RewriteCond %{HTTP_REFERER} (newprinceton\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (dvdsqueeze\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (xopy\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (webdevboard\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (devaddict\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (eaton-inc\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (whiteguysgroup\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (guestbookz\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (webdevsquare\.com) [NC,OR]
    RewriteCond %{HTTP_REFERER} (indfx\.net) [NC,OR]
    RewriteCond %{HTTP_REFERER} (snap\.to) [NC,OR]
    RewriteCond %{HTTP_REFERER} (2y\.net) [NC,OR]
    RewriteCond %{HTTP_REFERER} (astromagia\.info) [NC,OR]
    RewriteCond %{HTTP_REFERER} (free-?sms) [NC]       
        RewriteRule .* - [F]</code>

<p>The above will block just about all of the most common referral spam that I've seen so far. I'm adding to the list constantly (last addition: 14th September 2005) so do check back and see if there are updates if you're using it.</p>

<p>One potential problem with this technique, other than that it will, in time, become useless as too many URLs are added, is that there is always a possibility authentic visitors will be blocked. So, on this site, instead of the last line above, I've actually used something a little more user-friendly:</p>

<code>RewriteRule .* bad_referrer.php [L]</code>

<p>Instead of a "Forbidden" message, this displays a quick note explaining why there has been an error and that the user can click on a link to proceed. If you want to check this out for yourself, try visiting <a href="http://www.addedbytes.com/swingers/block-referrer-spam/">http://www.addedbytes.com/swingers/block-referrer-spam/</a> (note the "swingers" portion of the URL). This page will reload with a new URL. Then try visiting <a href="http://www.addedbytes.com/spam/block-referrer-spam/">http://www.addedbytes.com/spam/block-referrer-spam/</a>. You should find you get a message explaining what has happened, and a URL to click if you want to proceed.</p>

<p>And there we have it. With minimum effort (for now), referral log spamming in my site has been almost entirely removed. Before adding this set of rules and scripts, I was seeing around 200 fake referrals per day in my log files. Now, I see about 3 or 4 a week. Hopefully, this will continue until I can devise a better way of protecting against this kind of problem - before blacklists become an impossibility to manage.</p> <br><br>]]></description>
				<pubDate>Wed, 14 Sep 2005 10:36:00 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/blog/block-referrer-spam/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=admin&amp;start=0" class="ditto_tag" rel="tag">admin</a>,<a href="/feeds/tag-feed/?tags=apache&amp;start=0" class="ditto_tag" rel="tag">apache</a>,<a href="/feeds/tag-feed/?tags=howto&amp;start=0" class="ditto_tag" rel="tag">howto</a>,<a href="/feeds/tag-feed/?tags=htaccess&amp;start=0" class="ditto_tag" rel="tag">htaccess</a>,<a href="/feeds/tag-feed/?tags=referrer&amp;start=0" class="ditto_tag" rel="tag">referrer</a>,<a href="/feeds/tag-feed/?tags=server&amp;start=0" class="ditto_tag" rel="tag">server</a>,<a href="/feeds/tag-feed/?tags=spam&amp;start=0" class="ditto_tag" rel="tag">spam</a>,<a href="/feeds/tag-feed/?tags=webdev&amp;start=0" class="ditto_tag" rel="tag">webdev</a>,<a href="/feeds/tag-feed/?tags=wordpress&amp;start=0" class="ditto_tag" rel="tag">wordpress</a>
			</item>

			<item>
				<title>Writing Secure PHP, Part 3</title>
				<link>http://www.addedbytes.com/writing-secure-php/writing-secure-php-3/</link>
				<description><![CDATA[ The third part of the Writing Secure PHP series, covering weak passwords, clients and more advanced topics. <p>In <a href="http://www.addedbytes.com/php/writing-secure-php/">Writing Secure PHP</a> and <a href="http://www.addedbytes.com/security/writing-secure-php-2/">Writing Secure PHP, Part 2</a> I covered many of the basic mistakes PHP developers make, and how to avoid common security problems. It is time to get a little deeper into security though, and begin to tackle some more advanced issues.</p>

<p>[Writing Secure PHP is a series. <a href="http://www.addedbytes.com/php/writing-secure-php/">Part 1</a>, <a href="http://www.addedbytes.com/php/writing-secure-php-2/">Part 2</a> and <a href="http://www.addedbytes.com/php/writing-secure-php-4/">Part 4</a> are currently also available.]</p>

<h3>Context</h3>

<p>Before I start, it is worth mentioning at this point in this series that much of what is to come is highly dependant on context. If you are running a small personal site and are regularly backing it up, the chances are that there is no real benefit to you spending weeks on advanced security issues. If an attacker can gain nothing (and cause no harm) by compromising your site, and it would only take you ten minutes to restore it, should something go wrong, then it would be a waste to spend too long on security concerns. At the other end of the scale, if you are managing an ecommerce site that processes thousands of credit cards a day, then it is negligent not to spend a lot of time researching and improving your site's security.</p>

<h3>Database Field Lengths</h3>

<p>Database (we're going to talk about <a href="http://www.mysql.com">MySQL</a> here, but this is applicable to any database) fields are always of a specific type, and every type has its limits. You can as well, in MySQL, limit field lengths further than they are already limited by their types.</p>

<p>However, to the inexperienced developer, this can present problems. If you are allowing users to post an article on your site, and adding that to a database field with type "blob", then the longest article you can store in the database is 65,535 characters. For most articles that will be fine, but what is going to happen when a user posts an article of 100,000 characters? At best, if you have set up your site so errors are not displayed, their article will simply vanish without being added to the site.</p>

<p>Remember that for an attacker to be able to compromise your system, they need information about it. They need to find weaknesses. Error messages are a very powerful part of that and if you are displaying errors, then an attacker can make use of this to find out information about your database.</p>

<p>To fix this, simply check the lengths of data input through forms and querystrings and ensure that before you launch a site you check forms will not cause errors to be displayed when too many characters are entered.</p>

<h3>Weak Passwords</h3>

<p>Dictionaries are a useful tool for an attacker. If you have a site with a login system and your database were compromised (and there is no harm in assuming that at some point it will be), an attacker can grab a list of hashed passwords. It is difficult (practically impossible) to directly translate a hash back into a password.</p>

<p>However, most attackers will have databases containing lists of words and their matching hashes in common formats (eg a database with all words in English and their MD5 hashes). It is fairly easy, should someone gain access to your database, for them to compare a hashed password to this list of pre-hashed passwords. If a match is found in the list, the attacker then knows what the un-hashed password is.</p>

<p>There are ways to avoid this problem, and the best of those is to ensure that only strong passwords are ever used. Some people find guaging the strength of passwords tricky, but the general rule of thumb is: a password like "password", "admin", "god", "sex", "qwerty", "123456" or similar (i.e. easily guessable) is extremely weak; a password made up only of a word in the dictionary is weak; a password made of letters, numbers and making use of upper and lower case is strong (there is a strong usability case to be made for not using case-sensitive passwords - if you wish to use case-insensitve ones, simply perform checks to ensure people do not pick passwords like "password12345").</p>

<h3>Clients</h3>

<p>Clients are a huge security risk, believe it or not. Some will hire a cheaper developer to make small changes six months after you're finished. Some will give out FTP details to anyone who phones and asks for them. [Out of curiosity, I decided to see how easy it is to get FTP details over the phone. I visited the site of a local company (who shall remain nameless) and found the name of their design company (who shall also remain nameless). I then phoned the local company and told them I was with the design company and needed them to send me the site's FTP details. They agreed without question or hesitation. Scary. (I told them what I was doing before they sent any sensitive data to me and they are now better educated and suitably paranoid about people asking for details over the phone).]</p>

<p>Some will ignore emails from people pointing out security problems (in the process of writing the previous article in this series, I found a large selection of sites with publically available database connection scripts. I emailed the owners explaining why they are at risk, and only one has replied and had the problem fixed at the time of writing). Admitedly, many of the emails and calls they receive will be misinformation or sales pitches, but it is still worth them having someone check this out - they do not know enough to distinguish a genuine problem from the rest.</p>

<p>Unfortunately, this is one security problem that cannot be solved with code. This one requires education. For this reason, I have created an unbranded copy of the sheet I give to my clients, with a selection of security tips on. When we launch the site, I sit down with them and tell them how they need to treat their site, and what to consider when making decisions regarding it.</p>

<p><a href="content/writing-secure-php-3/client_security.png">Client Security Handout</a> (PNG, 74KB)</p>

<h3>Code Injection (a.k.a. "Cross-Site Scripting")</h3>

<p>Unlike SQL Injection, which relies on the use of delimiters in user-input text to take control of database queries, code injection relies on mistakes in the treatment of text before it is output. Or, to put it in simpler terms, code injection is where a malicious user uses a text box to add HTML that they've written to your webpage.</p>

<p>Let's say you have a system that allows users to register as members to your site and that they are allowed to create their own username. They fill out a form, and you insert the data they enter, once you've made it safe to use in a SQL query, into a database. Your members listing page fetches all the usernames from the database and lists them, outputting exactly what is in the database to anyone that views that page.</p>

<p>Now, let's say you've not added a limit to username lengths. Someone could, if they wanted, create a user with the following username:</p>

<pre class="php">Username&lt;script type="text/javascript" src="http://www.website.com/malicious.js"&gt;&lt;/script&gt;</pre>

<p>Anyone that then views a page with that username on it will see a normal username, but a JavaScript has been loaded from another site invisibly to the user.</p>

<p>There are plenty of uses for this. First and foremost, it allows attackers to add keyloggers, tracking scripts or porn banners on your site, or just stop your site working altogether. There are several ways to ensure this doesn't happen. First, you could encode HTML in usernames. If you wanted to allow people to use greater-then and less-than signs in their usernames, that is. If not, you can strip these characters out, or strip out HTML tags altogether.</p>

<p>Another, better way to approach this is to limit the character set that can be used in usernames. If you only allow letters and numbers, for example, you could simply use a regular expression in the signup process to validate the username and force the user to pick another if they have disallowed characters in their username. Obviously the problem is not just applicable to usernames - however, as with most other security concerns, being quite paranoid will ensure that you always check data coming from a user before outputting it, and sanitising it in an appropriate way.</p>

<h3>Aftermath</h3>

<p>Part of a good security strategy is the assumption that at some point everything (and I mean everything) will be deleted or destroyed. It is wise to assume that at some point any security measure you have in place will be compromised. All data may be taken (which is one reason why it is important to encrypt things like passwords and credit card numbers in databases), all files deleted and so on.</p>

<p>One part of PHP development, though perhaps not directly about PHP security, is ensuring that after a catastrophic failure a site can be brought back online quickly. While downtime of four hours maybe acceptable with a low-traffic point-of-presence site, any ecommerce retailer is going to erupt with fury at the thought of that much lost revenue.</p>

<p>Dealing with the client under these circumstances is the first step. Often, your first inkling of a problem with a site may actually come from the client. They may have phoned you and could be angry, worried, or a myriad of other emotions. At moments like this, you would be very glad to have a clear contigency plan in place. Many developers panic when the client phones saying their front page has been defaced. Stick to your action plan and to your client you will seem confident and unphased. That will relax them. The plan will also allow you to resolve the problem far faster.</p>

<p>First, find out what happened. Are you dealing with a security breach or has someone at the host company tripped over a power lead? Was the database compromised, or deleted, as a result of an attack or was your server simply unable to cope with too much traffic? You need to know what has happened in order to deal with it - a site going offline could be down to too many factors to just assume it is a security problem.</p>

<p>Assuming this is a security problem, the next step is to reassure the client. Let them know what has happened. If someone got into the database, no problem - all sensitive data is encrypted. If they've uploaded files to your server (quite possible), you'll have to delete all files and restore from a backup.</p>

<p>You've got to find out how the attacker broke into your system. Check log files, if you have access to them. Also, have a look at hacker and cracker web sites - many of them will list successful attacks against servers by various groups (these are often what are sometimes known as "script kiddies" - not hackers as such, but usually exploiting vulnerabilities found by others). You may well find your site listed and that listing will give you invaluable information. Look at other sites brought down by the same group at around the same time - you will often spot a theme (e.g. all sites that have been attacked were running the same version of <a href="http://www.microsoft.com/WindowsServer2003/iis/default.mspx">IIS</a> or <a href="http://www.apache.org">Apache</a>, were all running <a href="http://www.phpbb.com">phpBB</a>, or all are file repositories running on <a href="http://www.macromedia.com/v1/cfdocs/cfml_language_reference/contents.htm">CFML</a>).</p>

<p>If you are running any third party software on the site, check the distribution site and if necessary get in touch with them, especially if other sites running the same software appear to have been compromised.</p>

<p>It is very important that you fix any hole there may be before you restore the site. It would be wise to add a "We are currently undergoing essential maintenance" page, but do not fully restore the site before you have found out and fixed whatever the problem was - you'll be wasting your time.</p>

<h3>Shared Hosting</h3>

<p>Shared hosting is much cheaper than dedicated hosting, and is where several sites are all hosted on the same server. Most sites are hosted this way, and this brings with it its own set of security issues.</p>

<p>First and foremost, the security of your site is, in these circumstances, almost entirely out of your hands. It is dependant on the hosting company you are with. They may be excellent, or they may be crooks. Check reviews of a company before you select them, as they will have access to all the data you store with them. There is no harm in being automatically suspicious of your hosting company.</p>

<p>If they are completely above board (and most are), you are still not necessarily secure with shared hosting. The security measures they put in place are generally pretty simple. Shared hosting servers should always use PHP's safe mode (which disables many of the more advanced and dangerous features of PHP). That is what it is there for. However, many don't.</p>

<p>Vulnerabilities associated with shared hosting are, for the most part, out of your hands. A badly set up server will allow any site on that server to access files like /etc/passwd and httpd.conf, often giving them access to all other sites on the same server. It is possible to secure yourself to some degree against the effects of this vulnerability. Storing information in a database is recommended. Of course, if you then store your database login in a file, an attacked could access this information. In order to make this inaccessible to others on the same server, you could set database login information within the httpd.conf file, using environmental variables (you will need to ask your host company to add the lines to the httpd.conf file).</p>

<p>Better yet is to ensure that your host, if shared, uses safe mode. While this is still not 100% secure (nothing is), it does help make these attacks more difficult. A dedicated server is another, far better, option, but the expense may be prohibitive.</p>

<p><em>Ready for more? Try <a href="http://www.addedbytes.com/security/writing-secure-php-4/">Writing Secure PHP, Part 4</a>.</em></p> <br><br>]]></description>
				<pubDate>Wed, 27 Jul 2005 08:58:00 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/writing-secure-php/writing-secure-php-3/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=guide&amp;start=0" class="ditto_tag" rel="tag">guide</a>,<a href="/feeds/tag-feed/?tags=php&amp;start=0" class="ditto_tag" rel="tag">php</a>,<a href="/feeds/tag-feed/?tags=programming&amp;start=0" class="ditto_tag" rel="tag">programming</a>,<a href="/feeds/tag-feed/?tags=security&amp;start=0" class="ditto_tag" rel="tag">security</a>,<a href="/feeds/tag-feed/?tags=tips&amp;start=0" class="ditto_tag" rel="tag">tips</a>,<a href="/feeds/tag-feed/?tags=web&amp;start=0" class="ditto_tag" rel="tag">web</a>,<a href="/feeds/tag-feed/?tags=webdev&amp;start=0" class="ditto_tag" rel="tag">webdev</a>,<a href="/feeds/tag-feed/?tags=work&amp;start=0" class="ditto_tag" rel="tag">work</a>
			</item>

			<item>
				<title>Block Prefetching</title>
				<link>http://www.addedbytes.com/blog/block-prefetching/</link>
				<description><![CDATA[ <p>Mozilla and Google's prefetching functions are a nice addition to browser technology in many ways. Unsurprisingly, they are not very well thought through.</p> <p>Mozilla and Google's prefetching functions are a nice addition to browser technology in many ways. Unsurprisingly, they are not very well thought through. The main two problems with the prefetching idea are that it messes with log files and it means every link on a page could potentially be followed despite the consequences (dangerous in a site administration context).</p>

<p>It appears from the FAQ that Google only intends their accelerator to prefetch specific pages, that have been specified with the &lt;link&gt; tag. However, many people are claiming that normal links have been prefetched.</p>

<p>To prevent prefetching of a page is simple: add the following PHP to the page you do not want prefetched:</p>

<pre class="php">if ((isset($_SERVER['HTTP_X_MOZ'])) && ($_SERVER['HTTP_X_MOZ'] == 'prefetch')) {
    // This is a prefetch request. Block it.
    header('HTTP/1.0 403 Forbidden');
    echo '403: Forbidden&lt;br&gt;&lt;br&gt;Prefetching not allowed here.';
    die();
}</pre>

<p>This will serve a "forbidden" header to the prefetcher. Normal browsing should be unaffected.</p> <br><br>]]></description>
				<pubDate>Wed, 20 Apr 2005 15:16:00 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/blog/block-prefetching/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=block&amp;start=0" class="ditto_tag" rel="tag">block</a>,<a href="/feeds/tag-feed/?tags=google&amp;start=0" class="ditto_tag" rel="tag">google</a>,<a href="/feeds/tag-feed/?tags=mozilla&amp;start=0" class="ditto_tag" rel="tag">mozilla</a>,<a href="/feeds/tag-feed/?tags=php&amp;start=0" class="ditto_tag" rel="tag">php</a>,<a href="/feeds/tag-feed/?tags=prefetching&amp;start=0" class="ditto_tag" rel="tag">prefetching</a>,<a href="/feeds/tag-feed/?tags=reference&amp;start=0" class="ditto_tag" rel="tag">reference</a>,<a href="/feeds/tag-feed/?tags=webdev&amp;start=0" class="ditto_tag" rel="tag">webdev</a>
			</item>

			<item>
				<title>Writing Secure PHP, Part 2</title>
				<link>http://www.addedbytes.com/writing-secure-php/writing-secure-php-2/</link>
				<description><![CDATA[ Learn how to improve your security a little further with the second part of this PHP tutorial. <p>In <a href="http://www.addedbytes.com/php/writing-secure-php/">Writing Secure PHP</a>, I covered a few of the most common security holes in websites. It's time to move on, though, to a few more advanced techniques for securing a website. As techniques for 'breaking into' a site or crashing a site become more advanced, so must the methods used to stop those attacks.</p>

<p>[Writing Secure PHP is a series. <a href="http://www.addedbytes.com/php/writing-secure-php/">Part 1</a>, <a href="http://www.addedbytes.com/php/writing-secure-php-3/">Part 3</a> and <a href="http://www.addedbytes.com/php/writing-secure-php-4/">Part 4</a> are currently also available.]</p>

<h3>File Systems</h3>

<p>Most hosting environments are very similar, and rather predictable. Many web developers are also very predictable. It doesn't take a genius to guess that a site's includes (and most dynamic sites use an includes directory for common files) is an www.website.com/includes/. If the site owner has allowed directory listing on the server, anyone can navigate to that folder and browse files.</p>

<p>Imagine for a second that you have a database connection script, and you want to connect to the database from every page on your site. You might well place that in your includes folder, and call it something like connect.inc. However, this is very predictable - many people do exactly this. Worst of all, a file with the extension ".inc" is usually rendered as text and output to the browser, rather than processed as a PHP script - meaning if someone were to visit that file in a browser, they'll be given your database login information.</p>

<p>Placing important files in predictable places with predictable names is a recipe for disaster. Placing them outside the web root can help to lessen the risk, but is not a foolproof solution. The best way to protect your important files from vulnerabilities is to place them outside the web root, in an unusually-named folder, and to make sure that error reporting is set to off (which should make life difficult for anyone hoping to find out where your important files are kept). You should also make sure directory listing is not allowed, and that all folders have a file named "index.html" in (at least), so that nobody can ever see the contents of a folder.</p>

<p>Never, ever, give a file the extension ".inc". If you must have ".inc" in the extension, use the extension ".inc.php", as that will ensure the file is processed by the PHP engine (meaning that anything like a username and password is not sent to the user). Always make sure your includes folder is outside your web root, and not named something obvious. Always make sure you add a blank file named "index.html" to all folders like include or image folders - even if you deny directory listing yourself, you may one day change hosts, or someone else may alter your server configuration - if directory listing is allowed, then your index.html file will make sure the user always receives a blank page rather than the directory listing. As well, always make sure directory listing is denied on your web server (easily done with .htaccess or httpd.conf).</p>

<p>------</p>

<p>Out of sheer curiosity, shortly after writing this section of this tutorial, I decided to see how many sites I could find in a few minutes vulnerable to this type of attack. Using <a href="http://www.google.com">Google</a> and a few obvious search phrases, I found about 30 database connection scripts, complete with usernames and passwords. A little more hunting turned up plenty more open include directories, with plenty more database connections and even FTP details. All in, it took about ten minutes to find enough information to cause serious damage to around 50 sites, without even using these vulnerabilities to see if it were possible to cause problems for other sites sharing the same server.</p>

<p>-----</p>

<h3>Login Systems</h3>

<p>Most site owners now require an online administration area or CMS (content management system), so that they can make changes to their site without needing to know how to use an <a href="http://filezilla.sourceforge.net/">FTP client</a>. Often, these are placed in predictable locations (as covered in the last article), however placing an administration area in a hard-to-find location isn't enough to protect it.</p>

<p>Most CMSes allow users to change their password to anything they choose. Many users will pick an easy-to-remember word, often the name of a loved one or something similar with special significance to them. Attackers will use something called a "dictionary attack" (or "brute force attack") to break this kind of protection. A dictionary attack involves entering each word from the dictionary in turn as the password until the correct one is found.</p>

<p>The best way to protect against this is threefold. First, you should add a turing test to a login page. Have a randomly generated series of letters and numbers on the page that the user must enter to login. Make sure this series changes each time the user tries to login, that it is an image (rather than simple text), and that it cannot be identified by an optical character recognition script.</p>

<p>Second, add in a simple counter. If you detect a certain number of failed logins in a row, disable logging in to the administration area until it is reactivated by someone responsible. If you only allow each potential attacker a small number of attempts to guess a password, they will have to be very lucky indeed to gain access to the protected area. This might be inconvenient for authentic users, however is usually a price worth paying.</p>

<p>Finally, make sure you track IP addresses of both those users who successfully login and those who don't. If you spot repeated attempts from a single IP address to access the site, you may consider blocking access from that IP address altogether.</p>

<h3>Database Users</h3>

<p>One excellent way to make sure that even if you have a problem with someone accessing your database who shouldn't be able to, you can limit the damage they can cause. Modern databases like MySQL and SQL Server allow you to control what a user can and cannot do. You can give users (or not) permission to create data, edit, delete, and more using these permissions. Usually, I try and ensure that I only allow users to add and edit data.</p>

<p>If a site requires an item be deleted, I will usually set the front end of the site to only appear to delete the item. For example, you could have a numeric field called "item_deleted", and set it to 1 when an item is deleted. You can then use that to prevent users seeing these items. You can then purge these later if required, yourself, while not giving your users "delete" permissions for the database. If a user cannot delete or drop tables, neither can someone who finds out the user login to the database (though obviously they can still do damage).</p>

<h3>Powerful Commands</h3>

<p>PHP contains a variety of commands with access to the operating system of the server, and that can interact with other programs. Unless you need access to these specific commands, it is highly recommended that you disable them entirely.</p>

<p>For example, the <a href="http://www.php.net/eval">eval()</a> function allows you to treat a string as PHP code and execute it. This can be a useful tool on occasion. However, if using the <a href="http://www.php.net/eval">eval()</a> function on any input from the user, the user could cause all sorts of problems. You could be, without careful input validation, giving the user free reign to execute whatever commands he or she wants.</p>

<p>There are ways to get around this. Not using <a href="http://www.php.net/eval">eval()</a> is a good start. However, the php.ini file gives you a way to completely disable certain functions in PHP - "disable_functions". This directive of the php.ini file takes a comma-separated list of function names, and will completely disable these in PHP. Commonly disabled functions include <a href="http://www.php.net/ini_set">ini_set()</a>, <a href="http://www.php.net/exec">exec()</a>, <a href="http://www.php.net/fopen">fopen()</a>, <a href="http://www.php.net/popen">popen()</a>, <a href="http://www.php.net/passthru">passthru()</a>, <a href="http://www.php.net/readfile">readfile()</a>, <a href="http://www.php.net/file">file()</a>, <a href="http://www.php.net/shell_exec">shell_exec()</a> and <a href="http://www.php.net/system">system()</a>.</p>

<p>It may be (it usually is) worth enabling safe_mode on your server. This instructs PHP to limit the use of functions and operators that can be used to cause problems. If it is possible to enable safe_mode and still have your scripts function, it is usually best to do so.</p>

<h3>Finally, Be Completely and Utterly Paranoid</h3>

<p>Much as I hate to bring this point up again, it still holds true (and always will). Most of the above problems can be avoided through careful input validation. Some become obvious points to address when you assume everyone is out to destroy your site. If you are prepared for the worst, you should be able to deal with anything.</p>

<p><em>Ready for more? Try <a href="http://www.addedbytes.com/security/writing-secure-php-3/">Writing Secure PHP, Part 3</a>.</em></p> <br><br>]]></description>
				<pubDate>Tue, 22 Mar 2005 16:53:00 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/writing-secure-php/writing-secure-php-2/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=development&amp;start=0" class="ditto_tag" rel="tag">development</a>,<a href="/feeds/tag-feed/?tags=imported&amp;start=0" class="ditto_tag" rel="tag">imported</a>,<a href="/feeds/tag-feed/?tags=mysql&amp;start=0" class="ditto_tag" rel="tag">mysql</a>,<a href="/feeds/tag-feed/?tags=php&amp;start=0" class="ditto_tag" rel="tag">php</a>,<a href="/feeds/tag-feed/?tags=programming&amp;start=0" class="ditto_tag" rel="tag">programming</a>,<a href="/feeds/tag-feed/?tags=security&amp;start=0" class="ditto_tag" rel="tag">security</a>,<a href="/feeds/tag-feed/?tags=web&amp;start=0" class="ditto_tag" rel="tag">web</a>,<a href="/feeds/tag-feed/?tags=webdev&amp;start=0" class="ditto_tag" rel="tag">webdev</a>,<a href="/feeds/tag-feed/?tags=work&amp;start=0" class="ditto_tag" rel="tag">work</a>
			</item>

			<item>
				<title>Writing Secure PHP, Part 1</title>
				<link>http://www.addedbytes.com/writing-secure-php/writing-secure-php-1/</link>
				<description><![CDATA[ Learn how to avoid some of the most common mistakes in PHP, and so make your sites more secure. <p><a href="http://www.php.net">PHP</a> is a very easy language to learn, and many people without any sort of background in programming learn it as a way to add interactivity to their web sites. Unfortunately, that often means PHP programmers, especially those newer to web development, are unaware of the potential security risks their web applications can contain. Here are a few of the more common security problems and how to avoid them.</p>

<p>[Writing Secure PHP is a series. <a href="http://www.addedbytes.com/php/writing-secure-php-2/">Part 2</a>, <a href="http://www.addedbytes.com/php/writing-secure-php-3/">Part 3</a> and <a href="http://www.addedbytes.com/php/writing-secure-php-4/">Part 4</a> are currently also available.]</p>

<h3>Rule Number One: Never, Ever, Trust Your Users</h3>

<p>It can never be said enough times, you should never, ever, ever trust your users to send you the data you expect. I have heard many people respond to that with something like "Oh, nobody malicious would be interested in my site". Leaving aside that that could not be more wrong, it is not always a malicious user who can exploit a security hole - problems can just as easily arise because of a user unintentionally doing something wrong.</p>

<p>So the cardinal rule of all web development, and I can't stress it enough, is: <strong>Never, Ever, Trust Your Users</strong>. Assume every single piece of data your site collects from a user contains malicious code. Always. That includes data you think you have checked with client-side validation, for example using JavaScript. If you can manage that, you'll be off to a good start. If PHP security is important to you, this single point is the most important to learn. Personally, I have a "PHP Security" sheet next to my desk with major points on, and this is in large bold text, right at the top.</p>

<h3>Global Variables</h3>

<p>In many languages you must explicitly create a variable in order to use it. In PHP, there is an option, "register_globals", that you can set in php.ini that allows you to use global variables, ones you do not need to explicitly create. </p>

<p>Consider the following code:</p>

<pre class="php">if ($password == "my_password") {
    $authorized = 1;
}

if ($authorized == 1) {
    echo "Lots of important stuff.";
}</pre>

<p>To many that may look fine, and in fact this exact type of code is in use all over the web. However, if a server has "register_globals" set to on, then simply adding "?authorized=1" to the URL will give anyone free access to exactly what you do not want everyone to see. This is one of the most common PHP security problems.</p>

<p>Fortunately, this has a couple of possible simple solutions. The first, and perhaps the best, is to set "register_globals" to off. The second is to ensure that you only use variables that you have explicitly set yourself. In the above example, that would mean adding "$authorized = 0;" at the beginning of the script:</p>

<pre class="php">$authorized = 0;
if ($password == "my_password") {
    $authorized = 1;
}

if ($authorized == 1) {
    echo "Lots of important stuff.";
}</pre>

<h3>Error Messages</h3>

<p>Errors are a very useful tool for both programmer and hacker. A developer needs them in order to fix bugs. A hacker can use them to find out all sorts of information about a site, from the directory structure of the server to database login information. If possible, it is best to turn off all error reporting in a live application. PHP can be told to do this through .htaccess or php.ini, by setting "error_reporting" to "0". If you have a development environment, you can set a different error reporting level for that.</p>

<h3>SQL Injection</h3>

<p>One of PHP's greatest strengths is the ease with which it can communicate with databases, most notably <a href="http://www.mysql.com">MySQL</a>. Many people make extensive use of this, and a great many sites, including this one, rely on databases to function.</p>

<p>However, as you would expect, with that much power there are potentially huge security problems you can face. Fortunately, there are plenty of solutions. The most common security hazard faced when interacting with a database is that of SQL Injection - when a user uses a security glitch to run SQL queries on your database.</p>

<p>Let's use a common example. Many login systems feature a line that looks a lot like this when checking the username and password entered into a form by a user against a database of valid username and password combinations, for example to control access to an administration area:</p>

<pre class="php">$check = mysql_query("SELECT Username, Password, UserLevel FROM Users WHERE Username = '".$_POST['username']."' and Password = '".$_POST['password']."'");</pre>

<p>Look familiar? It may well do. And on the face of it, the above does not look like it could do much damage. But let's say for a moment that I enter the following into the "username" input box in the form and submit it:</p>

<pre class="php">' OR 1=1 #</pre>

<p>The query that is going to be executed will now look like this:</p>

<pre class="sql">SELECT Username, Password FROM Users WHERE Username = '' OR 1=1 #' and Password = ''</pre>

<p>The hash symbol (#) tells MySQL that everything following it is a comment and to ignore it. So it will actually only execute the SQL up to that point. As 1 always equals 1, the SQL will return all of the usernames and passwords from the database. And as the first username and password combination in most user login databases is the admin user, the person who simply entered a few symbols in a username box is now logged in as your website administrator, with the same powers they would have if they actually knew the username and password.</p>

<p>With a little creativity, the above can be exploited further, allowing a user to create their own login account, read credit card numbers or even wipe a database clean.</p>

<p>Fortunately, this type of vulnerability is easy enough to work around. By checking for apostrophes in the items we enter into the database, and removing or neutralising them, we can prevent anyone from running their own SQL code on our database. The function below would do the trick:</p>

<pre class="php">function make_safe($variable) {
    $variable = mysql_real_escape_string(trim($variable));
    return $variable;
}</pre>

<p>Now, to modify our query. Instead of using _POST variables as in the query above, we now run all user data through the make_safe function, resulting in the following code:</p>

<pre class="php">$username = make_safe($_POST['username']);
$password = make_safe($_POST['password']);
$check = mysql_query("SELECT Username, Password, UserLevel FROM Users WHERE Username = '".$username."' and Password = '".$password."'");</pre>

<p>Now, if a user entered the malicious data above, the query will look like the following, which is perfectly harmless. The following query will select from a database where the username is equal to "\' OR 1=1 #".</p>

<pre class="sql">SELECT Username, Password, UserLevel FROM Users WHERE Username = '\' OR 1=1 #' and Password = ''</pre>

<p>Now, unless you happen to have a user with a very unusual username and a blank password, your malicious attacker will not be able to do any damage at all. It is important to check all data passed to your database like this, however secure you think it is. HTTP Headers sent from the user can be faked. Their referral address can be faked. Their browsers User Agent string can be faked. Do not trust a single piece of data sent by the user, though, and you will be fine.</p>

<h3>File Manipulation</h3>

<p>Some sites currently running on the web today have URLs that look like this:</p>

<pre class="php">index.php?page=contactus.html</pre>

<p>The "index.php" file then simply includes the "contactus.html" file, and the site appears to work. However, the user can very easily change the "contactus.html" bit to anything they like. For example, if you are using <a href="http://www.apache.org/">Apache</a>'s mod_auth to protect files and have saved your password in a file named ".htpasswd" (the conventional name), then if a user were to visit the following address, the script would output your username and password:</p>

<pre class="php">index.php?page=.htpasswd</pre>

<p>By changing the URL, on some systems, to reference a file on another server, they could even run PHP that they have written on your site. Scared? You should be. Fortunately, again, this is reasonably easy to protect against. First, make sure you have correctly set "open_basedir" in your php.ini file, and have set "allow_url_fopen" to "off". That will prevent most of these kinds of attacks by preventing the inclusion of remote files and system files. Next, if you can, check the file requested against a list of valid files. If you limit the files that can be accessed using this script, you will save yourself a lot of aggravation later.</p>

<h3>Using Defaults</h3>

<p>When MySQL is installed, it uses a default username of "root" and blank password. SQL Server uses "sa" as the default user with a blank password. If someone finds the address of your database server and wants to try to log in, these are the first combinations they will try. If you have not set a different password (and ideally username as well) than the default, then you may well wake up one morning to find your database has been wiped and all your customers' credit card numbers stolen. The same applies to all software you use - if software comes with default username or password, change them.</p>

<h3>Leaving Installation Files Online</h3>

<p>Many PHP programs come with installation files. Many of these are self-deleting once run, and many applications will refuse to run until you delete the installation files. Many however, will not pay the blindest bit of attention if the install files are still online. If they are still online, they may still be usable, and someone may be able to use them to overwrite your entire site.</p>

<h3>Predictability</h3>

<p>Let us imagine for a second that your site has attracted the attention of a Bad Person. This Bad Person wants to break in to your administration area, and change all of your product descriptions to "This Product Sucks". I would hazard a guess that their first step will be to go to http://www.yoursite.com/admin/ - just in case it exists. Placing your sensitive files and folders somewhere predictable like that makes life for potential hackers that little bit easier.</p>

<p>With this in mind, make sure you name your sensitive files and folders so that they are tough to guess. Placing your admin area at http://www.yoursite.com/jsfh8sfsifuhsi8392/ might make it harder to just type in quickly, but it adds an extra layer of security to your site. Pick something memorable by all means if you need an address you can remember quickly, but don't pick "admin" or "administration" (or your username or password). Pick something unusual.</p>

<p>The same applies to usernames and passwords. If you have an admin area, do not use "admin" as the username and "password" as the password. Pick something unusual, ideally with both letters and numbers (some hackers use something called a "dictionary attack", trying every word in a dictionary as a password until they find a word that works - adding a couple of digits to the end of a password renders this type of attack useless). It is also wise to change your password fairly regularly (every month or two).</p>

<p>Finally, make sure that your error messages give nothing away. If your admin area gives an error message saying "Unknown Username" when a bad username is entered and "Wrong Password" when the wrong password is entered, a malicious user will know when they've managed to guess a valid username. Using a generic "Login Error" error message for both of the above means that a malicious user will have no idea if it is the username or password he has entered that is wrong.</p>

<h3>Finally, Be Completely and Utterly Paranoid</h3>

<p>If you assume your site will never come under attack, or face any problems of any sort, then when something eventually does go wrong, you will be in massive amounts of trouble. If, on the other hand, you assume every single visitor to your site is out to get you and you are permanently at war, you will help yourself to keep your site secure, and be prepared in case things should go wrong.</p>

<p><em>Ready for more? Try <a href="http://www.addedbytes.com/security/writing-secure-php-2/">Writing Secure PHP, Part 2</a>.</em></p> <br><br>]]></description>
				<pubDate>Fri, 16 Jul 2004 09:07:15 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/writing-secure-php/writing-secure-php-1/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=code&amp;start=0" class="ditto_tag" rel="tag">code</a>,<a href="/feeds/tag-feed/?tags=coding&amp;start=0" class="ditto_tag" rel="tag">coding</a>,<a href="/feeds/tag-feed/?tags=development&amp;start=0" class="ditto_tag" rel="tag">development</a>,<a href="/feeds/tag-feed/?tags=mysql&amp;start=0" class="ditto_tag" rel="tag">mysql</a>,<a href="/feeds/tag-feed/?tags=php&amp;start=0" class="ditto_tag" rel="tag">php</a>,<a href="/feeds/tag-feed/?tags=programming&amp;start=0" class="ditto_tag" rel="tag">programming</a>,<a href="/feeds/tag-feed/?tags=security&amp;start=0" class="ditto_tag" rel="tag">security</a>,<a href="/feeds/tag-feed/?tags=tips&amp;start=0" class="ditto_tag" rel="tag">tips</a>,<a href="/feeds/tag-feed/?tags=tutorial&amp;start=0" class="ditto_tag" rel="tag">tutorial</a>,<a href="/feeds/tag-feed/?tags=web&amp;start=0" class="ditto_tag" rel="tag">web</a>,<a href="/feeds/tag-feed/?tags=webdesign&amp;start=0" class="ditto_tag" rel="tag">webdesign</a>,<a href="/feeds/tag-feed/?tags=webdev&amp;start=0" class="ditto_tag" rel="tag">webdev</a>
			</item>

			<item>
				<title>The Box Model For Beginners</title>
				<link>http://www.addedbytes.com/for-beginners/the-box-model-for-beginners/</link>
				<description><![CDATA[ An explanation of what the box model is and how it is treated by different user agents. <p>The term "box model" is often used by people when talking about CSS-based layouts and design. Not everyone understands what is meant by this though, and not everyone understands why it is so important.</p>

<p>Any HTML element can be considered a box, and so the box model applies to all HTML (and XHTML) elements.</p>

<p>The box model is the specification that defines how a box and its attributes relate to each other. In its simplest form, the box model tells browsers that a box defined as having width 100 pixels and height 50 pixels should be drawn 100 pixels wide and 50 pixels tall.</p>

<p>There is more you can add to a box, though, like padding, margins, borders, etc. This image should help explain what I'm about to run through:</p>

<p style="text-align:center;"><img src="content/box-model/box.png" alt="Outline of box model" /></p>

<p>As you can see, a box is made up of four distinct parts. The outside one, the margin, is completely invisible. It has no background color, and will not obstruct elements behind it. The margin is outside the second part, which is the border. The border outlines the visible portion of the element. Inside the border is the third part of the box, the padding, and then inside that the content area of the box. The padding defines the space between the content area of the box and the border.</p>

<p>(Note that in the image above, the only border of the three drawn that would actually be visible is the solid line - the dashed lines are added to help demonstrate the box model).</p>

<p>When you define a width and a height for your box using CSS, you are defining not the entire area taken up by the content, padding, border and margin. You are actually just defining the content area itself - the bit right in the middle. The padding, border and margin must be added to that in order to calculate the total space occupied by the box. (From this point on, we will use width for demonstrations, but the same principles apply to both width and height).</p>

<code>box {
    width: 200px;
    border: 10px solid #99c;
    padding: 20px;
    margin: 20px;
}</code>

<p>The above CSS, applied to a box, would mean that that box occupied 300 pixels of space horizontally on the page. The content of the box would occupy 200 pixels of that (dashed line added to demonstrate the edge of the area occupied by the box):</p>

<p style="text-align:center;"><img src="content/box-model/box_demo.png" alt="Box model demonstration." /></p>

<p>In the above image, you can see that the pale blue area is 240 pixels wide (200 pixels of content plus 20 pixels padding either side). The border is 10 pixels wide either side, making the total width including the border 260 pixels. The margin is 20 pixels either side, making the total width of the box 300 pixels.</p>

<p>In practice, this can cause some confusion. For example, if I have a 100 pixel wide space available, and want to fill it with a pale red box with a dark red border and a small amount of padding, it would be very easy to write the CSS like so:</p>

<code>box {
    width: 100px;
    border: 1px solid #900;
    padding: 10px;
    margin: 0;
    background: #fee;
}</code>

<p>(A declaration of 0, as used for the margin above, does not require a unit to be added. Any value other than 0 does require a unit, e.g. px for pixels. Also, although "background" is defined as a shorthand property, it is more widely supported than the more correct "background-color".)</p>

<p>However, that will not give us a 100 pixel wide box, as the width declaration defines the content area of the box. The content area of the box will be 100 pixels - the total width of the box as defined above will be 122 pixels:</p>

<p style="text-align:center;"><img src="content/box-model/box_demo2.png" alt="Box model demonstration." /></p>

<p>In order to set the above box to only occupy 100 pixels horizontally, you would need to set the width of the content area to be 100 pixels minus the padding and minus the border, in this case 78 pixels, like so:</p>

<code>box {
    width: <strong>78px</strong>;
    border: 1px solid #900;
    padding: 10px;
    margin: 0;
    background: #fee;
}</code>

<p>To calculate the overall width of a box, including all padding, borders and margins, you would use the following formula:</p>

<code>total box width = content area width + left padding + right padding + left border + right border + left margin + right margin</code>

<h3>Compatibility</h3>

<p>At this point, you should now have a good understanding of what the box model is, and how boxes <em>should</em> be treated by different browsers. However, as you will soon learn (if you did not know already), not every browser does as it is supposed to. In order to use boxes, and by extension make the most of CSS in your website, you will need to be aware of how the different browsers treat boxes in practice and how to overcome and work around the problems presented by these idiosyncrasies.</p>

<h3>Top Notch</h3>

<p><img src="images/browser_logos/opera6.gif" alt="Opera 6" /> <img src="images/browser_logos/opera7.gif" alt="Opera 7" /> <img src="images/browser_logos/mozilla.gif" alt="Mozilla" /> <img src="images/browser_logos/firefox.gif" alt="Firefox" /> <img src="images/browser_logos/camino.gif" alt="Camino" /> <img src="images/browser_logos/safari.gif" alt="Safari" /> <img src="images/browser_logos/konqueror.gif" alt="Konqueror" /> <img src="images/browser_logos/netscape6.gif" alt="Netscape 6" /> <img src="images/browser_logos/netscape7.gif" alt="Netscape 7" /> <img src="images/browser_logos/ie6.gif" alt="Internet Explorer 6" /></p>

<p>Most browsers released in the last few years have no problem with boxes and render boxes correctly. Opera 6 and 7, Mozilla 1 (and by extension other browsers based on the Gecko engine like Netscape 7, Camino and Firefox and other derivatives), Safari, Konquerer (and derivatives) and Internet Explorer 5 for the Mac are all shining examples of how a web browser <em>should</em> behave, all rendering boxes flawlessly. IE 6 for Windows also will render a box correctly, as long as the [url=http://www.addedbytes.com/design/dtds-explained]Document Type Definition[/url] for the page is correct.</p>

<h3>Whoops, Mrs Miggins, You're Sitting On My Artichokes</h3>

<p><img src="images/browser_logos/ie5.gif" alt="Internet Explorer 5" /> <img src="images/browser_logos/ie6.gif" alt="Internet Explorer 6" /></p>

<p>Some browsers don't display a box correctly. Unlike those below here, these browsers are widely enough used on the web that it is usually worth the effort to work through the problem. There are various methods for doing this, some better than others, that follow on. Most notable among the browsers with problems are Internet Explorers 4 and 5 and Internet Explorer 6. IE 6 is easy to work around, by adding a correct DTD (which you should be doing anyway).</p>

<p>Internet Explorer 5 is the main reason there is a box model problem at all. It, unfortunately, does not follow the simple definition for box layout as defined by the W3c. When you define a width for a box and it is rendered in IE5, instead of that width defining the content area of the box, it <em>includes the borders and padding</em>. Margins are added on to the content width correctly, but padding and borders are not. Unfortunately, this leaves us with some unpleasant choices:</p>

<ol><li><strong>Use a box model hack</strong><br />
Hack's like [url=http://www.tantek.com/CSS/Examples/boxmodelhack.html]Tantek's box model hack[/url] are unfortunately something of a necessity. While some might argue that using hacks like this is completely missing the point of using CSS for web design, commercial necessity and the prevalence of IE5 leave us with little in the way of choice. The IE5 box model hack is in use all over the web and has spawned plenty of variants.</li><li><strong>Add in extra code</strong><br />
Some might consider this a slightly "better" way of working around this problem. Rather than adding a style sheet hack, you can nest elements within each other. Adding a div within another div means that rather than using padding, you can use just margins, which are handled correctly by IE5. As with the box model hack, it is far from a perfect solution, but there are few other options if you want a site to look the same in IE5 as other more capable browsers.</li></ol>

<h3>Hall of Shame</h3>

<p><img src="images/browser_logos/ie4.gif" alt="Internet Explorer 4" /> <img src="images/browser_logos/netscape4.gif" alt="Netscape 4" /></p>

<p>On the one hand, the browsers that I am about to mention are appalling, all failing dismally to render a simple box correctly for one reason or another. On a more positive note, users of these browsers, mostly old versions of current browsers, make up an extremely small, and continually shrinking, portion of web users. While you could probably find a workaround for the bugs in the display of boxes in these browsers, it is almost certainly not worth the effort - you are likely to cause yourself more harm than good with workarounds for these!</p>

<p>Netscape 4's box model is awful, but even worse, the simple box model hacks to fix the problem for IE5 and IE6 will crash Netscape 4. Netscape 4's style sheet support is abysmal overall, and it is being supported less and less. Though it is strictly a personal choice, I don't think it is worth the time and effort to support Netscape 4 any more - it's just not used enough, and the number of users is only ever going to shrink.</p>

<p>Internet Explorer 4 suffers, basically, the same problem as IE5. It treats boxes in a very similar way. However, it falls over in far more ways, and many of the available hacks will crash IE4. As it is also used by few people, and that number is dropping, many designers ignore it.</p>

<h3>What does the future hold?</h3>

<p>CSS3 promises us the option to determine how we want the user agent to treat boxes, and specify which box model we want to use. Support for CSS3 at a level that will be possible is many many years away yet. Until then, we are stuck with the CSS2 box model, and while IE5 is still used by a significant percentage of the web's population, we are going to have problems with boxes.</p> <br><br>]]></description>
				<pubDate>Fri, 09 Jul 2004 10:48:54 +0000</pubDate>
				<guid isPermaLink="false">http://www.addedbytes.com/for-beginners/the-box-model-for-beginners/</guid>
				<dc:creator>Dave Child</dc:creator>
				<a href="/feeds/tag-feed/?tags=box&amp;start=0" class="ditto_tag" rel="tag">box</a>,<a href="/feeds/tag-feed/?tags=boxmodel&amp;start=0" class="ditto_tag" rel="tag">boxmodel</a>,<a href="/feeds/tag-feed/?tags=css&amp;start=0" class="ditto_tag" rel="tag">css</a>,<a href="/feeds/tag-feed/?tags=design&amp;start=0" class="ditto_tag" rel="tag">design</a>,<a href="/feeds/tag-feed/?tags=html&amp;start=0" class="ditto_tag" rel="tag">html</a>,<a href="/feeds/tag-feed/?tags=model&amp;start=0" class="ditto_tag" rel="tag">model</a>,<a href="/feeds/tag-feed/?tags=reference&amp;start=0" class="ditto_tag" rel="tag">reference</a>,<a href="/feeds/tag-feed/?tags=tips&amp;start=0" class="ditto_tag" rel="tag">tips</a>,<a href="/feeds/tag-feed/?tags=tutorial&amp;start=0" class="ditto_tag" rel="tag">tutorial</a>,<a href="/feeds/tag-feed/?tags=webdesign&amp;start=0" class="ditto_tag" rel="tag">webdesign</a>,<a href="/feeds/tag-feed/?tags=webdev&amp;start=0" class="ditto_tag" rel="tag">webdev</a>
			</item>
	</channel>
</rss>
