Ik ben al een tijdje bezig met een API System te maken voor mijn website. In de database komen namelijk persoonlijke gegevens te staan die extern op te vragen zijn. Dus wil ik er zeker van zijn dat dit systeem veilig en waterdicht is.

Zo ziet de code van het systeem er ongeveer uit:

API Client:

<?php
// API Content
if (isset($_POST['username']) && isset($_POST['password'])) {
	// Encrypted Post Fields
	$username = base64_encode($_POST['username']);
	$password = base64_encode(sha1($_POST['password']));
	$ip_adress = base64_encode($_SERVER['REMOTE_ADDR']);
	
	// PHP Curl
	$ch = curl_init($api_server);
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS, 'api_key=' . $api_key . '&website=' . $_SERVER['HTTP_HOST'] . '&username=' . $username . '&password=' . $password . '&ip_adress=' . $ip_adress);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	$re = curl_exec($ch);
	curl_close($ch);
	
	// Handle Data
	$api_content = explode('|', $re);
	if (empty($api_content[10])) {
		echo $re;
	} else {
		$data1 =   $api_content[0];
// enz enz

	}
} else {
// Hier het formulier om in te loggen  
}
?>


API Server:
De code hiervan komt niet online te staan, hieronder staat informatie die mij belangrijk lijkt om in te schatten of mijn systeem veilig is:

- Iedere query die door de database word uitgevoerd is beveiligd met de volgende functie:

<?php
// Mysql Injection
function clean_input($query) {
	$query = stripslashes($query);
	$query = strip_tags($query);
	$query = trim($query);
	return mysql_real_escape_string($query);
}
?>

- Het wachtwoord ziet er ongeveer zo uit:

<?php
$password = md5(($salt . $_POST['password']) . $salt);
?>

- De API code word gecontroleerd met de database, net zoals die website die gebruikt maakt van de API Client
- De data word uit de database 'ge-echo-ed' (onbeveiligd)
- De server maakt een logbestand met: ip adres gebruiker, ip adres website, api key, query, tijd, datum

Alvast bedankt!
Waarom zou je geen sha1 gebruiken dan? Ja op zich is het wel veilig hoor. Ik zeg alleen dat het terug te berekenen is, maar wees gerust niet iedereen kan dat. Je zou ook van de voor en de achterkant een salt kunnen gebruiken dus zo:

<?php
sha1($salt1 . $wachtwoord . $salt2);
?>

Maar dwing gebruikers ook af om 'sterke' wachtwoord te gebruiken.
"Waarom zou je geen sha1 gebruiken dan?"
In plaats van md5 bedoel je? Geen idee... SHA is iets anders weer dan sha1??

In mijn voorbeeld md5(sdfsjfhsh_wachtwoord_343334) is "wachtwoord" het wachtwoord en wat er voor en achter staat de salt & peppa :) Dat is hetzelfde wat jij bedoelt denk ik?

En doe je die salts altijd hetzelfde? Of maak je dat variabel op een of andere manier?
Kijk, hier is een methode die wordt gebruikt door phpbb3.

't Is te zeggen: hiermee kan je paswoorden controleren zoals ze in een phpBB3 forum gecodeerd zijn.
Ik heb dit zelf niet geschreven, er staat een referentie bij.

Zoals je ziet: verschillende waarden die in de database kunnen staan geven je toch een true (of false als je $val_post aanpast)

Wat phpBB doet, is telkens bij het inloggen een andere waarde ( phpbb_hash($_POST['paswoord']) ) in de db opslaan.

<?php
$val_database =phpbb_hash('admin123');
// stel: $val_database is nu de waarde zoals ze in de db staat.
$val_post = "admin123";
// zoals je ze uit $_POST haalt

if(phpbb_check_hash(
$val_post,
$val_database
)
) {
echo "Value is true";
}
else {
echo "val is false";
}

echo '<p>wachtwoord in database: '. $val_database .'</p>';

////////////////////////////////////////////////////////////////////////
/**
* slightly adapted from @see http://lifekamazza.blogspot.com/2007/10/hack-password-encryption-in-phpbb3.html
*/
function phpbb_hash($password) {
$itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$random_state = unique_id();
$random = '';
$count = 6;
if (($fh = @fopen('/dev/urandom', 'rb'))) {
$random = fread($fh, $count);
fclose($fh);
}
if (strlen($random) < $count) {
$random = '';
for ($i = 0; $i < $count; $i += 16) {
$random_state = md5(unique_id() . $random_state);
$random .= pack('H*', md5($random_state));
}
$random = substr($random, 0, $count);
}
$hash = _hash_crypt_private($password, _hash_gensalt_private($random, $itoa64), $itoa64);
if (strlen($hash) == 34) {
return $hash;
}

return md5($password);
}

function unique_id($extra = 'c') {
static $dss_seeded = false;
global $config;

$val = $config['rand_seed'] . microtime();
$val = md5($val);
$config['rand_seed'] = md5($config['rand_seed'] . $val . $extra);
if ($dss_seeded !== true && ($config['rand_seed_last_update'] < time() - rand(1,10))) {
$config['rand_seed_last_update']=time();
$dss_seeded = true;
}

return substr($val, 4, 16);
}

function _hash_crypt_private($password, $setting, &$itoa64) {
$output = '*';
// Check for correct hash
if (substr($setting, 0, 3) != '$H$') {
return $output;
}
$count_log2 = strpos($itoa64, $setting[3]);
if ($count_log2 < 7 || $count_log2 > 30) {
return $output;
}
$count = 1 << $count_log2;
$salt = substr($setting, 4, 8);
if (strlen($salt) != 8) {
return $output;
}

/**
* We're kind of forced to use MD5 here since it's the only
* cryptographic primitive available in all versions of PHP
* currently in use. To implement our own low-level crypto
* in PHP would result in much worse performance and
* consequently in lower iteration counts and hashes that are
* quicker to crack (by non-PHP code).
*/

$hash = pack('H*', md5($salt . $password));
do {
$hash = pack('H*', md5($hash . $password));
} while (--$count);
$output = substr($setting, 0, 12);
$output .= _hash_encode64($hash, 16, $itoa64);

return $output;
}

function _hash_gensalt_private($input, &$itoa64, $iteration_count_log2 = 6) {
if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) {
$iteration_count_log2 = 8;
}

$output = '$H$';
$output .= $itoa64[min($iteration_count_log2 + ((PHP_VERSION >= 5) ? 5 : 3), 30)];
$output .= _hash_encode64($input, 6, $itoa64);

return $output;
}

/**
* Encode hash
*/
function _hash_encode64($input, $count, &$itoa64) {
$output = '';
$i = 0;
do {
$value = ord($input[$i++]);
$output .= $itoa64[$value & 0x3f];

if ($i < $count) {
$value |= ord($input[$i]) << 8;
}
$output .= $itoa64[($value >> 6) & 0x3f];
if ($i++ >= $count) {
break;
}

if ($i < $count) {
$value |= ord($input[$i]) << 16;
}
$output .= $itoa64[($value >> 12) & 0x3f];
if ($i++ >= $count) {
break;
}
$output .= $itoa64[($value >> 18) & 0x3f];
} while ($i < $count);
return $output;
}

function phpbb_check_hash($password, $hash) {
$itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
if (strlen($hash) == 34) {
return (_hash_crypt_private($password, $hash, $itoa64) === $hash) ? true : false;
}

return (md5($password) === $hash) ? true : false;
}
?>
Ik snap niet hoe het werkt hoor... en wat je nou precies bedoelt. Kun je een voorbeeldje geven in woorden van wat er gebeurt?
Probeer zelf eens.
Zie dat je een gecodeerd paswoord kan kopiëren uit een db, voor een phpBB3 forum.
(Desnoods zwier je ergens een phpbb3 forum ergens online, ... zie in de users tabel ...)

test dan dit uit

<?php
echo phpbb_check_hash(
$ongecodeerd_paswoord,
$waarde_zoals_ze_in_de_db_staat
);
?>
(zie dat je de functies ook ergens zet, uiteraard)
Mja, de vraag was dus of je kunt uitleggen in woorden wat er gebeurt... want ik snap gewoon niet wat jij zegt / bedoelt. Kan goed aan mij liggen hoor :-)

Misschien is er iemand anders die snapt wat Kris wil zeggen, maar die het op een adere manier kan verwoorden...
Ok, dus tot nu toe is het script redelijk veilig.
Als ik het goed begrijp moet dit dus nog gebeuren:
- SSL Verbinding (word al geregeld)
- Een betere manier van wachtwoorden opslaan (md5(sha1($_POST['password']) . $salt);) ??)
- Een alternatief voor $_SERVER['REMOTE_ADDR']

De data word nu zonder encryptie weergeven en opgehaald via de client, is dit veilig, of moet ik hier nog een encryptie op zetten. Zo ja, welke?
doe maar gewoon sha(post.salt).
Oke bedankt!
Maar hebben jullie ook nog ideeën voor de andere 'problemen'?

En is mijn clean_iput functie goed (genoeg).
Bevat hij onnodige dingen, of mist hij iets enz.

Alvast bedankt!
Heeft iemand nog een antwoord op de bovenstaande vragen?

Reageren