PHP/SQL قاعدة بيانات الاستعلام عن ممارسة جيدة وأمن

StackOverflow https://stackoverflow.com/questions/826981

سؤال

لذلك أنا مطور PHP محنك قليلاً وكنت "أفعل الشيء اللعين" منذ عام 2007 ؛ ومع ذلك ، ما زلت n00bish نسبيا عندما يتعلق الأمر بتأمين طلباتي. في الطريقة التي لا أعرف بها حقًا كل ما أعرفه ، يجب أن أتمكن من ذلك.

لقد التقطت تأمين تطبيقات الويب PHP وأنا أقرأ طريقي من خلال اختبار الأشياء على طول الطريق. لدي بعض الأسئلة للجنرال حتى المجموعة التي تتعلق بالاستعلام عن قاعدة البيانات (بشكل رئيسي تحت MySQL):

عند إنشاء التطبيقات التي تضع البيانات على قاعدة بيانات هي mysql_real_escape_string والتحقق العام (is_numeric etc) على بيانات الإدخال بما فيه الكفاية؟ ماذا عن الأنواع الأخرى من الهجمات المختلفة عن حقن SQL.

هل يمكن لشخص ما أن يشرح الإجراءات المخزنة والبيانات المعدة مع معلومات أكثر قليلاً من - يمكنك إجراء مكالمات لهم. أود أن أعرف كيف يعملون ، ما هو التحقق من صحة الكواليس.

أنا أعمل في بيئة ملزمة PHP4 و PHP5 ليس خيارًا في الوقت الحالي. هل كان أي شخص آخر في هذا الموضع من قبل ، ماذا فعلت لتأمين تطبيقاتك بينما يستخدم جميع الأطفال الرائعين واجهة MySqli الجديدة الحلوة؟

ما هي بعض الممارسات الجيدة العامة التي وجدها الناس أنها مفيدة ، والتأكيد على إنشاء بنية تحتية قادرة على تحمل الترقيات والهجرات المحتملة (مثل نقل PHP4 إلى PHP5).

ملاحظة: لم تتمكن البحث من البحث عن أي شيء مشابه لهذا والذي ضرب أمان PHP-MySQL.

هل كانت مفيدة؟

المحلول

توصياتي:

  1. Ditch mysqli لصالح PDO (مع سائق MySQL)
  2. استخدم عبارات محضرة pdo paremeter

يمكنك بعد ذلك فعل شيء مثل:

$pdo_obj = new PDO( 'mysql:server=localhost; dbname=mydatabase', 
                    $dbusername, $dbpassword );

$sql = 'SELECT column FROM table WHERE condition=:condition';
$params = array( ':condition' => 1 );

$statement = $pdo_obj->prepare( $sql, 
    array( PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY ) );
$statement->execute( $params );
$result = $statement->fetchAll( PDO::FETCH_ASSOC );

الايجابيات:

  1. لا مزيد من الهروب اليدوي لأن PDO يفعل كل شيء بالنسبة لك!
  2. من السهل نسبيًا تبديل الإرشاد في قاعدة البيانات فجأة.

سلبيات:

  • لا أستطيع التفكير في أي.

نصائح أخرى

إجابة خافيير التي لديها رابط OWASP هي بداية جيدة.

هناك بعض الأشياء الأخرى التي يمكنك القيام بها أكثر:

  1. فيما يتعلق بهجمات حقن SQL ، يمكنك كتابة وظيفة تقوم بإزالة عبارات SQL الشائعة من المدخلات مثل "Drop" أو "Delete * Where" ، مثل هذا:

    * $ sqlarray = array ("Drop" ، "أو 1 = 1" ، "Union Select" ، "Select * من" ، "Select Host" ، "Create Table" ، "من المستخدمين" ، "المستخدمين") ؛ * * *

    ثم اكتب الوظيفة التي ستتحقق من المدخلات الخاصة بك مقابل هذه الصفيف. تأكد من أن أي من الأشياء الموجودة داخل $ sqlarray لن تكون مدخلات شائعة من المستخدمين. (لا تنس استخدام Strtolower على هذا ، شكرًا لو).

  2. لست متأكدًا مما إذا كان Memcache يعمل مع PHP 4 ولكن يمكنك وضع بعض حماية البريد العشوائي مع MemcAche فقط من خلال السماح فقط بوصول IP عن بُعد إلى Process.php Page X Times of y time time.

  3. الامتيازات مهمة. إذا كنت بحاجة فقط إلى إدراج امتيازات (على سبيل المثال ، معالجة الطلب) ، فيجب عليك تسجيل الدخول إلى قاعدة البيانات في صفحة عملية الطلب مع مستخدم يحتوي فقط على إدراج وربما تحديد الامتيازات. هذا يعني أنه حتى إذا تم الحصول على حقن SQL ، فيمكنهم فقط إجراء استعلامات إدراج / اختيار وعدم حذف أو إعادة الهيكلة.

  4. ضع ملفات معالجة PHP مهمة في دليل مثل /تشمل. ثم عدم السماح لجميع وصول IPS إلى ذلك /تشمل الدليل.

  5. ضع MD5 المملح مع عامل المستخدم + Remoteip + ملحك في جلسة المستخدم ، وجعله يتحقق من كل صفحة من تحميل MD5 الصحيح في ملف تعريف الارتباط الخاص بهم.

  6. عدم السماح برؤوس معينة (http://www.owasp.org/index.php/testing_for_http_methods_and_xst). وضع pum (إذا لم تكن بحاجة إلى تحميل ملفات)/تتبع/توصيل/حذف الرؤوس.

لا أعمل عادةً مع PHP ، لذا لا يمكنني تقديم المشورة المستهدفة على وجه التحديد لمتطلباتك ، لكنني أقترح عليك إلقاء نظرة على صفحة OWASP ، وخاصة تقرير نقاط الضعف العشرة الأولى: http://www.owasp.org/index.php/top_10_2007

في تلك الصفحة ، لكل ضعف تحصل على قائمة بالأشياء التي يمكنك القيام بها لتجنب المشكلة في منصات مختلفة (.NET ، Java ، PHP ، إلخ)

فيما يتعلق بالبيانات المعدة ، فإنهم يعملون من خلال السماح لمحرك قاعدة البيانات بمعرفة عدد المعلمات والأنواع التي يمكن توقعها خلال استعلام معين ، باستخدام هذه المعلومات ، يمكن للمحرك أن يفهم الشخصيات التي هي جزء من المعلمة الفعلية وليس شيئًا يجب تحليله SQL مثل "(اقتباس واحد) كجزء من البيانات بدلاً من" كوحد السلسلة ". آسف ، لا يمكنني تقديم المزيد من المعلومات المستهدفة بـ PHP ، ولكن آمل أن يساعد ذلك.

AFAIK ، PHP/MYSQL لا تحتوي عادة على استعلامات معلمة.

استخدام sprintf() مع mysql_real_escape_string() يجب أن تعمل بشكل جيد. إذا كنت تستخدم سلاسل التنسيق المناسبة ل sprintf() (على سبيل المثال "٪ D" للأعداد الصحيحة) يجب أن تكون آمنًا جدًا.

قد أكون مخطئًا ، لكن لا ينبغي أن يكون كافيًا للاستخدام mysql_real_escape_string على المستخدم الذي قدمه البيانات؟

ما لم تكن أرقامًا ، في هذه الحالة ، يجب عليك التأكد من أنها في الواقع أرقام بدلاً من ذلك باستخدام على سبيل المثال ctype_digit أو is_numeric أو sprintf (استخدام %d أو %u لفرض المدخلات في رقم).

أيضًا ، وجود مستخدم MySQL Serarate لنصوص PHP الخاصة بك والذي يمكنه فقط تحديد وإدراج وتحديث وحذف على الأرجح فكرة جيدة ...


مثال من php.net

مثال #3 استعلام "أفضل الممارسات"

باستخدام mysql_real_escape_string () حول كل متغير يمنع حقن SQL. يوضح هذا المثال طريقة "أفضل الممارسات" للاستعلام عن قاعدة بيانات ، بغض النظر عن إعداد أسعار السحر.

سيتم تنفيذ الاستعلام الآن بشكل صحيح ، ولن تعمل هجمات حقن SQL.

   <?php
    if (isset($_POST['product_name']) && isset($_POST['product_description']) && isset($_POST['user_id'])) {
        // Connect

        $link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password');

        if(!is_resource($link)) {

            echo "Failed to connect to the server\n";
            // ... log the error properly

        } else {

            // Reverse magic_quotes_gpc/magic_quotes_sybase effects on those vars if ON.

            if(get_magic_quotes_gpc()) {
                $product_name        = stripslashes($_POST['product_name']);
                $product_description = stripslashes($_POST['product_description']);
            } else {
                $product_name        = $_POST['product_name'];
                $product_description = $_POST['product_description'];
            }

            // Make a safe query
            $query = sprintf("INSERT INTO products (`name`, `description`, `user_id`) VALUES ('%s', '%s', %d)",
                        mysql_real_escape_string($product_name, $link),
                        mysql_real_escape_string($product_description, $link),
                        $_POST['user_id']);

            mysql_query($query, $link);

            if (mysql_affected_rows($link) > 0) {
                echo "Product inserted\n";
            }
        }
    } else {
        echo "Fill the form properly\n";
    }

استخدم الإجراءات المخزنة لأي نشاط ينطوي على تجنب DB ، واستخدم معلمات الربط لجميع الاختيار.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top