The best way to guarantee the correct settings for Ajax calls

I am working on a website that requires some ajax calls to increase flexibility and performance. My ajax calls relate to the ranking system. I need three input values ​​to handle using ajax (storeID, clientID, orderID). To submit an action using ajax, I want to make sure that the passed parameter values ​​have not been changed by users using web tools. Therefore, I thought of three different ways to ensure that the information sent was not changed:

  • Send an extra value, which is the encryption of all the data sent. Therefore, on the server side, when processing ajax, I can re-encrypt the sent data and see if the encryption result matches the transmitted encryption value.

  • Send all data as a single encrypted value. Then on the server, when doing ajax, I can decrypt the data and assign the values ​​again.

  • Send only the orderID and its encryption, and then using method (1), make sure that the orderID is not changed and that using the database query, two other data is retrieved.

Here is my opinion on each of the three methods:

  • Consumes memory, since I have to send orderID, clientID, storeID, encryptedID. Moreover, the information tracked when ajax is called will give people information about what happens when they evaluate the order.

  • I checked online for mcrypt_encrypt and mcrypt_decrypt, but I never used them. I saw that they produce a long string, but I prefer my data to be transmitted short or to look like encrypted md5 data. Are there any better methods?

  • This is an elegant way, it looks straightforward, but it needs some MySQL intervention, which can take a lot of time, especially when data will grow in the future.

So which one do you think is better? If you have more ways, I appreciate it if you share them here. Thanks you

, : AJAX, . X Y. , ID Y . , . , .

PS: CSRF.

+4
10

salt (.. sha/md5 ..) , ( ).

, , , , , , , .

:

define('SUPER_SECRET_KEY', 'foobar123'); // our 007 secret key to hash requests against

function generateToken($storeID, $clientID, $orderID) {
    return hash('sha256', SUPER_SECRET_KEY . "/{$storeID}/{$clientID}/{$orderID}");
}

function validateToken($token, $storeID, $clientID, $orderID) {
    return generateToken($storeID, $clientID, $orderID) === $token;
}

, , . salt , - (, - /clientID/storeID/orderID ).

, nonce salt.

nonces, :

function generateNonce() {
    return hash('sha512', mt_rand() . time()); // please make a more secure nonce generator than this :)
}

// We need a way to retrieve the nonce for a particular request:
function generateLookup($storeID, $clientID, $orderID) {
    return hash('sha256', "{$storeID}/{$clientID}/{$orderID}");
}

function generateToken($nonce, $storeID, $clientID, $orderID) {
    $lookup = generateLookup($storeID, $clientID, $orderID);

    // Store the $nonce and $lookup somewhere (i.e a database)
    $db->query("INSERT INTO ... (nonce,lookup,expired) VALUES ('$nonce','$lookup','N')");

    return hash('sha256', "{$nonce}/$storeID/$clientID/$orderID");
}

function validateToken($token, $storeID, $clientID, $orderID) {
    $lookup = generateLookup($storeID, $clientID, $orderID);
    $rows = $db->query("SELECT nonce FROM ... WHERE lookup = '$lookup' AND expired = 'N'"); // again, pseudocode for retrieving the nonce from the persistent store
    if (count($rows) !== 0) {
        $nonce = $rows[0]['nonce'];
        // expire the nonce (note: these database queries should be in a transaction)
        $db->query("UPDATE ... SET expired = 'Y' WHERE $lookup = '$lookup' AND nonce = '$nonce'");
        return generateToken($nonce, $storeID, $clientID, $orderID) === $token;
    }
    return false;
}

:

GET

$data = // retrieve data
$token = generateToken(generateNonce(), $data['storeID'], $data['clientID'], $data['orderID']);

// output the $token value in a hidden field in your form

POST

if (validateToken($_POST['token'], $_POST['storeID'], $_POST['clientID'], $_POST['orderID'])) {
    // All good
}
else {
    echo "Back, ye filthy hacker!";
}
+2

:

....

  • , (auth).
  • , (ACL).
  • , .
  • , X-, Y, , .
  • , , (, ) . Y- X-. , Y Firebug, ?

2 3, . , , .

+5

, Mcrypt Rijndael. 128 .

, (storeID, clientID, orderID) 32 , 4- , 128- . .

$block = pack('a4LLL', 'MyID', $storeID, $clientID, $orderID);

IV :

$mod = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
$iv = openssl_random_pseudo_bytes(mcrypt_enc_get_iv_size($mod));
$mySecretKey = 'LA72U/aLEOcDoN0rqtM5sehNNjd7TUSILiBgI8bej6o=';

mcrypt_generic_init($mod, base64_decode($mySecretKey), $iv);

$encrypted = mcrypt_generic($mod, $block);

mcrypt_generic_deinit($mod);
mcrypt_module_close($mod);

IV, . base64 / + , GET:

$encodedBlock = substr(strtr(base64_encode($encrypted), '/+', '-_'), 0, -2);
$encodedIV = substr(strtr(base64_encode($iv), '/+', '-_'), 0, -2);

, ajax, :

$encrypted = base64_decode(strtr($_GET['block'], '-_', '/+') . '==');
$iv = base64_decode(strtr($_GET['iv'], '-_', '/+') . '==');
$mod = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');

mcrypt_generic_init($mod, base64_decode($mySecretKey), $iv);

$block = mdecrypt_generic($mod, $encrypted);

mcrypt_generic_deinit($mod);
mcrypt_module_close($mod);

$data = unpack('a4str/Lstore/Lclient/Lorder', $block);

if ($data['str'] != 'MyID')
  throw new Exception('Something fishy is going on');

, $data ['store'], $data ['client'] $data ['order'].

nonce , .

+3

, .

, , ( ).

, . . ajax .

+2

.

, .

, .

, ​​ , . som CSRF, , , , -, script ..

, , , , , , , /, . - , , hanlde ( ajax ) , (, ). -CSRF, , ( , , ..)

, -CSRF- , , . , "id", . ..

+2

- .

. ( REST)

  • , orderID
  • , : ,

: , , .

+2

, - , , (, md5), , , .

, javscript md5, :

hash=md5('sometext'+storeID+clientID+orderID);

AJAX , , , .

, , , , -, . , .

, md5 . .

+1

. , , , . , , , .

, , (, $SESSION). , , .

, .

, , script .

- , , - , , , , . , . , , , , , , , , , .

: , , , :

: mcrypt_create_iv . , 20 .

$formtoken = mcrypt_create_iv(20);
$_SESSION['infos'][$formtoken] = array($value,$anothervalue);

$formtoken . , AJAX, , , . , , - , , , , , , .

+1

, http . :

https .

https, , , .

, ajax, , .

, .

, , (, ) . .

, ,

, , .

  • , .
  • , .

→ →

, , , , .

, V1, V2, ... http, , .

ajax .

V1, V2, ..., Vn , , .

TheSecret, . :

SignValue := md5( V1 + V2 + ... Vn + TheSecret )

, . md5 .

TheSecret, . DailySecret :

DailySecret := TheSecret  + md5( TheSecret + date( 'Ymd' ) )
SignValue := md5( V1 + V2 + ... Vn + DailySecret )
0

, ajax .

But if you cannot do this, you can also just assign values ​​to the server, and your ajax only accepts hashed values. If the client changes the hash, it becomes invalid, so you go. This is standard practice to prevent identity manipulation.

Hope this helps.

0
source

Source: https://habr.com/ru/post/1541199/


All Articles