3

I am currently using a programm to send newsletters, in every newsletter I am sending a link so the customer can look at his own data and sub/unsub from newsletters. The link I am using now is this: http://localhost/Mail/subscriptionseditklant.php?ID=77 and is made with this code:

<a href="subscriptionsedit.php?page=1&ID=<?=$objResult["ID"];?>">subscriptions</a>

For security reasons I dont want to show the customer ID=77 part so he can't modify it to look at other customers info. My idea was to hide the ID inside random numbers (4 in front and 4 behind the ID) which I have done using this:

<a href="subscriptionsedit.php?page=1&ID=<? echo rand(1000,9999); ?><?=$objResult["ID"];?><? echo rand(1000,9999); ?>">subscriptions</a>

This will display a link like this one: http://localhost/Mail/subscriptionsedit.php?page=1&ID=9755774430

On the subscriptionsedit.php I am using $_GET to get the ID from the url.

My question:
Is there any way I can get $_GET to ignore the first 4 and last 4 numbers from the ID so it will capture the right ID?

I have tried to google for something like this but since I dont know how it is called (if it even exists) I was not able to find anything. I hope my question is clear but if you have any question just ask them! (Also if anyone knows a better title for this question feel free to edit it because I have no idea how to name this question)

Daanvn
  • 1,254
  • 6
  • 27
  • 42
  • 1
    ["Security through Obscurity"](https://en.wikipedia.org/wiki/Security_through_obscurity) is bad practice. See my answer to another question on how to encrypt the ID here: http://stackoverflow.com/questions/9465369/a-good-practice-for-creating-human-typable-non-sequential-unique-ids/9466640#9466640 – Kaii May 08 '13 at 09:49
  • You could always Post the I'd, then it will not be visible in the URL. – vascowhite May 08 '13 at 11:44

11 Answers11

2

Hiding number is poor solution, the better one is to encrypt this number via http://php.net/manual/en/function.mcrypt-encrypt.php

of course you can ignore letters cast this $_GET['var'] to char array and then use range for example

$_GET['var'] = 123543123;

to get 543 you need to use function substr():

$hidden_number = substr($_GET['var'],3,3);
Kaii
  • 20,122
  • 3
  • 38
  • 60
Robert
  • 19,800
  • 5
  • 55
  • 85
  • 1
    so many correct answers, and yet this is the only one mentioning that security through obscurity is a poor solution. – Kaii May 08 '13 at 09:51
  • after my post and your comment users will edit their posts :P heh – Robert May 08 '13 at 09:54
  • Thnx for your answer, I know that this isn't the best solution what I am doing but my "supervisor" wants me to use this. I solved it using substr but thnx for the suggestion to encrypt it! – Daanvn May 08 '13 at 11:07
  • tell your supervisor it's short term and insecure solution – Robert May 08 '13 at 11:12
2

Instead of trying to hide the id, you could use a mapping table on the server with two columns: primary(hash), id

The hash can be a random blob, but for readability you could use a uuid as well, e.g.

hash                                 | id
-------------------------------------+----
9d76d130-0119-4d7a-9eed-95ad3617e512 | 123

Then, use the hash inside the url. The advantage of a random hash is that there's no correlation between the hash and the id, other than the server-side table.

A smaller hash could be obtained by using uniqid() and md5() or sha1():

sha1(uniqid('', true));

Alternative

If the ID itself is public but you just want to avoid tampering, look into hash_hmac():

$salt = md5(uniqid('', true));
$signature = hash_hmac('sha1', $id . $salt, 'some super secret key');

Generate the key using something like base64_encode(openssl_random_pseudo_bytes(8))

You can add this $signature and $salt to the URL as well and then verify it when you receive it.

$id = $_GET['id'];
$salt = $_GET['salt'];

if (hash_hmac('sha1', $id . $salt, 'some super secret key') === $_GET['signature']) {
    // valid
}
Community
  • 1
  • 1
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • instead of using UUID a simple `md5(microtime(true).$ID)` would be sufficient as well. (a hash collision is not possible with this short input length) – Kaii May 08 '13 at 10:04
  • @Kaii Actually, `md5(uniqid(''))` would probably suffice as well :) – Ja͢ck May 08 '13 at 10:05
  • It's good but someone I was taught that the same thing should not be encrypted twice the same. That is why IV is used in block algorithms. Someone can reproduce this hash table after some time because it's static. – Robert May 08 '13 at 10:14
  • @RobertPodwika Yeah, a salt would be required as well. Updated my answer. – Ja͢ck May 08 '13 at 10:16
1

check the manual for substr method: http://php.net/substr

something like

$id = substr($_GET['ID'],4,-4); 

should do the trick you want

Kaffee
  • 1,563
  • 11
  • 21
1
$id= substr($_GET['ID'], 4, -4);
Spontifixus
  • 6,570
  • 9
  • 45
  • 63
RK.
  • 973
  • 5
  • 19
  • 45
0

You can use substr() function to remove the first 4 and last 4 characters from your string. But better yet, just encde your id using build-in php encryption function

andrew
  • 2,058
  • 2
  • 25
  • 33
0

Use encrypt and decrypt functions in PHP. Do not believe in your own algorithms. Otherwise you can use substr() in php.

Sudip Pal
  • 2,041
  • 1
  • 13
  • 16
0

this will work

$id='1234554321';
preg_match('/\d{4}(\d+)\d{4}/', $id, $matches);
var_dump($matches[1]);

But..

I wouldn't do that.

I would generate some unique string, store it database and provide it to end user. So that url would be lilke this

example.com/view.php?token=<unique-string>

see http://php.net/manual/en/function.uniqid.php to get unique string.

Ruslan Polutsygan
  • 4,401
  • 2
  • 26
  • 37
0

You could use substr() in PHP to extract the ID you need.

Something like this?

<?php echo substr($_GET['ID'], 4, -4); ?>

BUT, this is a horrible horrible idea for 'security' reasons.

You would be better off using an ID that isn't incremental and therefore 'guessable'. Try using a md5() function or something to generate an additional ID, as well as your primary key to store in the database.

http://php.net/manual/en/function.md5.php

Michael Giovanni Pumo
  • 14,338
  • 18
  • 91
  • 140
0

your subscriptionsedit.php script should accept the customer ID and look for

$_SESSION["PASSWORD"]

previously set by the user as a result of the login process, something like:

subscriptionsedit.php?page=1&ID=77

look at password stored in the $_SESSION["PASSWORD"] field 

doing that way it will not be possible to sneak inside the data of other customers because $_SESSION[] is private information held by the server for every user

Gianluca Ghettini
  • 11,129
  • 19
  • 93
  • 159
-1

You can use

preg_match('/^\d{4}(\d{4})/', $_GET['id'])
Haocheng
  • 1,323
  • 1
  • 9
  • 14
-1
$ID = substr($_GET['ID'], 3, -4);

http://www.php.net/manual/en/function.substr.php

Elliot Lings
  • 1,096
  • 1
  • 9
  • 16