In 1987, the SkillsBank software occupied about 45 floppy disks, and our customers could either buy a single user license (you can’t copy the disks) or a site license (make as many copies as you need). At first we managed the license on trust, but when we learned that one of our dealers was making his own copies and selling them, I decided it was time to add some copy protection.Most copy protection has two components. The original disks need some kind of marker that can’t be duplicated, and the software that reads the disk needs to check that the marker is there. If someone wants to break the protection, they either need to duplicate the marker or bypass the checking software.
I felt pretty certain that the software wasn’t going to be hacked. We used the Aztec C compiler for the Apple II that would either output native 6502 code or a custom pseudo-code (like Java’s bytecode). We used the pseudo-code because it was smaller (size was almost everything then), but it also made it very hard to read. The code was in overlays to boot.
Creating a good marker was the problem. CopyIIPlus was the program of the day for making copies of disks. Although it was marketed simply to let you make backups, people routinely used it to steal software, and it had a million tricks up its sleeve. One of the issues was that the Apple II firmware would let you read literally every bit on a track. In theory, all CopyIIPlus had to do was rewrite the bits it had read.
There were a lot of bits. The disks contained 35 tracks x 16 sectors per track x 256 bytes per sector x 8 bits per byte, or about 1.1 megabits (140k bytes). On a given track, in addition to the 32,768 bits that made up the data, there was identifying information for each sector plus some extra bits for filler.
Any disk had to contain the 35 x 16 x 256, but the filler was variable. We used a $12,000 disk duplicator to manufacture our disks, and I found that every track the duplicator laid down was very consistent, plus or minus a small number of bits. An Apple II drive, by contrast, wrote down tracks with wildly varying amounts of filler. It could read everything, but it couldn’t write it, even when CopyIIPlus told it to. So I didn’t put any markers on the disks at all. I just counted the bits. Close enough to our number? Then it had been copied by us. (Or another high-end duplicator. I wasn’t going to fret about that.)
Twenty years later, stealing is more complicated. What’s worse, the bad guys don’t necessarily even want to take your software; they just want to mess with you.
I’m in the process of writing time tracking software (where does my day go?), and it involves a login and a MySQL database. Both of these aspects, I am slowly learning, offer numerous cracks for the bad guys to squeeze though. Instead of counting bits, here is what I am doing in 2007.
I encrypt your login password in my database, using the PHP crypt function. This means, for starters, that not even I can read your password; If you forget it, I can’t send it back to you. Sites that mail you back your password must be storing it in plain text. If you’re serious about encryption, you should follow the small details: us2.php.net/crypt.
I tuck away most of the PHP code outside of the public_html directory. About six month’s ago, I discovered that someone had hacked into the visitor counter on my son’s website. (The guy bragged about it on the web. What is wrong with these people?) Stupid me, I had called it counter.txt and left it in the primary directory. I still don’t know how he did it, but after that, I move what I can out of html space.
I need to protect against SQL injection. You can get the whole story in this Wikipedia article, but here’s an example. When someone tries to login, I get their ID in the variable $userID and use the following query to find their record in the database:
SELECT password FROM Users WHERE userID = '$userID';
Unfortunately, it’s possible to type anything into the user ID field, including
a’; DELETE FROM Users WHERE 1 OR userID = '
Bye, bye users! To protect against this, I use the PHP function mysql_real_escape_string prior to invoking the query, which effectively nullifies any SQL syntax:
$userID = mysql_real_escape_string($_POST['userID']);
[ add comment ] ( 16 views ) | permalink

Calendar



