نقطه ویرگول;

هر از گاهی از هر چیزی

هر از گاهی از هر چیزی

HMAC Verification

چهارشنبه, ۳۰ آذر ۱۳۹۰، ۰۶:۳۵ ب.ظ
توی یکی از کتاب هایی که داشتم مطالعه می کردم به موضوع جالبی در مورد امنیت URL ها رسیدم که بد ندیدم اونو با شاما دوستان به اشتراک بزارم.
Validate کردن داده های ارسالی یا همون آرگومان ها جزو اصول اولیه تضمین امنیت برای یک برنامه هستش. راه حل های مختلفی مثل استفاده کردن از White/Black List, Escaping و .... وجود داره. ولی حقیقت اینه که دور زدن این مدل از بررسی صحت داده ها برای یک کرکر کار درست, چندان سخت نیست.....
HMAC Verification روشی هست که تو این پست قصد داریم نگاهیی به اون داشته باشیم. خلاصه روش این هست که از آرگومان های ارسالی یک هش درست می کنیم و اون رو به همراه خود آرگومان ها ارسال می کنیم که اگر یه زمانی یه کرکر با آرگومانهای ما شلوغ کاری کرد سیستم Validation ما قابل دور زدن نباشه.
این کلاس یک نمومه ساده از پیاده سازی این روش هستش.
[sourcecode language="php"]
function create_parameters($array) {
$data = '';
$ret = array();
foreach ($array as $key => $value) {
$data .= $key . $value;
$ret[] = "$key=$value";
}
$hash = md5($data); // sha1($data) or any hashing func you want
$ret[] = "hash=$hash";
return join ('&', $ret); // you can use implode instead of join
}
echo ' Target URL ';
// out put:
// Target URL
[/sourcecode]
خوب این روش اول کمی ساده هستش و با Brute Force و یا یکم حرفه ای تر به کمک Rainbow ها قابل دور زدن هستش. حالا اگه از روش HMAC استفاده کنیم دیگه می شه گفت که امنیت این قسمت از برنامه رو تضمین کردیم.
کلاسی که الان معرفی می شه برای هش کردن داده ها به کمک یک کلید مخقی هستش که خودمون تعیین می کنیم.
[sourcecode language="php"]
// Crypt/HMAC.php
class Crypt_HMAC {
/**
* Constructor
* Pass method as first parameter
*
* @param string method - Hash function used for the calculation
* @return void
* @access public
*/
function Crypt_HMAC($key, $method = 'md5') {
if (!in_array($method, array('sha1', 'md5'))) {
die("Unsupported hash function '$method'.");
}
$this->_func = $method;
/* Pad the key as the RFC wishes (step 1) */
if (strlen($key) > 64) {
$key = pack('H32', $method($key));
}
if (strlen($key) _ipad = substr($key, 0, 64) ^ str_repeat(chr(0x36), 64);
$this->_opad = substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64);
}
/**
* Hashing function
*
* @param string data - string that will hashed (step 4)
* @return string
* @access public
*/
function hash($data) {
$func = $this->_func;
$inner = pack('H32', $func($this->_ipad . $data));
$digest = $func($this->_opad . $inner);
return $digest;
}
}
[/sourcecode]
برای استفاده کردن از این کلاس هم سلایق می تونه متفاوت باشه. در زیر یه نمونه از پیاده سازی نهایی و در نهایت بررسی صحت داده ها بعد از دریافت URL هش شده برای شما آماده کردم.
[sourcecode language="php"]
require_once('Crypt/HMAC.php');
/* The RFC recommends a key size larger than the output hash
* for the hash function you use (16 for md5() and 20 for sha1()). */
define ('SECRET_KEY', 'Professional PHP 5 Programming Example');
function create_parameters($array) {
$data = '';
$ret = array();
/* Construct the string with our key/value pairs */
foreach ($array as $key => $value) {
$data .= $key . $value;
$ret[] = "$key=$value";
}
$h = new Crypt_HMAC(SECRET_KEY, 'md5');
$hash = $h->hash($data);
$ret[] = "hash=$hash";
return join ('&', $ret);
}
echo 'URL!';
// output
// URL!
[/sourcecode]
[sourcecode language="php"]
// To verify the parameters passed to the script, we can use this script:
require_once('Crypt/HMAC.php');
define ('SECRET_KEY', 'Professional PHP 5 Programming Example');
function verify_parameters($array) {
$data = '';
$ret = array();
/* Store the hash in a separate variable and unset the hash from
* the array itself (as it was not used in constructing the hash
*/
$hash = $array['hash'];
unset ($array['hash']);
/* Construct the string with our key/value pairs */
foreach ($array as $key => $value) {
$data .= $key . $value;
$ret[] = "$key=$value";
}
$h = new Crypt_HMAC(SECRET_KEY, 'md5');
if ($hash != $h->hash($data)) {
return FALSE;
} else {
return TRUE;
}
}
/* We use a static array here, but in real life you would be using
* $array = $_GET or similar. */
$array = array(
'cause' => 'vars',
'hash' => '6a0af635f1bbfb100297202ccd6dce53'
);
if (!verify_parameters($array)) {
die("Dweep! Somebody tampered with our parameters.n");
} else {
echo "Good guys, they didn't touch our stuff!!";
}
[/sourcecode]
نکته: این موارد می تونه خیلی کامل تر هم باشه ولی خوب فعلا همین قدر سواد داریم.
مثلا می شه با اضافه کردن session و یا ذخیره کردن هش ها تو پایگاه داده بازهم امنیت رو بیشتر کرد.
در کل امنیت جزیی از سیستم هستش و به نظر من معیار کارایی هم به حساب می آید. پایان
موافقین ۰ مخالفین ۰ ۹۰/۰۹/۳۰
مرتضی فتحی

encrypt

hash

نظرات  (۳)

۱۵ دی ۹۰ ، ۰۱:۴۷ وحید چکشی
سلام خیلی جالب بود.
استفاده از md5sum بهترین روش برای validate کردن درخواستها و اجرای اسکریپتهاست.
سلام.
من حدود 3 یا 4 ماه بیشتر نیست که با PHP آشنا شدم و مبتدی هستم. یه سوال داشتم... کلا چرا باید از URL Hashing استفاده کنیم ؟ حالا چه به صورت Class و چه معمولی.
خوب اکثر حملات از طریق تغییر غیر مجاز یک سری input ها که وارد هسته یا موتور برنامه می شن, صورت می گیره. حالا این تغییرات می تونه عوض کردن داده های HTTP Request ها باشه یا نفوذ توی داده هایی که بین قسمت های مختلف برنامه از طریق GET , POST جابجا می شن.
حالا اگر بنا به هر دلیلی بررسی صحت داده ها سمت سرور به خوبی صورت نگرفته باشه یک نفوذگر می تونه با تغییر داده های URL یه حمله SQL Injection یا XSS انجام بده.
در کل تمامی این کار ها برای این هست که ما از وارد شدن داده های غیر مجاز به برنامه جلوگیری کنیم.
یکی از این راه ها URL Hashing هست که تا حدود بسیار زیادی عدم وجود داده های مخرب رو تضمین می کنه.

ارسال نظر

ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی