jeton csrf ;D
This commit is contained in:
parent
3bd2bcd01a
commit
9f34926e7f
5 changed files with 385 additions and 10 deletions
22
api.php
22
api.php
|
@ -14,6 +14,9 @@
|
|||
include("session_verif.php");
|
||||
include("bdd.php");
|
||||
|
||||
include('php-csrf.php');
|
||||
$csrf = new CSRF();
|
||||
|
||||
|
||||
// Get the requested URL
|
||||
$request_uri = $_SERVER['REQUEST_URI'];
|
||||
|
@ -177,8 +180,16 @@
|
|||
|
||||
if($_SERVER['REQUEST_METHOD'] === 'POST'){
|
||||
verifier_session();
|
||||
|
||||
switch(array_pop($url_parts)){
|
||||
case "aj_doc":
|
||||
|
||||
|
||||
if(!$csrf->validate($context='televersement',$_POST["jeton-csrf"])){
|
||||
echo( json_encode(["status"=> "2","msg"=>"jeton csrf manquant.".$_POST["jeton-csrf"]]) );
|
||||
break;
|
||||
}
|
||||
|
||||
try{
|
||||
ajouter_doc($_POST);
|
||||
|
||||
|
@ -188,6 +199,11 @@
|
|||
break;
|
||||
|
||||
case "valider_ensemble":
|
||||
|
||||
if(!$csrf->validate($context='valider_ensemble',$_POST["jeton-csrf"])){
|
||||
echo( json_encode(["status"=> "2","msg"=>"jeton csrf manquant.".$_POST["jeton-csrf"]]) );
|
||||
break;
|
||||
}
|
||||
try{
|
||||
valider_ensemble($_POST["ensemble_id"]);
|
||||
echo(json_encode(["status"=>"1","msg"=>"Ensemble validé."]));
|
||||
|
@ -197,6 +213,12 @@
|
|||
break;
|
||||
|
||||
case "supprimer_ensemble":
|
||||
|
||||
if(!$csrf->validate($context='supprimer_ensemble',$_POST["jeton-csrf"])){
|
||||
echo( json_encode(["status"=> "2","msg"=>"jeton csrf manquant." ]) );
|
||||
break;
|
||||
}
|
||||
|
||||
try{
|
||||
supprimer_ensemble($_POST["ensemble_id"]);
|
||||
echo(json_encode(["status"=>"1","msg"=>"Ensemble supprimé."]));
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
</head>
|
||||
<body>
|
||||
<?php
|
||||
|
||||
session_start();
|
||||
|
||||
?>
|
||||
|
|
340
php-csrf.php
Normal file
340
php-csrf.php
Normal file
|
@ -0,0 +1,340 @@
|
|||
<?php
|
||||
/**
|
||||
* php-csrf v1.0.4
|
||||
*
|
||||
* Single PHP library file for protection over Cross-Site Request Forgery
|
||||
* Easily generate and manage CSRF tokens in groups.
|
||||
*
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Grammatopoulos Athanasios-Vasileios
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* // Load or Start a new list of tokens
|
||||
* $csrf_tokens = new CSRF(
|
||||
* <modifier for the session variable and the form input name>,
|
||||
* <default time before the token expire, in seconds>
|
||||
* );
|
||||
* // Generate an input for a form with a token
|
||||
* // Tokens on the list are binded on a group so that
|
||||
* // they can only be matched on that group
|
||||
* // You can use as a group name the form name
|
||||
* echo $csrf_tokens->input(<name of the group>);
|
||||
*/
|
||||
class CSRF {
|
||||
|
||||
private $name;
|
||||
private $hashes;
|
||||
private $hashTime2Live;
|
||||
private $hashSize;
|
||||
private $inputName;
|
||||
|
||||
/**
|
||||
* Initialize a CSRF instance
|
||||
* @param string $session_name Session name
|
||||
* @param string $input_name Form name
|
||||
* @param integer $hashTime2Live Default seconds hash before expiration
|
||||
* @param integer $hashSize Default hash size in chars
|
||||
*/
|
||||
function __construct ($session_name='csrf-lib', $input_name='key-awesome', $hashTime2Live=0, $hashSize=64) {
|
||||
// Session mods
|
||||
$this->name = $session_name;
|
||||
// Form input name
|
||||
$this->inputName = $input_name;
|
||||
// Default time before expire for hashes
|
||||
$this->hashTime2Live = $hashTime2Live;
|
||||
// Default hash size
|
||||
$this->hashSize = $hashSize;
|
||||
// Load hash list
|
||||
$this->_load();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a CSRF_Hash
|
||||
* @param string $context Name of the form
|
||||
* @param integer $time2Live Seconds before expiration
|
||||
* @param integer $max_hashes Clear old context hashes if more than this number
|
||||
* @return CSRF_Hash
|
||||
*/
|
||||
private function generateHash ($context='', $time2Live=-1, $max_hashes=5) {
|
||||
// If no time2live (or invalid) use default
|
||||
if ($time2Live < 0) $time2Live = $this->hashTime2Live;
|
||||
// Generate new hash
|
||||
$hash = new CSRF_Hash($context, $time2Live, $this->hashSize);
|
||||
// Save it
|
||||
array_push($this->hashes, $hash);
|
||||
if ($this->clearHashes($context, $max_hashes) === 0) {
|
||||
$this->_save();
|
||||
}
|
||||
|
||||
// Return hash info
|
||||
return $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hashes of a context
|
||||
* @param string $context the group to clean
|
||||
* @param integer $max_hashes max hashes to get
|
||||
* @return array array of hashes as strings
|
||||
*/
|
||||
public function getHashes ($context='', $max_hashes=-1) {
|
||||
$len = count($this->hashes);
|
||||
$hashes = array();
|
||||
// Check in the hash list
|
||||
for ($i = $len - 1; $i >= 0 && $len > 0; $i--) {
|
||||
if ($this->hashes[$i]->inContext($context)) {
|
||||
array_push($hashes, $this->hashes[$i]->get());
|
||||
$len--;
|
||||
}
|
||||
}
|
||||
return $hashes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the hashes of a context
|
||||
* @param string $context the group to clean
|
||||
* @param integer $max_hashes ignore first x hashes
|
||||
* @return integer number of deleted hashes
|
||||
*/
|
||||
public function clearHashes ($context='', $max_hashes=0) {
|
||||
$ignore = $max_hashes;
|
||||
$deleted = 0;
|
||||
// Check in the hash list
|
||||
for ($i = count($this->hashes) - 1; $i >= 0; $i--) {
|
||||
if ($this->hashes[$i]->inContext($context) && $ignore-- <= 0) {
|
||||
array_splice($this->hashes, $i, 1);
|
||||
$deleted++;
|
||||
}
|
||||
}
|
||||
if ($deleted > 0) {
|
||||
$this->_save();
|
||||
}
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an input html element
|
||||
* @param string $context Name of the form
|
||||
* @param integer $time2Live Seconds before expire
|
||||
* @param integer $max_hashes Clear old context hashes if more than this number
|
||||
* @return integer html input element code as a string
|
||||
*/
|
||||
public function input ($context='', $time2Live=-1, $max_hashes=5) {
|
||||
// Generate hash
|
||||
$hash = $this->generateHash ($context, $time2Live, $max_hashes);
|
||||
// Generate html input string
|
||||
return '<input type="hidden" name="' . htmlspecialchars($this->inputName) . '" id="' . htmlspecialchars($this->inputName) . '" value="' . htmlspecialchars($hash->get()) . '"/>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a script html element with the hash variable
|
||||
* @param string $context Name of the form
|
||||
* @param string $name The name for the variable
|
||||
* @param integer $time2Live Seconds before expire
|
||||
* @param integer $max_hashes Clear old context hashes if more than this number
|
||||
* @return integer html script element code as a string
|
||||
*/
|
||||
public function script ($context='', $name='', $declaration='var', $time2Live=-1, $max_hashes=5) {
|
||||
// Generate hash
|
||||
$hash = $this->generateHash ($context, $time2Live, $max_hashes);
|
||||
// Variable name
|
||||
if (strlen($name) === 0) {
|
||||
$name = $this->inputName;
|
||||
}
|
||||
// Generate html input string
|
||||
return '<script type="text/javascript">' . $declaration . ' ' . $name . ' = ' . json_encode($hash->get()) . ';</script>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a javascript variable with the hash
|
||||
* @param string $context Name of the form
|
||||
* @param string $name The name for the variable
|
||||
* @param integer $time2Live Seconds before expire
|
||||
* @param integer $max_hashes Clear old context hashes if more than this number
|
||||
* @return integer html script element code as a string
|
||||
*/
|
||||
public function javascript ($context='', $name='', $declaration='var', $time2Live=-1, $max_hashes=5) {
|
||||
// Generate hash
|
||||
$hash = $this->generateHash ($context, $time2Live, $max_hashes);
|
||||
// Variable name
|
||||
if (strlen($name) === 0) {
|
||||
$name = $this->inputName;
|
||||
}
|
||||
// Generate html input string
|
||||
return $declaration . ' ' . $name . ' = ' . json_encode($hash->get()) . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a string hash
|
||||
* @param string $context Name of the form
|
||||
* @param integer $time2Live Seconds before expire
|
||||
* @param integer $max_hashes Clear old context hashes if more than this number
|
||||
* @return integer hash as a string
|
||||
*/
|
||||
public function string ($context='', $time2Live=-1, $max_hashes=5) {
|
||||
// Generate hash
|
||||
$hash = $this->generateHash ($context, $time2Live, $max_hashes);
|
||||
// Generate html input string
|
||||
return $hash->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate by context
|
||||
* @param string $context Name of the form
|
||||
* @return boolean Valid or not
|
||||
*/
|
||||
public function validate ($context='', $hash = null) {
|
||||
// If hash was not given, find hash
|
||||
if (is_null($hash)) {
|
||||
if (isset($_POST[$this->inputName])) {
|
||||
$hash = $_POST[$this->inputName];
|
||||
}
|
||||
else if (isset($_GET[$this->inputName])) {
|
||||
$hash = $_GET[$this->inputName];
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check in the hash list
|
||||
for ($i = count($this->hashes) - 1; $i >= 0; $i--) {
|
||||
if ($this->hashes[$i]->verify($hash, $context)) {
|
||||
array_splice($this->hashes, $i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load hash list
|
||||
*/
|
||||
private function _load () {
|
||||
$this->hashes = array();
|
||||
// If there are hashes on the session
|
||||
if (isset($_SESSION[$this->name])) {
|
||||
// Load session hashes
|
||||
$session_hashes = unserialize($_SESSION[$this->name]);
|
||||
// Ignore expired
|
||||
for ($i = count($session_hashes) - 1; $i >= 0; $i--) {
|
||||
// If an expired found, the rest will be expired
|
||||
if ($session_hashes[$i]->hasExpire()) {
|
||||
break;
|
||||
}
|
||||
array_unshift($this->hashes, $session_hashes[$i]);
|
||||
}
|
||||
if (count($this->hashes) != count($session_hashes)) {
|
||||
$this->_save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save hash list
|
||||
*/
|
||||
private function _save () {
|
||||
$_SESSION[$this->name] = serialize($this->hashes);
|
||||
}
|
||||
}
|
||||
|
||||
class CSRF_Hash {
|
||||
|
||||
private $hash;
|
||||
private $context;
|
||||
private $expire;
|
||||
|
||||
/**
|
||||
* [__construct description]
|
||||
* @param string $context [description]
|
||||
* @param integer $time2Live Number of seconds before expiration
|
||||
*/
|
||||
function __construct($context, $time2Live=0, $hashSize=64) {
|
||||
// Save context name
|
||||
$this->context = $context;
|
||||
|
||||
// Generate hash
|
||||
$this->hash = $this->_generateHash($hashSize);
|
||||
|
||||
// Set expiration time
|
||||
if ($time2Live > 0) {
|
||||
$this->expire = time() + $time2Live;
|
||||
}
|
||||
else {
|
||||
$this->expire = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The hash function to use
|
||||
* @param int $n Size in bytes
|
||||
* @return string The generated hash
|
||||
*/
|
||||
private function _generateHash ($n) {
|
||||
return bin2hex(openssl_random_pseudo_bytes($n/2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if hash has expired
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasExpire () {
|
||||
if ($this->expire === 0 || $this->expire > time()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify hash
|
||||
* @return boolean
|
||||
*/
|
||||
public function verify ($hash, $context='') {
|
||||
if (strcmp($context, $this->context) === 0 && !$this->hasExpire() && hash_equals($hash, $this->hash)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Context
|
||||
* @return boolean
|
||||
*/
|
||||
public function inContext ($context='') {
|
||||
if (strcmp($context, $this->context) === 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hash
|
||||
* @return string
|
||||
*/
|
||||
public function get () {
|
||||
return $this->hash;
|
||||
}
|
||||
}
|
|
@ -8,7 +8,11 @@
|
|||
<body>
|
||||
<?php
|
||||
include("session_verif.php");
|
||||
// Include the PHP-CSRF library
|
||||
include('php-csrf.php');
|
||||
verifier_session();
|
||||
|
||||
$csrf = new CSRF();
|
||||
?>
|
||||
|
||||
<!-- Input to choose files -->
|
||||
|
@ -61,6 +65,9 @@ function uploadFiles() {
|
|||
i ++;
|
||||
}
|
||||
|
||||
//csrf token
|
||||
formData.append("jeton-csrf","<?=$csrf->string($context="televersement")?>");
|
||||
|
||||
// Append captured images as files to the FormData
|
||||
const capturedImages = document.querySelectorAll('#selectedImages img');
|
||||
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
<?php
|
||||
|
||||
include('php-csrf.php');
|
||||
|
||||
session_start();
|
||||
|
||||
$csrf = new CSRF();
|
||||
|
||||
|
||||
include("session_verif.php");
|
||||
|
||||
|
||||
|
@ -90,14 +94,15 @@ function displayDocuments() {
|
|||
<?php displayDocuments(); ?>
|
||||
|
||||
<script>
|
||||
|
||||
function valider_ensemble(ensembleId) {
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("jeton-csrf","<?=$csrf->string($context="valider_ensemble")?>");
|
||||
formData.append("ensemble_id",ensembleId);
|
||||
fetch('api.php/valider_ensemble', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: 'ensemble_id=' + ensembleId,
|
||||
body: formData,
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
|
@ -114,13 +119,13 @@ function displayDocuments() {
|
|||
|
||||
|
||||
function supprimer_ensemble(ensembleId) {
|
||||
const formData = new FormData();
|
||||
formData.append("jeton-csrf","<?=$csrf->string($context="supprimer_ensemble")?>");
|
||||
formData.append("ensemble_id",ensembleId);
|
||||
|
||||
fetch('api.php/supprimer_ensemble', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: 'ensemble_id=' + ensembleId,
|
||||
body: formData,
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
|
|
Loading…
Reference in a new issue