2014-09-15 2 views
0

기존 Java 웹 응용 프로그램의 보안 수정 작업을하고 있습니다. 응용 프로그램에는 JDBC에 의해 실행되는 일부 동적 SQL 코드가 있지만, 우리가 사용하는 정적 코드 분석 도구에서는 허용되지 않습니다. 그래서, 문제를 해결할 수있는 방법을 찾고 있습니다. 기본적으로 쿼리를 생성하는 코드에 전달 된 모든 입력을 검증 했으므로 SQL 삽입의 가능성은 없습니다. 그러나 SCA 도구는 여전히이 유효성 검사를 승인하지 않습니다. 따라서 동적 쿼리 로직을 피할 수있는 방법이 있는지 알고 싶습니다. 쿼리는 조건에 따라 동적으로 생성되므로 Prepared Statements를 사용할 수 없습니다.동적 SQL 코드를 사용할 때 SQL 주입을 피하십시오.

저장 프로 시저가 도움이된다는 것을 알고 있습니다. 그러나 자체적 인 문제가 있으며 팀도 Stored Procedures에 경험이 없다는 것을 알고 있습니다. 따라서이 문제를 해결할 수있는 더 나은 방법을 찾고 있습니다. 또한 SQL Server를 사용하고 있기 때문에 ESAPI 툴킷에서 오라클과 MySQL 만 지원하는 쿼리 매개 변수를 암호화하기위한 인코딩 기능을 찾지 못했습니다.

SQL을 XML 파일로 생성하는 java 코드를 Mybatis와 같은 프레임 워크를 사용하여이 문제를 해결할 수 있는지 알고 싶으십니까? 다른 사람들에게 더 좋은 방법이 있는지 알려 주실 수 있습니까?

+0

코드가 인젝션 증거인 것으로 확인되면 동적 값을 "검증"할 수있는 방법이 없습니다. 쿼리를 매개 변수화해야합니다. –

+0

여러 질문을하고 있는데 SCA 도구에 대한 질문은 내가 한 번도 해본 적이없는 단서를 가지고있다. 동적 SQL 제거에 대한 질문은 더 많은 정보가 필요합니다. 동적 SQL은 무엇을합니까? 마지막으로 QUOTENAME을 사용하여 소싱 입력을 어느 정도 수행 할 수 있습니다. 이것이 충분하지 않으면 모든 신체 구멍에서 나올 때까지 중첩 된 대체물로 불쾌한 udf를 만들 수 있습니다. – Tristan

+0

나는 팀을 위해 SQL에 대한 훈련을 받기를 제안한다. 이를 처리하는 가장 좋은 방법은 저장 프로 시저입니다. 그리고 그것은 약간의 분리를 제공합니다. 모든 SQL이 코드 내에 포함되어 있다면 추상화 레이어를 작성하여 코드가 더 쉽게 작업 할 수 있도록해야합니다. –

답변

1

동적으로 SQL을 생성하고 준비된 문을 사용할 수 있습니다.

이것이 어떻게 수행 될 수 있는지 생각해보십시오.

StringBuilder whereClause = new StringBuilder(); 


if (name != null) { 
    whereClause.append(String.format("name = '%s'", name)); 
} 

// other similar conditions 

String sql = "select * from table" + (whereClause.length() != 0 ? "where " + whereClause.toString() : ""); 

Statement stmt = connection.createStatement(); 

ResultSet rs = stmt.executeQuery(sql); 

// use rs to fetch data 

그리고 당신은 다음과 같아야합니다

StringBuilder whereClause = new StringBuilder(); 
ArrayList<Object> parameters = new ArrayList<>(); 

if (name != null) { 
    whereClause.append("name = ?"); 
    parameters.add(name); 
} 

// other similar conditions 

String sql = "select * from table" + (whereClause.length() != 0 ? "where " + whereClause.toString() : ""); 

PreparedStatement stmt = connection.prepareStatement(); 

for (int i = 0; i < parameters.length(); ++i) { 
    setParameterValue(stmt, i + 1, parameter.get(i)); 
} 

ResultSet rs = stmt.executeQuery(sql); 

// use rs to fetch data 

setParameterValue처럼 뭔가로 변경해야합니다 : 지금 당신은 다음과 같은 코드를 MyBatis로와

void setParameterValue(PreparedStatement ps, int index, Object value) { 
    if (value instanceof String) { 
     ps.setString(index, (String)value); 
    } if (value instanceof Integer) { 
     ps.setInt(index, (Integer)value); 
    } // and more boilerplate code like this for all types you need 
} 

당신 can 피하기 쓰기 이러한 보일러 플레이트 코드는 동적 SQL을 생성하고이를 훨씬 쉽게 만듭니다. 그러나 CSA가 mybatis가 SQL을 처리하는 방법을 알지 못합니다.

0

비슷한 문제를 직접 해결하는 동안이 질문을 발견했습니다.

먼저 자바 코드에서 SQL 코드를 분석하여 리소스 폴더 아래의 텍스트 파일에 저장할 수 있습니다. 그런 다음 java 코드에서 classloader의 메서드를 사용하여 sql을 inputStream으로 읽고 String으로 변환합니다. SQL 코드를 별도의 파일에 저장하면 통계 코드 분석이 가능합니다.

둘째, sql에서 명명 된 매개 변수를 정규식을 통해 쉽게 인식 할 수있는 형식으로 사용할 수 있습니다. 예 : $ {namedParam} 구문은 다른 표현식 언어에 익숙합니다. 그런 다음이 매개 변수가있는 SQL 및 Map<String, Object>을 쿼리 매개 변수로 사용하는 도우미 메서드를 작성할 수 있습니다. 이 맵의 키는 sql 매개 변수 이름과 일치해야합니다. 이 헬퍼 메소드는, set 파라미터로 PreparedStatement를 생성합니다. 명명 된 매개 변수를 사용하면 sql 코드가 더 읽기 쉽고 디버깅을 줄일 수 있습니다.

셋째, 마지막으로 sql 코드의 일부를 일부 매개 변수의 존재 여부에 따라 표시 할 수 있습니다. 그리고 이전에 설명 된 도우미 메서드에서 사용하여 매개 변수 Map의 항목이있는 결과 문장에만 포함합니다. 예 : /*${namedParam}[*/ some sql code /*]${namedParam}*/. 이것은 동적 SQL에 조건을 삽입하는 눈에 거슬리는 방법 일 것입니다.

DRY 원칙에 따라 기존의 표현식 엔진을 사용하려고 할 수도 있지만, 종속성과 처리 비용이 한 가지 더 늘어납니다.

작업 코드를 얻으면 여기에 해결책을 게시 할 것입니다.