Question

I was thinking of implementing a MySQL database with valid serial codes which would be checked against user input and grant usage of the app if the check returns true, but I know this is way too basic since the user (who will be using a localhost based application) could easily crack the database and add his own serials (or at least tell someone else who has got a basic understanding of PHP & SQL if they think apps come out of the "magic box").

Since I have not done this before, is there any popular approach? Or better yet it'd be nice if you just gave me some ideas.

Was it helpful?

Solution

There is never going be any 100% uncrackable approach. Anything can be reverse engineered, if you have the time and know-how.

But what you can do to maximise your chances of not being cracked is use some kind of pre-compiler/obfuscator like Zend Guard or ionCube (and others) to protect your code. Most (all?) of these come with pre-built licensing functionality, which is definitely the recommended approach.

The problem with these is that they are not free...

EDIT

Thinking about it, you could implement something like this yourself, safely, in a very select set of circumstances. If you are developing something that you could distribute HipHop binaries of, you could implement something without fear that it could be cracked by people who don't fairly seriously know what they are doing. HipHop is freely available to download from github.

The remote database check is still a bad idea though, because people can sniff the network traffic and reverse engineer the keys, or learn how to spoof the response (a simple hosts file edit could intercept the network traffic). You would be better hard-coding the key for each instance and validating it on each invoke with some algorithm - this site and Google may help you here.

OTHER TIPS

AFAIK If they have the PHP source code in plain-text, they can circumvent any protections you put in place.

That said, there are services out there such as ionCube (google it) which obfuscate (compile?) the code, and require a key (from some remote server) to unlock the code for execution.

Or you can host the software for the customers so that they don't have direct access to the application.

You could implement a "call home", that sends the serial that the user has entered on their site. You then check that serial in your database, and send an appropriate reply whether the user has or hasn't got access to his system. You could do so when the user logs in on their site.

The problem with this is that since it's quite easy to change php files when not encrypted / encoded with a tool like Zend Guard, the user could circumvent this by changing the call to not be made, and always return true. Or they could alter their webserver's hosts-file, to reroute the request to a server they own, and place a file there that fakes your check and also always returns true.

To prevent this, you'll have to both encrypt your php files and implement a challenge-response system to check their serial.

If I understand what you mean. :-P

So you have a MySAL database on your host and the customer app connects to it, right?

At first i would add a layer betwen database and customer. A http remote interface like SOAP or something using json.

You should encrypt the connection to it (https) or at least use some challenge response approach.

But when your application is open source ther will be allways a way to bypass it. And ven if it's not ;-).

Take a look here http://dev.michaelnorris.co.uk/tests/random_string.php

<?php 
function makePin($lenth=10) { 
// makes a random alpha numeric string of a given lenth 
$aZ09 = array_merge(range('A', 'Z'), range('a', 'z'),range(0, 9));
//$aZ09 = array_merge(range('A', 'Z'), range(0, 9)); 
$out =''; 
for($c=0;$c < $lenth;$c++) { 
   $out .= $aZ09[mt_rand(0,count($aZ09)-1)]; 
} 
return $out; 
}
$obscure = makePin();
echo $obscure;
?>

This is actually better for you I think. Take a look here http://dev.michaelnorris.co.uk/tests/random_password.php

I cannot take credit for this example as I mashed it together from other sources online which I cannot remember but here it is anyway.

<?php

// just so we know it is broken
error_reporting(E_ALL);

//string passType can be alpha, numeric, or alphanumeric defaults to alphanumeric int $length is the length of the password, defaults to eight

class randomPassword{

    function __construct($passType='alphanumeric', $length=8, $rangeLength=9){
        $this->setLength($length);
        $this->setRangeLength($rangeLength);
        $this->passType = $this->setPassType($passType);
    }

    function setRangeLength($rangeLength){
        $this->rangeLength=$rangeLength;
    }

    // set the length of the password
    private function setLength($length){
        $this->length=$length;
    }


    // set the type of password
    private function setPassType($passType){
        return $passType.'Chars';
    }

    // return an array of numbers
    private function numericChars(){
        return range(0, $this->rangeLength);
    }

    // return an array of chars
    private function alphaChars(){
        return range('a', 'z');
    }

    // return an array of alphanumeric chars
    private function alphaNumericChars(){
        return array_merge($this->numericChars(), $this->alphaChars());
    }

    // return a string of chars
    private function makeString(){
        // here we set the function to call based on the password type
        $funcName = $this->passType;
        return implode($this->$funcName());
    }

    // shuffle the chars and return $length of chars
    public function makePassword(){
        return substr(str_shuffle($this->makeString()), 1, $this->length);
    }

} // end class

function randomPassword($length) {
    // create an array of chars to use as password
    $chars = implode(array_merge(range(0,9), range('a', 'z')));

    // randomly snarf $length number of array keys
    return substr(str_shuffle($chars), 1, $length);

}

/*
try
{
$obj = new randomPassword('alphanumeric', 16, 100);
echo $obj->makePassword().'<br />';
}
catch(Exception $ex)
{
echo $ex->getMessage();
}
*/
echo strtoupper(randomPassword(5)).'-'.strtoupper(randomPassword(5)).'-'.strtoupper(randomPassword(5)).'-'.strtoupper(randomPassword(5)).'-'.strtoupper(randomPassword(5)).'-'.strtoupper(randomPassword(5));
?>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top