PDA

View Full Version : سوال: سوال در مورد cookie و امنیت ورود و خروج



mamali-mohammad
یک شنبه 04 فروردین 1392, 20:20 عصر
سلام
طبق سایت w3schools یاد گرفتم از کوکی استفاده کنم
در سایتم زمانی کاربر ثبت نام میکنه پسورد با یه رشته جمع میشه و 2-3 بار md5 میشه و در دیتابیس ذخیره میشه
زمان لاگین اگه این یوز و پسورد صحیح باشه اینطوری کوکی ایجاد میکنم :

<?php
setcookie("user", $name, time()+3600);
?>
بعد از ورود برای صحت اینکه کاربر در سایت هست یا نه این کد رو میزنم ( مثلا میخوایم دکمه خروج به کاربر نشون بده اما به مهمان این دکمه نیاد ) :

<?php
if (isset($_COOKIE["user"]))
echo "Welcome " . $_COOKIE["user"] . "!<br>";
else
echo "Welcome guest!<br>";
?>
برای خروج هم این کد رو گذاشتیم :

<?php
// set the expiration date to one hour ago
setcookie("user", "", time()-3600);
?>
برای واکشی از دیتابیس هم این کد رو گذاشتیم :

$username=$_COOKIE["user"];
mysql_query("SELECT * FROM `user` WHERE `username`='$username'");

نظر شما چیه ؟
ممنون

eshpilen
یک شنبه 04 فروردین 1392, 20:29 عصر
وضع امنیتش خرابه!
الان هر کاربر میتونه نام کاربری دلخواه خودش رو توی کوکی ست کنه و بجای دیگران (یا حتی ادمین) شناخته بشه.
دوما، اونکه محتویات کوکی رو مستقیما در کوئری درج کردی حفرهء SQL Injection ایجاد میکنه.

تمام اطلاعاتی که از سمت کلاینت میاد ممکنه جعلی و خطرناک باشن.
دستکاری کردن کوکی هم که دیگه کاری نداره!

mamali-mohammad
یک شنبه 04 فروردین 1392, 21:20 عصر
عذر میخوام میشه مثال بزنید ؟
1- راه نفوذ
2- کد صحیح
ممنون از شما

eshpilen
دوشنبه 05 فروردین 1392, 00:00 صبح
عذر میخوام میشه مثال بزنید ؟
1- راه نفوذ
2- کد صحیح
ممنون از شما
راه نفوذ چیه!
یعنی خبر نداشتی که کاربران میتونن هر کوکی ای با هر محتویاتی که میخوان ست کنن؟
کد صحیح هم که بنده سرنخ دادم. دیگه وقت ندارم هر روز چندتا از این سوالها میشه واسه مردم کد بنویسم.
سرچ کن تحقیق کن کد، منبع زیاد هست؛ کار خودت رو خودت باید انجام بدی. بالاخره که باید یاد بگیری!
اینا هم چیزهای آنچنان پیچیده یا نادری نیست که بگی هرکسی نمیدونه و راه حلش مشخص نیست. درحد واقعا مبتدیه.

از نظر کوکی میتونم بیشتر راهنمایی کنم که شما باید به ازای هر کاربر یه رشتهء رندوم هم داشته باشی که اون رو هم توی کوکی ذخیره و مقایسه کنی با مقدار موجود در دیتابیس یا سشن برای احراز هویت.
کاربر میتونه نام کاربری رو تغییر بده، ولی نمیدونه که مثلا رشتهء رندوم مربوط به کاربر دیگه چیه. بنابراین کوکی جعلیش راه به جایی نمیبره.
البته اگر از سشن استفاده کنی اصلا نیازی به کوکی خودت نداری. بنظر من از سشن استفاده کن و کار خودت رو راحت کن، چون استفادهء امن از کوکی برای احراز هویت، نکته داره و باید دانش و مهارتش رو داشته باشی. البته روش رشتهء رندوم ظاهرا خوبه، ولی ممکنه نیازها و نکات پیشبینی نشده ای هم برای شما و برنامهء شما پیش بیاد، که در تمام این موارد سشن جایگزین خوبیه برای اینکه خیالت راحت باشه.

اول برو یه چیزی رو یاد بگیر بعد استفاده کن. اینا هم کاملا به امنیت نیاز دارن، پس اول باید بری مبحث امنیت رو یاد بگیری بعد بیای سیستم احراز هویت درست کنی.

mamali-mohammad
دوشنبه 05 فروردین 1392, 00:49 صبح
ممنون از شما
من نگفتم کد بدید بلکه راهنمایی خواستم
الان من با همون کوکی که ساختم وارد سایت شدم
اما برای ویرایش کوکی جایی ندیدم که یوزر باشه و بشه تغییرش داد
بلکه خود مرورگر کوکی رندوم رو منحصر به فرد میسازه
خب هکر چطوری قرار این کوکی رو بدست بیاره ؟!
اگه اشتباه میکنم شما توضیح بدید

eshpilen
دوشنبه 05 فروردین 1392, 02:04 صبح
اما برای ویرایش کوکی جایی ندیدم که یوزر باشه و بشه تغییرش داد
میگی توی مرورگر جایی نیست؟
خب لزوما که از مرورگر بطور مستقیم برای این کار استفاده نمیشه.
هرچند احتمالا برای مرورگرها هم addon ای چیزی باشه واسه اینطور کارها. ولی من اطلاع ندارم چون توی خط هک نبودم تاحالا.


بلکه خود مرورگر کوکی رندوم رو منحصر به فرد میسازه
کوکی رندوم؟
کدوم کوکی رندوم؟
مرورگر فقط همون چیزی که شما مشخص میکنید رو میسازه.
فقط هر کوکی رو هر سایتی ست کرده، کوکی رو در دسترس اون سایت میذاره و سایت دیگه بهش دسترسی نداره.


خب هکر چطوری قرار این کوکی رو بدست بیاره ؟!
اگه اشتباه میکنم شما توضیح بدید

کدوم رو؟ اون که فقط نام کاربری رو توش ذخیره کردی؟
کاری نداره با همین PHP هم میشه یه برنامه چند خطی نوشت که درخواست HTTP ارسال کنه با هر کوکی دلخواه. دقیقا مثل کاری که مرورگر میکنه. مرورگر هم یه برنامس دیگه. هرکاری مرورگر بکنه میشه برنامش رو نوشت که همون کار رو بکنه (منتها با چیزهای جعلی که میخوایم توی درخواست بفرسته).
اگر برنامت آنلاین باشه میتونم یه روشی بهت بگم که باهاش تست و ثابتش کنیم.

mamali-mohammad
دوشنبه 05 فروردین 1392, 12:54 عصر
ممنون از شما
پس اجازه بدید من با همین کدهایی که اینجا نوشتم یه برنامه ساده بنویسم آنلاین شما تست کنید
ممنون

رضا قربانی
دوشنبه 05 فروردین 1392, 13:01 عصر
سوال در مورد cookie و امنیت ورود و خروج


اصلا امنیت نداره :لبخند:

mamali-mohammad
دوشنبه 05 فروردین 1392, 14:37 عصر
بعد از ورود یه کد رندوم میدم 32 رقمی در دیبتابیس ذخیره میکنم و کوکی رو بر اساس اون میخونه
مشکل حل میشه ؟

T.R.G.T
دوشنبه 05 فروردین 1392, 14:48 عصر
دوست عزیز کل مشکل اینه که اطلاعات کوکی هم مانند قت و پست قابل تغییر هستند و نباید به کوکی ها زیاد اعتماد کرد برای استفاده از کوکی در دیتابیس یا برای نمایش حتما باید اطلاعات رو فیلتر کنید نه تنها کوکی بلکه برای استفاده از هرداده ای باید تدابیر مخصوص اون رو برای امنیت بیشتر به کار ببرید

mamali-mohammad
دوشنبه 05 فروردین 1392, 14:53 عصر
منظور شما escape و special chars هست ؟

mamali-mohammad
دوشنبه 05 فروردین 1392, 16:52 عصر
من کدم رو اینطوری تغییر دادم
زمانی که کاربر لاگین میکنه یه کد رندوم درست میکنه خود php به این صورت :

$code=md5(rand(1000,5000));
بعدش این کد رو در دیتابیس ذخیره میکنیم برای کاربر و همچنین به کوکی هم میدیمش

setcookie("user", $code, time()+3600);

حالا برای کشیدن اطلاعات کاربر از کد استفاده می کنیم

mysql_query("SELECT * FROM `user` WHERE `code`='$code'");

بهتر شد ؟

2undercover
دوشنبه 05 فروردین 1392, 19:08 عصر
نه!!!

چون اولا ممکنه code تکراری دربیاد تازه به راحتی میشه کد جعلی ساخت!

mamali-mohammad
دوشنبه 05 فروردین 1392, 19:23 عصر
شما بفرمایید ما چه کنیم ؟

eshpilen
دوشنبه 05 فروردین 1392, 19:50 عصر
من کدم رو اینطوری تغییر دادم
زمانی که کاربر لاگین میکنه یه کد رندوم درست میکنه خود php به این صورت :

$code=md5(rand(1000,5000));
بعدش این کد رو در دیتابیس ذخیره میکنیم برای کاربر و همچنین به کوکی هم میدیمش

setcookie("user", $code, time()+3600);

حالا برای کشیدن اطلاعات کاربر از کد استفاده می کنیم

mysql_query("SELECT * FROM `user` WHERE `code`='$code'");

بهتر شد ؟
الان بهتر شد.
ولی تعداد حالتهای کد رندوم شما 4000 حالت بیشتر نیست که این خیلی کمه.
این تعداد رو قطعا میشه Brute-force کرد.
هیچوقت با این فرض روی امنیت کار نکن که هکر نمیدونه الگوریتم مورد استفادهء شما چیه! فرض کن دقیقا میدونه چه الگوریتمی استفاده کردی.

تابع رندومت هم از نوع امنیتی نیست.
باید با یک تابع رندوم امنیتی، یک رشتهء رندوم با تعداد حالتهای به مراتب بیشتر (مثلا 2 به توان 128 حالت) ایجاد کنی.
بعدش، در کوکی فقط کد رندوم رو ذخیره نکن. نام کاربری رو هم ذخیره کن.
یعنی هر دوی نام کاربری و کد رندوم رو از کوکی بخون و باهاشون کوئری درست کن به این شکل:


$user=mysql_real_escape_string($user);
$code=mysql_real_escape_string($code);

mysql_query("SELECT * FROM `user` WHERE `username`='$user' AND `code`='$code'");

ضمنا رشتهء رندوم رو میتونی موقع ثبت نام تولید کنی و در رکورد کاربر درج بشه و تغییر نکنه. ولی اینکه در هر لاگین تغییر کنه هم از نظر امنیتی خوبه. بنده در پروژهء خودم این رو قابل کانفیگ گذاشتم که تغییر بکنه یا نکنه. واسه من موقع لاگ آوت هم عوض میشه! و حتی میشه تنظیم کرد که در هر درخواست معمولی هم تغییر بکنه.

eshpilen
دوشنبه 05 فروردین 1392, 19:57 عصر
البته اصولا درج نام کاربری در کوکی هم از نظر اصول امنیت صحیح نیست. بجاش میتونی از یه چیز دیگه ای مثل آیدی عددی رکورد استفاده کنی.
اگر از آیدی عددی استفاده کردی اونوقت بجای mysql_real_escape_string میتونی از توابعی مثل is_numeric هم برای مطمئن شدن از اینکه جز عدد چیزی نباشه (و بنابراین برای درج در کوئری خطرناک نباشه) استفاده کنی. البته میتونی از همون mysql_real_escape_string هم استفاده کنی، ولی اونوقت در کوئری باید حتما مقدار آیدی رو در کوتیشن قرار بدی مثل رشته ها.

مثال:

روش اول:


if(!is_numeric($id)) exit('id not numeric');
$code=mysql_real_escape_string($code);

mysql_query("SELECT * FROM `user` WHERE `id`=$id AND `code`='$code'");

روش دوم:


$id=mysql_real_escape_string($id);
$code=mysql_real_escape_string($code);

mysql_query("SELECT * FROM `user` WHERE `id`='$id' AND `code`='$code'");

البته امنیت که بیش از این نکته داره. ولی اینا فعلا درشت هاش و درحد پایه بودن.
مثلا کوکی رو با فلگ http_only ست کن.

mamali-mohammad
دوشنبه 05 فروردین 1392, 20:02 عصر
ممنون
پس اجازه بدید اینرو از اول مرور کنیم
از ثبت نام تا ورو
ثبت نام
تابع esc همون فراخوانی برای escpae و ... هست
* بررسی صحت ایمیل ، خالی نبودن اینا رو انجام میدم اما در این کد ننوشتم دیگه

<?php
if($_POST['register']){
$username=esc($_POST['username']);
$password=esc($_POST['password']);
$password=$password+"ce236Fgvv";
$password=md5(md5(md5($password)));
mysql_query("INSERT INTO `user` (username,password) VALUES ('$username','$password')")
}
?>

ورود

<?php
if($_POST['login']){
$username=esc($_POST['username']);
$password=esc($_POST['password']);
$password=$password+"ce236Fgvv";
$password=md5(md5(md5($password)));
$sql=mysql_query("SELECT * FROM `user` WHERE `username`='$username' AND `password`='$password'");
if(mysql_num_rows($sql)>0) {
$code=base64_encode(md5(rand(1000,5000));
mysql_query("UPDATE `user` SET (`code`='$code') WHERE `username`='$username' LIMIT 1");
} else {
echo 'Error !';
}
}
?>

eshpilen
دوشنبه 05 فروردین 1392, 20:13 عصر
خب توی این مایه ها دیگه.
البته هنوز مثلا روش هش مبتدیه، ولی این مشکل درحد برنامهء آموزشی شما نیست.
کد رندوم هم که گفتم هم تابعش باید قویتر باشه و هم تعداد حالتهای ممکنش خیلی بیشتر.
راستی خروجی md5 رو دیگه واسه چی base64_encode کردی؟
راستی پسورد رو وقتی md5 کنی خروجی md5 دیگه خطر SQL injection نداره و بنابراین نیازی به Escape کردنش نیست. فقط حواست باشه قبل از هش شدن توی کوئری نذاری (چون مثلا mysql خودش هم تابع هش داره).

mamali-mohammad
دوشنبه 05 فروردین 1392, 20:18 عصر
حالا یه تابع که بیشتر نست پس بهتره که escape بشه
برای این base64 کردم که قویتر باشه
این کد چطوره :

$rand = substr(md5(microtime()),rand(0,26),5);

eshpilen
دوشنبه 05 فروردین 1392, 20:18 عصر
یک تابع رندوم امنیتی خفن ناک: http://www.hamidreza-mz.tk/?p=649

eshpilen
دوشنبه 05 فروردین 1392, 20:23 عصر
برای این base64 کردم که قویتر باشه
این کد چطوره :

$rand = substr(md5(microtime()),rand(0,26),5);
با این کارا قویتر نمیشه که کلی ضعیف تر هم میشه.
اصول یه چیزی رو نمیدونی همینطوری پشتک وارو نزن که خطرناکه!
نکن این کارها را :متعجب:

با همون تابع رندومی که دادم یه رشتهء 22 کاراکتری متشکل از حروف بزرگ و کوچک و اعداد درست کن.
البته حالا که حجمش زیاد مسئله نیست، اصلا 41 کاراکتر (مثل پروژهء خودم) بگیر که دیگه هیچ شک و شبهه توش نباشه.
ولی خب برنامهء شما در اون حد نیست که 22 و 41 واسش زیاد فرقی بکنه (بهت برنخوره ها :لبخند:).

mamali-mohammad
دوشنبه 05 فروردین 1392, 20:50 عصر
با این کارا قویتر نمیشه که کلی ضعیف تر هم میشه.
اصول یه چیزی رو نمیدونی همینطوری پشتک وارو نزن که خطرناکه!
نکن این کارها را :متعجب:

با همون تابع رندومی که دادم یه رشتهء 22 کاراکتری متشکل از حروف بزرگ و کوچک و اعداد درست کن.
البته حالا که حجمش زیاد مسئله نیست، اصلا 41 کاراکتر (مثل پروژهء خودم) بگیر که دیگه هیچ شک و شبهه توش نباشه.
ولی خب برنامهء شما در اون حد نیست که 22 و 41 واسش زیاد فرقی بکنه (بهت برنخوره ها :لبخند:).

نه بر نمیخوره
اما من تا الان با سشن کار میکردم تصمیم گرفتم از کوکی استفاده کنم
برنامه هم کم و بیش بزرگ هست و اگه میتونستم حتما آدرسش رو میدادم ببینید که کاربر زیادی رو جذب خودش کرده
اما سشن واقعا روی اعصاب بود

اقا از اینا بگذریم خیلی لطف کردی حال دادی
اگه موردی نیست این تحلیل مارو بخون ببین دیگه موردی میمونه یا نه

1- کاربر ثبت نام میکنه ( پسورد با همین تابعی که شما گفتی ساخته میشه برای کاربر )
یه ستون code هم میزاریم اما خالیه ( میخوایم کوکی رو زمان ورود بزاریم )

2- زمان ورود یه کد رندوم قوی ساخته میشه و این کد برای کوکی در نظر گرفته میشه و همچنین در ستون code برای کاربر هم ذخیره میشه

3- زمان فراخوانی هم دوباره کوکی رو میخونیم و از فیلترمون ردش میکنیم و مطابقت میدیم با code موجود در جدول

درست شد ؟
ممنون

eshpilen
دوشنبه 05 فروردین 1392, 21:05 عصر
آره خوبه تا اینجا.