sub_title
 개발자마당
제   목 SQL Injection
작성자 고구마 등록일 2017-04-29 18:18:51 조회수 20,986

※ 크롬, 오페라 등 브라우저는 인터넷 익스플로러와 비교해 구현 방법에 차이가 있다.

같은 html 문서를 작성해도 브라우저에 따라 결과가 다를 수 있다는 말이다.

보안 포스팅을 위해 문제 상황을 발생시키기에 인터넷 익스플로러가 적합해 보안 포스팅에서는 항상 인터넷 익스플로러를 실습 브라우저로 사용한다.


 


CWE 는 Common Weakness Enumeration의 약어를 가진 미 산하 기관이 운영하는 사이트로


- 웹 개발시 취약점에 대한 정의, 설명, 해당 취약점의 플랫폼, 빈도 및 예제코드, 완화방법 기술 등을 참고할 수 있는 사이트이다. 개발을 업으로 삼는다면 PL이나 PM이 되고 나서야 참고할 일이 있을만한 사이트이다. CWE에서는 웹 보안을 위해 반드시 지켜야 할 사례들을 리스트로 구분해뒀는데 그중 가장 대표적인 하나가 SQL / Command Injection이다.

Injection은 Form이 있으면 언제든 시도할 수 있는 공격기법으로. 동적 SQL문 사용하는 경우 입력에 쿼리문 삽입시켜 계정이 없더라도 로그인 및 테이블에 대한 정보를 추출할 수 있는 기법이다.


가장 대표적인 예가 로그인시 Id입력이 가능한 경우이다.
 

@Override public
 MemberVO login(LoginVO loginVO) {
  Connection conn = null;
  Statement stmt = null;
  ResultSet rs = null;
//FIXME SQLInjection 방어하기
  String query = " SELECT USER_ID, USER_NAME, USER_PASSWORD "
                      + "FROM USERS WHERE USER_ID = '" + loginVO.getId() + "' AND USER_PASSWORD = '" + loginVO.getPassword() + "'";

  try {
   conn = dataSource.getConnection();
    stmt = conn.createStatement();
   rs = stmt.executeQuery(query);
   MemberVO memberVO = null;
if(rs.next()) {
    memberVO = new MemberVO();
    memberVO.setId(rs.getString(1));
    memberVO.setUserName(rs.getString(2));
    memberVO.setPassword(rs.getString(3));
}
   return memberVO; }
  catch(SQLException sqle) {
   throw new RuntimeException(sqle.getMessage(), sqle);
}
  finally { DBCloseUtil.close(conn, stmt, rs);
  }
 }

2000년대 초반 로그인 기능의 Dao 클래스. Statement 객체를 사용하고 있다.

※ 데이터베이스에는 id : admin / password : admin의 유저 하나만 등록된 상태이다.
- 다음과 같이 로그인을 할 때 아이디 뒤에 '를 붙인 후 -- 를 입력한 후 비밀번호는 틀린 것으로 입력한다. admin 계정의 경우 password 또한 5자이기 때문에 6자를 입력하면 로그인이 실패해야 하지만 완료되고, 이후 사이트의 페이지들에 접근이 가능해진다. 어떤 이유일까?

로그인 Dao의 쿼리문을 볼 수 있도록 사이트를 제작했다. 아이디와 비밀번호를 맞게 입력한 경우 인증성공이라고 나온다.

다른 비밀번호 (11111)을 입력한 경우 인증 실패가 출력된다.

admin'--을 입력한 순간의 실행 쿼리문을 보면 USER_ID 칼럼만 확인 후 닫아버리고 -- 를 통해 이후 부분을 주석화 시키는 것이다. 따라서 아래 AND 조건을 확인하지 않는 것이다. 이를 응용하면

다음과 같이 or 로 항상 참인 명제를 넣으면 아이디조차 몰라도 접근이 가능해진다.


Dao코드에서 Statement 객체를 사용하면 이러한 SQL Injection을 피할 수 없다. 오라클에서는 이를 극복하기 위해 PreparedStatement를 제공해 -- 를 주석이 아닌 Text로 인식하도록 처리를 해 보안성을 강화한다. 따라서 Dao 코드는 다음과 같이 변경되어야 한다.

 

@Override
public MemberVO login(LoginVO loginVO) {
  Connection conn = null;
PreparedStatement stmt = null;
  ResultSet rs = null;
//FIXME SQLInjection 방어하기
  String query = " SELECT USER_ID, USER_NAME, USER_PASSWORD "
    + " FROM USERS WHERE USER_ID = ? AND USER_PASSWORD = ? ";
try {
   conn = dataSource.getConnection();
   stmt = conn.prepareStatement(query);
   stmt.setString(1, loginVO.getId()); stmt.setString(2, loginVO.getPassword());
rs = stmt.executeQuery(); MemberVO memberVO = null;
if(rs.next()) {
    memberVO = new MemberVO();
    memberVO.setId(rs.getString(1));
    memberVO.setUserName(rs.getString(2));
    memberVO.setPassword(rs.getString(3)); }

return memberVO;
}
  catch(SQLException sqle) {
throw new RuntimeException(sqle.getMessage(), sqle);
}
finally {
   DBCloseUtil.close(conn, stmt, rs);
}
}

 개선된 Dao 클래스. PreparedStatement를 사용해 보안성을 강화했다. 다음과 같이 코드를 수정하면

외부에서 쿼리문을 임의로 수정할 수 없어 SQL Injection을 방어할 수 있다.

 


 
0
    
 
0
        list
 
※ 짧은 댓글일수록 예의를 갖추어 작성해 주시기 바랍니다.
line
reply cancel
 
번호 제목 글쓴이 추천 조회 날짜
31  자바(Java) 외부 프로젝트 공유(Share) 하기 이미지   member 고구마 0 / 0 1821 2017-04-29
30  SQL Injection 이미지   member 고구마 0 / 0 20986 2017-04-29
29  (JAVA) 자바 리터럴(Literal) 의미와 용도 이미지   member 고구마 0 / 0 2644 2017-04-28
28  (JAVA) 자바 상수 (final) 사용이유와 방법 이미지   member 고구마 0 / 0 2007 2017-04-28
27  (JAVA) 자바 스캐너(Scanner)로 파일 내용 읽어오기 이미지   member 고구마 0 / 0 4253 2017-04-28
26  리눅스 환경에 설치된 톰캣 재시작하기 이미지   member 높이뜬새 2 / 1 12518 2015-10-27
25  다음과 같은 에러가 발생할때 write failed: No space left on device (28) in Unknown on lin..   member 높이뜬새 1 / 1 4350 2015-07-09
24  sendmail 시작 재시작 종료하기   member 높이뜬새 0 / 0 4687 2015-06-29
23  find 명령어로 찾을 문자열이 들어간 파일찾기   member 컴퓨터존 3 / 0 19854 2010-03-04
22  아파치 재시작 없이 로그 삭제하기   member 컴퓨터존 0 / 0 18454 2010-03-04
21  IIS에서 FLV파일 MIME 타입 등록하기 이미지   admin 웹마당넷 1 / 0 12071 2009-11-27
20  동영상 트래픽 계산하기   member 컴퓨터존 0 / 0 10933 2009-11-18
19  리눅스계정 생성과 삭제 이미지   member 높이뜬새 0 / 0 8576 2009-08-26
18  리눅스에서 tar를 이용한 계정백업하기 이미지   member 높이뜬새 0 / 0 6099 2009-08-22
17  php파일로 실행될 확장자 추가하기   member 컴퓨터존 1 / 0 16613 2009-03-18
16  다음과 같은 에러가 발생할때 Could not reliably determine the server's fully qualified do..   member 높이뜬새 6 / 1 68556 2009-03-17
15  웹프로그래밍 언어별 리퍼러(referer) 구하기   admin 웹마당넷 2 / 0 44597 2009-03-05
14  방금 알게된 새로운 사실!! 윈도우 또는 alert 경고창 내용 복사   member 사라마음 2 / 0 6347 2009-02-15
13  특정 포트(PORT)가 열려있는지 확인하는 방법   member 컴퓨터존 1 / 1 104421 2009-01-22
12  URL이란?   admin 웹마당넷 1 / 0 10815 2009-01-14
11  명령어 프롬프트 창에서 IIS 시작,중지,리스타트하기   member 컴퓨터존 1 / 2 25551 2008-12-11
10  아파치(apache) 시작,중지,리스타트하기   member 컴퓨터존 4 / 3 104383 2008-12-08
9  Windows 미디어 서비스 HTTP 서버제어 프로토콜 활성화 이미지   admin 웹마당넷 0 / 0 5738 2008-09-27
8  리눅스(Linux) 쉘 상태에서 웹서버 접속자 수 알아내기   member 컴퓨터존 0 / 0 3197 2008-09-04
7  [서버운영] 웹 해킹 흔적을 찾는 간단한 find 명령어   member 파도 0 / 1 4117 2008-07-02
write
button [1] [3] button