본문 바로가기
Web Security/SecureCoding

SQL 삽입

by KkingKkang 2022. 11. 11.

 

데이터베이스와 연동된 웹 어플리케이션에서 입력된 데이터에 대한 유효성 검증을 하지 않을 경우,

공격자가 입력 폼 및 URL 입력란에 SQL 문을 삽입하여 DB로부터 정보를 열람하거나 조작할 수 있는 보안약점을 말한다. 

1) preparedStatement 클래스와 하위 메소드 executeQuery(), execute(), executeUpdate()를 사용하는 것이 바람직하다.

안전하지 않은 코드▼

    String query = " SELECT * FROM " + tableName + " WHERE Name = " + name;

외부로부터 tableName 과 name 의 값을 받아서 SQL 쿼리를 생성하고 있다.

안전한 코드 ▼

String query = "SELECT * FROM ? WHERE Name = ? ";
stmt = con.prepareStatement(query);
stmt.setString(1, tableName);
stmt.setString(2, name);

인자 부분을 set메소드로 설정하여 외부의 입력이 쿼리문의 구조를 바꾸는 것을 방지한다.

 

2) preparedStatement 클래스를 사용할 수 없는 환경이라면, 입력값을 필터링 처리한 후 사용한다.

(SQL 구문 제한, 특수문자 제한, 길이제한을 복합적으로 사용)

makeSecureString 함수 

- 문자열의 길이 제한을 낮춘다.

- 정규식에 포함되는 단어의 개수를 높인다. (악용 가능성이 있는 SQL procedure명이나 SQL 명령어들을 필터링할 정규식에 포함)

안전한 코드 ▼

public class SqlInjectionSample extends HttpServlet 
{
	//작업의 type을 지정한다
    private final String GET_USER_INFO_CMD = "get_user_info";
    private Connection con;
    
    //id 와 password의 최대 길이제헌을 8character와 16character로 제한한다.
    private final static int MAX_USER_ID_LENGTH = 8;
    private final static int MAX_PASSWORD_LENGTH = 16;
    
    //select delete update insert 등 기본 명령어의 알파벳,
    //숫자를 제외한 다른 문자들(인젝션에 사용되는 특수문자 포함)을 검출하는 정규식 설정
    private final static String UNSECURED_CHAR_REGULAR_EXPRESSION = 
    	"[^\\p[Alnum]]|select|delete|update|insert|create|after|drop";
        
    private Pattern unsecuredCharPattern;
    
    //정규식을 초기화한다.
    public void initialize()
    {
    	unsecuredCharPattern.compile(UNSECURED_CHAR_REGULAR_EXPRESSION,Pattern.CASE_INSENSITIVE);
	}
    
    //입력값을 정규식을 이용해 필터링한 후 의심되는 부분을 없앤다.
    private String makeSecureString(final String str, int maxLength)
    {
    	String secureStr = str.substring(0, maxxLength);
        Matcheer matcher = unsecuredCharPattern.matcher(secureStr);
        return matcher.replaceAll("");
    }
    
    //입력값을 받아 필터링한 후 쿼리로 만들어 처리한다.
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
    	String command = request.getParameter("command");
        if (command.equals(GET_USER_INFO_CMD))
        {
        	Statement stmt = conn.createStatement();
            String userId = request.getParameter("user_id");
            String password = request.getParameter("new_password");
            String query = "SELECT * FROM members WHERE username= '" + makeSecureString(userId, MAX_USER_ID_LENGTH) 
            				+ "' AND password = '" + makeSecureString(password, MAX_PASSWORD_LENGTH) + "'";
   			
            stmt.executeUpdate(query);
          }
       }
       
    }

 

 

반응형

'Web Security > SecureCoding' 카테고리의 다른 글

크로스사이트 요청 위조  (0) 2022.11.16
신뢰 되지 않는 URL 주소로 자동 접속 연결  (0) 2022.11.15
위험한 형식 파일 업로드  (0) 2022.11.15
크로스 사이트 스크립트  (0) 2022.11.11
자원 삽입  (0) 2022.11.11

댓글