سؤال

وأنا أحاول أن أضع بعض الحقن المضادة مزود المعمول بها في جافا، وأنا تجد صعوبة جدا للعمل مع وظيفة "replaceAll" السلسلة. في النهاية انا بحاجة الى وظيفة التي سيتم تحويل أي \ القائمة ل\\، أي " إلى \"، أي ' إلى \'، وأي \n إلى \\n بحيث عندما يتم تقييم سلسلة من الحقن الخلية SQL سيتم حظر.

ولقد رفعوا بعض التعليمات البرمجية كنت أعمل مع وكل \\\\\\\\\\\ في وظيفة وجعل عيني الذهاب المكسرات. إذا كان أي شخص يحدث أن يكون مثالا لهذا أود أن نقدر ذلك.

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

المحلول

وPreparedStatements هي وسيلة للذهاب، لأنها تجعل حقن SQL مستحيلا. وإليك مثال بسيط أخذ إدخال المستخدم كمعلمات:

public insertUser(String name, String email) {
   Connection conn = null;
   PreparedStatement stmt = null;
   try {
      conn = setupTheDatabaseConnectionSomehow();
      stmt = conn.prepareStatement("INSERT INTO person (name, email) values (?, ?)");
      stmt.setString(1, name);
      stmt.setString(2, email);
      stmt.executeUpdate();
   }
   finally {
      try {
         if (stmt != null) { stmt.close(); }
      }
      catch (Exception e) {
         // log this error
      }
      try {
         if (conn != null) { conn.close(); }
      }
      catch (Exception e) {
         // log this error
      }
   }
}

وبغض النظر عن الشخصيات هي في الاسم والبريد الإلكتروني، وسيتم وضع تلك الأحرف مباشرة في قاعدة البيانات. أنها لن تؤثر على بيان INSERT بأي شكل من الأشكال.

وهناك طرق مجموعة مختلفة لأنواع البيانات المختلفة - أي واحد منكم استخدام هذا يتوقف على ما هي حقول قاعدة البيانات الخاصة بك. على سبيل المثال، إذا كان لديك عمود عدد صحيح في قاعدة البيانات، يجب عليك استخدام أسلوب setInt. rel="noreferrer"> يسرد كافة الأساليب المختلفة المتاحة لوضع والحصول على البيانات.

نصائح أخرى

والطريقة الوحيدة لمنع حقن SQL هي مع SQL معلمات. انها ببساطة غير ممكن لبناء مصفاة هذا أذكى من الناس الذين الإختراق SQL أجل لقمة العيش.

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

إذا حقا لا يمكنك استخدام <لأ href = "http://www.owasp.org/index.php/SQL٪5FInjection٪5FPrevention٪5FCheat٪5FSheet#Defense_Option_1:_Prepared_Statements_.28Parameterized_Queries.29" يختلط = " noreferrer "> خيار الدفاع 1: تحضير بيانات (معلمات استعلامات) أو الدفاع الخيار 2: إجراءات مخزنة ، لا بناء أداة الخاصة بك، استخدم OWASP المؤسسة الأمن API . من OWASP ESAPI استضافتها على مدونة جوجل:

<اقتباس فقرة>   

لا تكتب الضوابط الأمنية الخاصة! إعادة اختراع العجلة عندما يتعلق الأمر ضوابط أمنية النامية من أجل كل تطبيق ويب أو خدمة ويب يؤدي إلى إهدار الوقت والثغرات الأمنية واسعة النطاق. وAPI OWASP المؤسسة الأمن (ESAPI) مجموعة أدوات تساعد المطورين برنامج حماية ضد تصميم وتنفيذ العيوب المتعلقة بالأمن.

لمزيد من التفاصيل، انظر منع حقن SQL في جاوة و <لأ href = " http://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet "يختلط =" noreferrer "> SQL حقن منع الغش ورقة .

ودفع اهتماما خاصا ل الدفاع الخيار 3: الهروب جميع العضو الموردة الإدخال أن يدخل OWASP ESAPI المشروع).

(وهذا هو ردا على تعليق OP تحت السؤال الأصلي، وأنا أتفق تماما أن PreparedStatement هو أداة لهذه المهمة، وليس regexes)

وعندما تقول \n، هل يعني تسلسل \ + n أو حرف تغذية الفعلي؟ اذا كان \ + n، والمهمة هي جميلة واضحة:

s = s.replaceAll("['\"\\\\]", "\\\\$0");

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

إذا كان لديك حرف تغذية في المدخلات وتريد استبدالها تسلسل هروب، يمكنك جعل تمريرة الثاني على المدخلات مع هذا:

s = s.replaceAll("\n", "\\\\n");

وأو ربما كنت ترغب اثنين الخطوط المائلة العكسية (أنا لست واضحة جدا على ذلك):

s = s.replaceAll("\n", "\\\\\\\\n");

وPreparedStatements هي وسيلة للذهاب في معظم، ولكن ليس كل الحالات. في بعض الأحيان سوف تجد نفسك في الحالة التي تكون فيها استعلام، أو جزء منه، وسيتم بناؤها وتخزينها كسلسلة لاستخدامها لاحقا. تحقق من SQL حقن منع الغش ورقة على في الموقع OWASP لمزيد من التفاصيل واجهات برمجة التطبيقات في لغات البرمجة المختلفة.

<ع> استخدام تعبير عادي لإزالة النص الذي يمكن أن يسبب حقن SQL يبدو وكأنه يتم إرسال بيان SQL إلى قاعدة البيانات عن طريق <لأ href = "http://java.sun.com/javase/6/docs/ المعهد / جافا / SQL / Statement.html "يختلط =" noreferrer "> Statement بدلا من <لأ href =" http://java.sun.com/javase/6/docs/api/java/sql /PreparedStatement.html "يختلط =" noreferrer "> PreparedStatement .

واحدة من أسهل الطرق لمنع حقن SQL في المقام الأول هو استخدام PreparedStatement، الذي يقبل البيانات لتحل محل في بيان SQL باستخدام العناصر النائبة، التي لا تعتمد على تسلسالت سلسلة لإنشاء عبارة SQL لإرسالها إلى قاعدة البيانات.

لمزيد من المعلومات، عن طريق تحضير بيانات من جافا دروس سيكون مكان جيد للبدء.

وتحضير بيانات هي الحل الأفضل، ولكن إذا كنت حقا بحاجة للقيام بذلك يدويا هل يمكن أيضا استخدام في StringEscapeUtils الطبقة من المكتبة أباتشي العموم لانغ. أنه يحتوي على <لأ href = "https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringEscapeUtils.html#escapeSql(java.lang.String) "يختلط =" noreferrer "> طريقة escapeSql(String) ، والتي يمكنك استخدامها:

وimport org.apache.commons.lang.StringEscapeUtils; … String escapedSQL = StringEscapeUtils.escapeSql(unescapedSQL);

في حال كنت تتعامل مع النظام القديم، أو كان لديك العديد من الأماكن للتبديل إلى PreparedStatements في وقت قصير جدا - أي إذا كان هناك عقبة أمام استخدام أفضل الممارسات التي اقترحتها إجابات أخرى، يمكنك محاولة <لأ href = "http://sourceforge.net/projects/antisqlfilter/" يختلط = "noreferrer"> AntiSQLFilter

وتحتاج إلى رمز التالية أدناه. في لمحة، وهذا قد تبدو مثل أي القانون القديم الذي أدليت به حتى. ومع ذلك، ما فعلته كان نظرة على شفرة المصدر ل <لأ href = "http://grepcode.com/file/repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.31/com/mysql /jdbc/PreparedStatement.java "يختلط =" noreferrer "> http://grepcode.com/file/repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.31/com/mysql/jdbc/PreparedStatement . JAVA . ثم بعد ذلك، نظرت بعناية من خلال مدونة setString (الباحث parameterIndex، سلسلة س) للعثور على الأحرف التي يهرب وتخصيص هذا إلى الصف بلدي بحيث يمكن استخدامها لأغراض التي تحتاج إليها. بعد كل شيء، إذا كان هذا هو قائمة من الشخصيات التي يهرب أوراكل، ثم معرفة هذا من الناحية الأمنية مريح حقا. ربما أوراكل بحاجة إلى دفعة لإضافة طريقة مشابهة لهذه واحدة من أجل إطلاق سراح جافا الرئيسي القادم.

public class SQLInjectionEscaper {

    public static String escapeString(String x, boolean escapeDoubleQuotes) {
        StringBuilder sBuilder = new StringBuilder(x.length() * 11/10);

        int stringLength = x.length();

        for (int i = 0; i < stringLength; ++i) {
            char c = x.charAt(i);

            switch (c) {
            case 0: /* Must be escaped for 'mysql' */
                sBuilder.append('\\');
                sBuilder.append('0');

                break;

            case '\n': /* Must be escaped for logs */
                sBuilder.append('\\');
                sBuilder.append('n');

                break;

            case '\r':
                sBuilder.append('\\');
                sBuilder.append('r');

                break;

            case '\\':
                sBuilder.append('\\');
                sBuilder.append('\\');

                break;

            case '\'':
                sBuilder.append('\\');
                sBuilder.append('\'');

                break;

            case '"': /* Better safe than sorry */
                if (escapeDoubleQuotes) {
                    sBuilder.append('\\');
                }

                sBuilder.append('"');

                break;

            case '\032': /* This gives problems on Win32 */
                sBuilder.append('\\');
                sBuilder.append('Z');

                break;

            case '\u00a5':
            case '\u20a9':
                // escape characters interpreted as backslash by mysql
                // fall through

            default:
                sBuilder.append(c);
            }
        }

        return sBuilder.toString();
    }
}

وبعد البحث والكثير اختبار الحل لمنع sqlmap من حقن SQL، في حالة من النظام القديم الذي غير قادر على تطبيق مستعدة statments في كل مكان.

جافا الأمنية العابرة لل البرمجة-موقع-XSS و-SQL الحقن الموضوع وكان الحل

وحاولت حلRichard الصورة ولكن لم ينجح في حالتي. أنا استخدم مرشح

<اقتباس فقرة>   

والهدف من هذا الفلتر هو إزار طلب إلى ترميز خاص،   المجمع MyHttpRequestWrapper التي تحول:

     

والمعلمات HTTP مع أحرف خاصة (<،>، '، ...) إلى HTML   رموز عبر org.springframework.web.util.HtmlUtils.htmlEscape (...)   طريقة، أسلوب. ملاحظة: هناك كلاسي مماثل في العموم أباتشي:   org.apache.commons.lang.StringEscapeUtils.escapeHtml (...) وSQL   الأحرف حقن ( ' "، ...) عبر أباتشي العموم كلاسي   org.apache.commons.lang.StringEscapeUtils.escapeSql (...)

<filter>
<filter-name>RequestWrappingFilter</filter-name>
<filter-class>com.huo.filter.RequestWrappingFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>RequestWrappingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>




package com.huo.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletReponse;
import javax.servlet.http.HttpServletRequest;

public class RequestWrappingFilter implements Filter{

    public void doFilter(ServletRequest req, ServletReponse res, FilterChain chain) throws IOException, ServletException{
        chain.doFilter(new MyHttpRequestWrapper(req), res);
    }

    public void init(FilterConfig config) throws ServletException{
    }

    public void destroy() throws ServletException{
    }
}




package com.huo.filter;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.lang.StringEscapeUtils;

public class MyHttpRequestWrapper extends HttpServletRequestWrapper{
    private Map<String, String[]> escapedParametersValuesMap = new HashMap<String, String[]>();

    public MyHttpRequestWrapper(HttpServletRequest req){
        super(req);
    }

    @Override
    public String getParameter(String name){
        String[] escapedParameterValues = escapedParametersValuesMap.get(name);
        String escapedParameterValue = null; 
        if(escapedParameterValues!=null){
            escapedParameterValue = escapedParameterValues[0];
        }else{
            String parameterValue = super.getParameter(name);

            // HTML transformation characters
            escapedParameterValue = org.springframework.web.util.HtmlUtils.htmlEscape(parameterValue);

            // SQL injection characters
            escapedParameterValue = StringEscapeUtils.escapeSql(escapedParameterValue);

            escapedParametersValuesMap.put(name, new String[]{escapedParameterValue});
        }//end-else

        return escapedParameterValue;
    }

    @Override
    public String[] getParameterValues(String name){
        String[] escapedParameterValues = escapedParametersValuesMap.get(name);
        if(escapedParameterValues==null){
            String[] parametersValues = super.getParameterValues(name);
            escapedParameterValue = new String[parametersValues.length];

            // 
            for(int i=0; i<parametersValues.length; i++){
                String parameterValue = parametersValues[i];
                String escapedParameterValue = parameterValue;

                // HTML transformation characters
                escapedParameterValue = org.springframework.web.util.HtmlUtils.htmlEscape(parameterValue);

                // SQL injection characters
                escapedParameterValue = StringEscapeUtils.escapeSql(escapedParameterValue);

                escapedParameterValues[i] = escapedParameterValue;
            }//end-for

            escapedParametersValuesMap.put(name, escapedParameterValues);
        }//end-else

        return escapedParameterValues;
    }
}

ومن: [المصدر]

public String MysqlRealScapeString(String str){
  String data = null;
  if (str != null && str.length() > 0) {
    str = str.replace("\\", "\\\\");
    str = str.replace("'", "\\'");
    str = str.replace("\0", "\\0");
    str = str.replace("\n", "\\n");
    str = str.replace("\r", "\\r");
    str = str.replace("\"", "\\\"");
    str = str.replace("\\x1a", "\\Z");
    data = str;
  }
return data;

و}

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