416 lines
10 KiB
PHP
416 lines
10 KiB
PHP
<?php
|
|
/* ----------
|
|
* ! NoCopyright, NoCopyleft for a free world !
|
|
* ! PasDeCopyright, PasDeCopyleft pour un monde libre !
|
|
* ----------
|
|
* Copyright (C) [2014] [Kara.Adrien] <adrien@iglou.eu>
|
|
* ----------
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
* ----------
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
* ----------
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
* ----------
|
|
* Beta 0.7.5 - 21 September 2016
|
|
* ----------
|
|
* LittleSecureLib, est une petite librairie php de securisation general.
|
|
* Elle traite les failles d'includes, XSS, InjectSQL, VolDeSession et CSRF.
|
|
* Un support de HASH et chiffrement est aussi présent.
|
|
---------- */
|
|
|
|
/* ---------- Configuration ---------- */
|
|
|
|
// Debug mode
|
|
$debug = true; // true | false
|
|
// IE Edge, désactiver le mode de "compatibilité" pour Internet Explorer
|
|
$ieEdge = true;
|
|
|
|
// key pour ID Unique du lien de session
|
|
define('SESSION_SINGLE_KEY', 'M@ cléf un!qu€ Et pr|vè');
|
|
|
|
// key de chiffrement
|
|
define('ENCRYPTION_KEY', 'ma clée aléatoire ...');
|
|
|
|
// Hash à utiliser
|
|
define('BADHASH', 'sha1'); // Simple
|
|
define('CRYPTHASH', 'haval256,3'); // Pour le chiffrement | strlen = 64 !
|
|
define('BIGHASH', 'whirlpool'); // Complexe
|
|
|
|
// Le grain de sel du HASH
|
|
define('SEED_A', 'faa');
|
|
define('SEED_B', 'foo');
|
|
|
|
//Exemple de sel en sha1, conseil d'utiliser une info user inaliénable non privé !
|
|
define('SALT', '78312c77fadb9f35dd5fd7b343a3925ac4cfdaf0');
|
|
|
|
/* ---------- Dépendances/Debug ---------- */
|
|
|
|
if ($debug) {
|
|
error_reporting(-1);
|
|
ini_set('display_errors', 'On');
|
|
|
|
if (!extension_loaded('openssl')) {
|
|
exit('DIE : The openssl lib is not loaded.');
|
|
}
|
|
if (!extension_loaded('mcrypt')) {
|
|
exit('DIE : The mcrypt +2.4.x lib is not loaded.');
|
|
}
|
|
if (!extension_loaded('iconv')) {
|
|
exit('DIE : The iconv lib is not loaded.');
|
|
}
|
|
|
|
if (!in_array(BADHASH, hash_algos())) {
|
|
exit('DIE : '.BADHASH.' is not available, check your libs.');
|
|
}
|
|
if (!in_array(CRYPTHASH, hash_algos())) {
|
|
exit('DIE : '.CRYPTHASH.' is not available, check your libs.');
|
|
}
|
|
if (!in_array(BIGHASH, hash_algos())) {
|
|
exit('DIE : '.BIGHASH.' is not available, check your libs.');
|
|
}
|
|
}
|
|
|
|
if ($ieEdge) {
|
|
header('x-ua-compatible: IE=Edge,chrome=1');
|
|
}
|
|
|
|
/* ---------- Filtres ---------- */
|
|
|
|
// Parseur de sécurisation
|
|
function securityParser($arg, $type = null)
|
|
{
|
|
if ((array) $arg === $arg) {
|
|
foreach ($arg as $key => $value) {
|
|
$value = charCleaner($value, $type);
|
|
$arg[$key] = utf8Encode($value);
|
|
}
|
|
} else {
|
|
$arg = charCleaner($arg, $type);
|
|
$arg = utf8Encode($arg);
|
|
}
|
|
|
|
return ($arg);
|
|
}
|
|
|
|
/* -------- Encodage -------- */
|
|
|
|
// Verification de l'UTF8
|
|
function utf8Encode($arg)
|
|
{
|
|
$inCharset = mb_detect_encoding($arg, 'auto');
|
|
|
|
if ($inCharset !== 'UTF-8') {
|
|
$arg = iconv($inCharset, 'UTF-8//TRANSLIT', $arg);
|
|
}
|
|
|
|
return ($arg);
|
|
}
|
|
|
|
/* -------- Clean -------- */
|
|
|
|
// Filtres de nettoyage - Utilisez $type True, pour un encodage plus soft
|
|
function charCleaner($arg, $type = null)
|
|
{
|
|
$arg = trim($arg);
|
|
|
|
if ($type) {
|
|
$arg = htmlspecialchars($arg, ENT_QUOTES, 'UTF-8', true);
|
|
} else {
|
|
$arg = filter_var($arg, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
|
}
|
|
|
|
return ($arg);
|
|
}
|
|
|
|
// Netoyage db - Pour Oracle utilisez les 'Procédures stockée' !
|
|
function dbCleaner($arg, $type = null)
|
|
{
|
|
$arg = trim($arg);
|
|
|
|
switch ($type) {
|
|
case 'mysql':
|
|
$arg = htmlspecialchars($arg, ENT_QUOTES);
|
|
break;
|
|
case 'sqlite':
|
|
$arg = SQLite3::escapeString($arg);
|
|
break;
|
|
case 'pg':
|
|
$arg = pg_escape_string($arg);
|
|
break;
|
|
case 'xml':
|
|
$arg = strtr($arg, array('\\' => '\\\\', "'" => "\'", '"' => '\"', "{" => '\{', "}" => '\}', "<" => '\<', ">" => '\>'));
|
|
break;
|
|
case 'json':
|
|
$arg = strtr($arg, array('\\' => '\\\\', '"' => '\"'));
|
|
break;
|
|
default :
|
|
exit('DIE : LittleSecureLib --> dbCleaner | Bad type.');
|
|
break;
|
|
}
|
|
|
|
return ($arg);
|
|
}
|
|
|
|
// Filtre pour shell
|
|
function shellCleaner($arg, $char = false)
|
|
{
|
|
if ($char) {
|
|
$arg = escapeshellcmd($arg);
|
|
} else {
|
|
$arg = escapeshellarg($arg);
|
|
}
|
|
|
|
return ($arg);
|
|
}
|
|
|
|
/* -------- Global -------- */
|
|
|
|
// Filtre pour fichier
|
|
function fileExist($arg, $path)
|
|
{
|
|
$arg = securityParser($arg);
|
|
|
|
if ('/' !== strstr($path, '/')) {
|
|
$path = $path.'/';
|
|
}
|
|
|
|
if (strstr($arg, "..")) {
|
|
$arg = false;
|
|
} else {
|
|
if (is_link($path.$arg) or !file_exists($path.$arg)) {
|
|
$arg = false;
|
|
}
|
|
}
|
|
|
|
return ($arg);
|
|
}
|
|
|
|
// Verif email/télèphone/url/ipv4/ipv6
|
|
function multiCheck($arg, $type = null)
|
|
{
|
|
switch ($type) {
|
|
case 'email':
|
|
$arg = filter_var($arg, FILTER_SANITIZE_EMAIL);
|
|
if (!filter_var($arg, FILTER_VALIDATE_EMAIL)) {
|
|
$arg = false;
|
|
}
|
|
break;
|
|
case 'phone':
|
|
$arg = filter_var($arg, FILTER_SANITIZE_NUMBER_INT);
|
|
if (!preg_match("#^\+?[0-9\./, -]{6,20}$#", $arg)) {
|
|
$arg = false;
|
|
}
|
|
break;
|
|
case 'url':
|
|
$arg = filter_var($arg, FILTER_SANITIZE_URL);
|
|
if (!filter_var($arg, FILTER_VALIDATE_URL)) {
|
|
$arg = false;
|
|
}
|
|
break;
|
|
case 'ip':
|
|
if (!filter_var($arg, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE)) {
|
|
$arg = false;
|
|
}
|
|
break;
|
|
default :
|
|
exit('DIE : LittleSecureLib --> multiCheck | Bad type.');
|
|
break;
|
|
}
|
|
|
|
return ($arg);
|
|
}
|
|
|
|
/* ---------- Sessions ---------- */
|
|
|
|
/* *
|
|
* Start safe session
|
|
*
|
|
* Check session is not started
|
|
* Https cookie
|
|
* regen id and fingerprint
|
|
*
|
|
* @return void
|
|
* */
|
|
function sessionStart($secure = null, $onlyHttp = true, $target = '/')
|
|
{
|
|
if (session_is_start())
|
|
return;
|
|
|
|
session_set_cookie_params(0, $target, null, $secure, $onlyHttp);
|
|
|
|
session_start();
|
|
sessionRegenId();
|
|
sessionFingerprint();
|
|
}
|
|
|
|
/* *
|
|
* Check if session is started
|
|
*
|
|
* @return boolean
|
|
* */
|
|
function sessionIsStart()
|
|
{
|
|
if (PHP_SESSION_ACTIVE === session_status())
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/* *
|
|
* Regenerate ID
|
|
*
|
|
* @return void
|
|
* */
|
|
function sessionRegenId()
|
|
{
|
|
if (!isset($_SESSION['idTime']) || empty($_SESSION['idTime']))
|
|
$_SESSION['idTime'] = time();
|
|
|
|
if (time() >= $_SESSION['idTime'] + 600) {
|
|
//New ID all 10mn
|
|
session_regenerate_id(true);
|
|
$_SESSION['idTime'] = time();
|
|
}
|
|
}
|
|
|
|
/* *
|
|
* Destroy session
|
|
*
|
|
* Check if session exist befor erase
|
|
*
|
|
* @return void
|
|
* */
|
|
function sessionDestroy()
|
|
{
|
|
sessionStart();
|
|
|
|
$_SESSION = array();
|
|
|
|
session_destroy();
|
|
session_write_close();
|
|
|
|
if (isset($_COOKIE['PHPSESSID'])) {
|
|
unset($_COOKIE['PHPSESSID']);
|
|
|
|
$params = session_get_cookie_params();
|
|
setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
|
|
}
|
|
}
|
|
|
|
/* *
|
|
* Make a fingerprint
|
|
*
|
|
* "Avoid" session hijacking
|
|
*
|
|
* @return void
|
|
* */
|
|
function sessionFingerprint()
|
|
{
|
|
$userInfo = SESSION_SINGLE_KEY;
|
|
|
|
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']))
|
|
$userInfo .= $_SERVER['HTTP_ACCEPT_ENCODING'];
|
|
|
|
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
|
|
$userInfo .= ','.$_SERVER['HTTP_ACCEPT_LANGUAGE'];
|
|
|
|
if (isset($_SERVER['HTTP_USER_AGENT']))
|
|
$userInfo .= ','.$_SERVER['HTTP_USER_AGENT'];
|
|
|
|
if (isset($_SERVER['REMOTE_ADDR']))
|
|
$userInfo .= ','.$_SERVER['REMOTE_ADDR'];
|
|
|
|
$userInfo = filter_var($userInfo, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
|
|
|
if (isset($_SESSION['userInfo'])) {
|
|
if ($_SESSION['userInfo'] !== $userInfo) {
|
|
error_log('|- FINGERPRINT ERROR -> || VALID: '.$_SESSION['userInfo'].' || REJECTED: '.$userInfo);
|
|
sessionDestroy();
|
|
return false;
|
|
}
|
|
} else {
|
|
$_SESSION['userInfo'] = $userInfo;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* ---------- CSRF ---------- */
|
|
|
|
// Token
|
|
function token($arg = null)
|
|
{
|
|
if ($arg) {
|
|
|
|
if ((isset($_SESSION['token'])) && ($_SESSION['token'] === $arg)) {
|
|
$arg = true;
|
|
} else {
|
|
$arg = false;
|
|
}
|
|
|
|
$_SESSION['token'] = '';
|
|
} else {
|
|
$arg = bin2hex(openssl_random_pseudo_bytes(32));
|
|
$_SESSION['token'] = $arg;
|
|
}
|
|
|
|
return ($arg);
|
|
}
|
|
|
|
// Variable aléatoire
|
|
function randVar($arg)
|
|
{
|
|
$rand = bin2hex(openssl_random_pseudo_bytes(8));
|
|
$_SESSION[$arg] = $rand;
|
|
|
|
return ($rand);
|
|
}
|
|
|
|
/* ---------- chiffrement et hash ---------- */
|
|
|
|
function leBoucher($arg, $type = null)
|
|
{
|
|
if ('BADHASH' === $type) {
|
|
$arg = hash(BADHASH, $arg, false);
|
|
} elseif ('CRYPTHASH' === $type) {
|
|
$arg = hash(CRYPTHASH, $arg, true);
|
|
} else {
|
|
//BIGHASH est utilisé par défault
|
|
$lenMax = strlen(SALT);
|
|
$lenMid = $lenMax / 2;
|
|
|
|
$arg = SEED_A.$arg.SEED_B;
|
|
$arg = hash(BIGHASH, $arg, false);
|
|
$arg = substr(SALT, 0, $lenMid).$arg.substr(SALT, $lenMid, $lenMax);
|
|
}
|
|
|
|
return ($arg);
|
|
}
|
|
|
|
function encrypt($arg, $action)
|
|
{
|
|
$key = leBoucher(ENCRYPTION_KEY, 'CRYPTHASH');
|
|
$ivSi = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB);
|
|
|
|
if ('cry' === $action) {
|
|
$iv = mcrypt_create_iv($ivSi, MCRYPT_RAND);
|
|
$arg = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $arg, MCRYPT_MODE_CFB, $iv);
|
|
$arg = $iv.$arg;
|
|
$arg = base64_encode($arg);
|
|
} elseif ('dec' === $action) {
|
|
$arg = base64_decode($arg);
|
|
$ivDe = substr($arg, 0, $ivSi);
|
|
$arg = substr($arg, $ivSi);
|
|
$arg = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $arg, MCRYPT_MODE_CFB, $ivDe);
|
|
} else {
|
|
exit('DIE : LittleSecureLib --> encrypt | Mauvaise action.');
|
|
}
|
|
|
|
return ($arg);
|
|
} |