sourcecode

Java - SQL 주입을 방지하는 이스케이프 문자열

copyscript 2023. 1. 10. 21:15
반응형

Java - SQL 주입을 방지하는 이스케이프 문자열

, " All" 함수java" anti sql injection을 사용하는 은 매우 .으로 기존의 모든 합니다.\로로 합니다.\\, any, any, any."로로 합니다.\", any, any, any.'로로 합니다.\'및 any , 「 」\n로로 합니다.\\nMySQL 주입에 의해 문자열이 평가될 때 차단되도록 합니다.

\\\\\\\\\\\눈알이 뒤집힐 것 같아요.이치노

Prepared Statements는 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 문에는 영향을 주지 않습니다.

데이터 유형마다 다른 설정 방법이 있으며, 사용하는 방법은 데이터베이스 필드에 따라 다릅니다.들어 INTEGER를 해야 .setInt방법.PreparedStatement 문서에는 데이터 설정 및 취득에 사용할 수 있는 모든 다양한 방법이 나열되어 있습니다.

SQL 주입을 방지하는 유일한 방법은 매개 변수화된 SQL을 사용하는 것입니다.SQL을 해킹해 생계를 유지하는 사람보다 똑똑한 필터를 구축하는 것은 불가능합니다.

따라서 모든 input, updates 및 where 구에 파라미터를 사용합니다.다이내믹 SQL은 단순히 해커에게 열려 있는 문으로, 스토어드 프로시저에 다이내믹 SQL이 포함되어 있습니다.매개 변수화, 매개 변수화, 매개 변수화

Defense Option 1: Prepared Statements (Parameterized Query) 또는 Defense Option 2: Stored Procedures를 사용할 수 없는 경우 OWASP Enterprise Security API를 사용하십시오.Google 코드에서 호스트되는 OWASP ESAPI에서:

보안 제어 장치를 직접 작성하지 마십시오!모든 웹 애플리케이션 또는 웹 서비스에 대한 보안 제어 기능을 개발하는 데 시간을 낭비하고 막대한 보안 취약점을 초래합니다.OWASP Enterprise Security API(ESAPI) 툴킷은 소프트웨어 개발자가 보안 관련 설계 및 구현 결함으로부터 보호할 수 있도록 지원합니다.

자세한 내용은 Java에서 SQL 주입 방지 및 SQL 주입 방지 치트시트참조하십시오.

OWASP ESAPI 프로젝트를 도입하는 Defense Option 3: 모든 사용자 제공 입력 탈출) 특히 주의하십시오.

(이것은 원래 질문에 대한 OP의 코멘트에 대한 답변입니다.Prepared Statement는 이 작업의 툴이지 정규식이 아닙니다.)

라고 말할 때\n 시퀀스 '''를 \+n니면면 실제 바? ???\+n작업은 매우 간단합니다.

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

입력의 1개의 백슬래시를 일치시키려면 그 중 4개를 regex 문자열에 넣습니다.출력에 백슬래시를 1개 넣으려면 그 중 4개를 치환 문자열에 넣습니다.이것은 정규식과 치환을 Java String 리터럴 형식으로 작성하는 것을 전제로 하고 있습니다.파일 읽기 등 다른 방법으로 작성하면 이중 이스케이프를 수행할 필요가 없습니다.

입력에 라인피드 문자가 있고 이를 이스케이프 시퀀스로 대체하려는 경우 다음과 같이 입력 위로 두 번째 패스를 만들 수 있습니다.

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

또는 두 개의 백슬래시를 원할 수도 있습니다(그 점은 잘 모르겠습니다).

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

Prepared Statements는 대부분의 경우에 사용할 수 있지만, 모든 경우에 사용할 수 있는 것은 아닙니다.쿼리 또는 그 일부를 나중에 사용하기 위해 작성 및 문자열로 저장해야 하는 상황에 처할 수 있습니다.OWASP 사이트SQL Injection Prevention 치트시트에서 다양한 프로그래밍 언어로 된 API를 참조하십시오.

정규 표현을 사용하여 SQL 주입의 원인이 될 수 있는 텍스트를 삭제하는 것은 SQL 문이 가 아닌 를 통해 데이터베이스로 전송되는 것처럼 들립니다.

중 는 SQL 주입을 입니다.PreparedStatement플레이스 홀더를 사용하여 SQL 문을 대체할 데이터를 받아들이기 때문에 데이터베이스로 전송할 SQL 문을 만들기 위해 문자열 연결에 의존하지 않습니다.

자세한 내용은 Java 튜토리얼의 준비스테이트먼트를 사용하는 것이 좋습니다.

준비된 스테이트먼트가 가장 좋은 해결책이지만 수동으로 해야 하는 경우에는 Apache Commons-Lang 라이브러리의 클래스를 사용할 수도 있습니다.다음과 같은 방법을 사용할 수 있습니다.

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

아래 코드가 필요합니다.언뜻 보면, 이것은 내가 만든 오래된 코드처럼 보일지도 모른다.다만, http://grepcode.com/file/repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.31/com/mysql/jdbc/PreparedStatement.java의 소스 코드를 확인했습니다.그 후 setString(int 파라미터)의 코드를 주의 깊게 살펴보았습니다.Index, String x)를 사용하면 이스케이프되는 문자를 찾아 원하는 용도로 사용할 수 있도록 내 클래스에 맞춤화할 수 있습니다.이것이 Oracle이 이스케이프하는 문자 목록이라면 보안 측면에서 이 사실을 아는 것이 매우 편리합니다.Oracle은 다음 주요 Java 릴리즈에 이와 유사한 메서드를 추가하기 위해 약간의 힌트가 필요할 수 있습니다.

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();
    }
}

시스템을 하고 있는 전환 PreparedStatement너무 짧은 시간 안에 - 즉, 다른 답변이 제안하는 베스트 프랙티스를 사용하는 데 장애가 있는 경우 AntiSQ를 사용해 보십시오.LFilter(LFilter)

하고 있습니다.PreparedStatements.그러나 보안 문제로 인해 데이터베이스에 직접 접속하지 말고 Restful API를 사용하여 쿼리를 처리해야 한다고 다른 모든 사용자가 말합니다.

제 생각에는 탈출할 때 조심하고 의도적으로 해야 한다는 것을 알고 있으면 문제가 없을 것 같습니다.

의 은 ★★★★★★★★★★★★★를 사용하고 있다.contains()합니다.UPDATE한 문자, 예를 들어 '하다', '하다', '하다', '하다', '하다', '하다', '다'와 같은 위험한 문자.=입력 시 다른 문자를 삽입하도록 사용자에게 요청하여 SQL 주입을 완전히 비활성화합니다.

편집: Java 정규 표현에 대한 W3 Schools의 이 소스 자료를 사용하여 문자열에서 이 검증을 수행할 수 있습니다.

sqlmap의 sql injection을 방지하기 위해 솔루션 테스트를 많이 검색한 후 준비된 statement를 어디에나 적용할 수 없는 레거시 시스템의 경우.

java-security-cross-site-scripting-xss-and-sql-injection 토픽이 솔루션이었습니다.

@Richard의 솔루션을 시도했지만 내 경우에는 작동하지 않았습니다.나는 필터를 사용했다.

이 필터의 목적은 요구를 자체 코드화된 래퍼 MyHttpRequestWrapper로 래핑하는 것입니다.이러한 래퍼 MyHttpRequestWrapper는 다음을 변환합니다.

org.springframework.web.util을 통해 특수문자(<, >, ', ...)를 포함한 HTTP 파라미터를 HTML 코드로 변환합니다.HtmlUtils.htmlEscape(…) 메서드.주의: Apache Commons: org.apache.commons.lang에도 유사한 classe가 있습니다.Apache Commons classe org.apache.commons.lang을 통해 SQL 주입 문자( , " , ... )를 StringEscapeUtils.escapeHtml(…)로 지정합니다.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;
    }
}

PL/SQL을 사용하는 경우DBMS_ASSERTSQL 주입에 대한 걱정 없이 사용할 수 있도록 입력을 삭제할 수 있습니다.

예를 들어 다음 답변을 참조하십시오.https://stackoverflow.com/a/21406499/1726419

송신원: 송신원

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;
}

먼저 사용자 입력 필드에 큰따옴표 또는 작은따옴표 또는 백슬래시가 필요합니까?라는 질문을 합니다.

백슬래시 - 아니요큰따옴표와 작은따옴표는 영어에서 거의 사용되지 않고 영국에서는 미국과 다르게 사용된다.

제거하거나 교체하면 단순해집니다.

private String scrub(
    String parameter,
    int    length
    )
{
    String parm = null;

    if ( parameter != null && parameter.length() > 0 && parameter.length() < length )
    {
        parm = parameter
            .replace( "\\", " " )
            .replace( "\"", " " )
            .replace( "\'", " " )
            .replace( "\t", " " )
            .replace( "\r", " " )
            .replace( "\n", " " )
            .trim();
    }

    return parm;
}

언급URL : https://stackoverflow.com/questions/1812891/java-escape-string-to-prevent-sql-injection

반응형