본문 바로가기
Web hacking/개념 정리 & 심화

3) 게시판 개발 및 SQLi, XSS 취약점 테스트

by m_.9m 2023. 1. 16.

1.1. 개발 기술서

환경 구성은 아래와 같다.

스프링 부트 Spring boot 2.7.3
빌드 프레임워크 Gradle
템플릿 엔진 Thymeleaf
SQL Mapper 프레임워크 Mybatis
데이터베이스 MySQL

 

1.1.1. 로그인 기능 구현

[초기 화면]

1. 처음 페이지에 들어갔을 때 보이는 화면으로 로그인을 제외한 다른 기능 사용이 불가능함.

 

[초기 화면 > 로그인]

2. 로그인 페이지(login.html)와 로그인이 성공했을 때 보이는 메인 페이지 구현.

 

[초기 화면 > 로그인 > 메인 화면]

3. 로그인 후 메인 페이지에 진입한 것을 확인한다.

 

4. 로그인과 로그인을 수행하는 SQL문에 대한 소스코드이다.

 

 

4. 로그인 수행 시 세션을 name에 저장해 로그인 여부를 체크하는 interceptor를 구현.

interceptor을 구현 시 모든 경로가 검사되기 때문에 로그인 여부와 상관없는 경로들은 첫번째 if문을 통해 true로 제외시킨다. 이후 두 번째 if 문으로 name 변수에 세션 값을 검증해 true로 보내고 세션이 검증되지 않으면 index 초기 페이지로 리다이렉트 시킨다.

 

1.1.2. 게시판 기능 구현

1. 글 목록 보기, 새로운 글쓰기, 페이징, 글 검색 기능 구현.

 

2. 취약점 테스트

2.1. SQL Injection

  설명
발견URL URL 파라미터 메뉴
[초기 화면 > 로그인]
/login
id, pw 로그인
[초기 화면 > 로그인 > 메인 화면 > 게시판]
/Board/board
search 게시글 검색
취약점
상세 내역
공격자가 임의의 SQL 질의 문을 삽입할 수 있는 공격이다. 사용자의 입력을 SQL 질의 문에 그대로 넣어서 사용했기때문에 발생된다. 이것으로 인해 데이터 우회와 변조, 추가, 추출이 가능하다.

 

Case 1) Blind SQL Injection

Step 1. 로그인 페이지를 클릭한다.

 

Step 2. 기존 SQL 문을 참고해 아이디, 비밀번호를 모른다는 상황 가정 하에 [거짓 or 참 and 거짓 or 참] = [참 and 참] 구조의 스크립트를 작성한다.

 

Step 3. 작성한 스크립트를 삽입해 참, 거짓이 수행되는 것을 확인한다.

삽입 스크립트: X" or (1=1) or "1"="1

[공격 구문이 참일 경우]

[공격 구문이 거짓일 경우]

 

case 2) Error Based SQL Injection

Error 메세지가 출력되는 곳에서 사용할 수 있다. 일반적으로 SQL문은 (1) 문법 에러 검증 (2) 논리 에러 검증의 순서를 따른다. Error Based SQL injection은 논리적 에러를 유발하는 공격이기 때문에 문법을 지키되, 논리 유발을 일으키는 함수를 사용해야한다.

 

MYSQL)

updatexml 함수는 두 개의 인수를 통해 XML에서 XPath 표현식에 일치하는 데이터를 추출하여 반환하는 함수이다. 두 번째 인수에 유효하지 않은 XPath 표현식이 사용된다면 다음과 같은 오류가 발생한다.

기본형 에러 유발 구문 에러 값
extractvalue(xml_frag, xpath_expr) AND extractvalue(rand(), concat(0x3a, 실행할-SQL-쿼리))-- ERROR 1105 (HY000): XPATH syntax error: 'xpath_expr 인수의 값’

두 번째 인수가 항상 유효하지 않은 XPath 표현식이 되도록 하기 위해 concat() 함수(두개의 문자열을 하나의 문자열로 만들어 주는 함수)를 이용해 콜론(0x3a)를 앞에 추가한다.

 

 

이와 같은 함수로는 updatexml이 있다.

기본형 에러 유발 구문 에러 값
AND updatexml(null, 실행할-SQL-쿼리, null)-- AND updatexml (rand(), concat(0x3a, 실행할-SQL-쿼리))-- ERROR 1105 (HY000): XPATH syntax error: 'xpath_expr 인수의 값’

 

* 이외의 DB별 오류 출력 함수는 아래 링크를 참조한다.

https://www.bugbountyclub.com/pentestgym/view/53

 

Step 1. 로그인 페이지에 에러를 발생시킬 수 있는 구문을 삽입해 Error 출력 여부를 테스트한다.

 

Step 2. 데이터 베이스 이름을 출력하는 구문을 삽입해 ”sample” 데이터 베이스 명을 추출한다.

삽입 스크립트: 1" and updatexml(null,concat(0x3a,(select database())),null) and "1"="1

 

Step 3. 테이블 명을 출력하는 구문을 삽입해 “member” 테이블 명을 추출한다.

삽입 스크립트: 1" and updatexml(null,concat(0x3a,(select table_name from information_schema.tables where table_schema="sample" limit 1,1)),null) and "1"="1

 

Step 4. 컬럼 명을 출력하는 구문을 삽입해 ‘’pw” 컬럼 명을 추출한다.

삽입 스크립트: 1' and updatexml(null,concat(0x3a,(select column_name from information_schema.columns where table_name='member' limit 1,1)),null) and '1'='1

 

Step 5. 데이터를 출력하는 구문을 삽입해 회원의 pw를 추출한다.

삽입 스크립트: 1" and updatexml(null,concat(0x3a,(select pw from member limit 0,1)),null) and "1"="1

 

 

case 3) Union SQL Injection

Step 1. test를 te"+"st 등을 사용해 키워드 검색이 되는지 확인해본다. 키워드 검색이 확인되면 접근 가능성이 생긴 것으로 판단한다.

* 데이터 베이스별로 상이한 문자열 합치기 방법을 통해 테스트한다.

 

Step 2. order by 절을 통해 컬럼 개수를 확인한다. 에러가 나는 지점까지 늘려서 몇 개의 컬럼이 있는지 확인한다.

* blob과 clob의 데이터형을 사용하는 경우 컬럼이 존재해도 에러가 나기 떄문에 이를 유의해야한다.

 

 

Step 3. 데이터 출력 위치를 알기 위해서 4개의 값을 UNION SQL로 삽입해 출력되는 열을 확인한다.

 

Step 4. 현재 데이터 베이스를 확인하는 구문을 삽입한다.

삽입 스크립트: x" union select 1,database(),3,4 #

 

Step 5. 전체 테이블을 확인하는 구문을 삽입한다.

삽입 스크립트: x" union select 1,table_name,3,4 FROM information_schema.tables WHERE table_schema = "sample" #

 

Step 6. 전체 컬럼을 확인하는 구문을 삽입한다.

삽입 스크립트: x" union select 1,column_name,3,4 from information_schema.columns where table_name="member" #

 

Step 7. 추출한 정보를 활용해 member 테이블 내 id, pw 값을 추출한다.

 

2.2. XSS(Cross Site Scripting)

구분 설명
발견URL URL 파라미터 메뉴
/board/write.php title, content, name 게시물 작성
/board/search_result.php catge, search 검색
취약점
상세내역
XSS(Cross-Site Scripting) 이란 웹 애플리케이션에서 일어나는 취약점으로 관리자가 아닌 권한이 없는 사용자가 웹 사이트에 스크립트를 삽입하는 공격 기법이다. 이 취약점은 웹 애플리케이션이 사용자로부터 입력 받은 값을 제대로 검사하지 않고 사용할 경우 나타난다. 이 취약점으로 해커가 사용자의 정보(쿠키, 세션 등)를 탈취하거나, 자동으로 비정상적인 기능을 수행하게 할 수 있다.

Case 1) Reflected XSS

Step 1. 검색 기능에서 catgo의 파라미터 값에 임의의 스크립트를 삽입한다.

Step 2. 스크립트가 실행되는 것을 확인한다.

Case 2) Stored XSS

Step 1. 악성 스크립트가 삽입된 게시 글을 작성합니다.

Step 2. 작성한 게시 글 열람 시 스크립트가 실행되는 것을 확인할 수 있습니다..

 

3. 시큐어코딩

3.1. SQL Injection

Spring Mybatis에서 사용하는 문법은 #{ }와 ${ }이 있다. ${ }의 경우 Parameter가 바로 출력되어 SQL Injection에 취약하다. 반면 #{ }의 경우 Parameter가 자동적으로 String 형태로 들어와 ‘Parameter’ 형태가 된다. 따라서 가장 잘 알려져 있는 Prepare Statement와같이 쿼리에 공격 기법을 삽입해도 쿼리가 공격자의 의도에 따라 실행되지 않는다.

select문에 ${ }를 #{ }로 바꾸어 주어 SQL Injection에 대한 보안 대책을 적용한다.

수정 전 수정 후
select id from member where id="${id}" AND pw="${pw}" select id, pw from member where id=#{id,jdbcType=NUMERIC} AND pw=#{pw,jdbcType=NUMERIC}

 

3.2. XSS(Cross Site Scripting)

Spring 내의 XSS의 경우 Controller에서 HttpServletRequest 파라미터를 전달받아 출력할 시 특수문자 필터링이 모두 적용되는 것을 확인할 수 있었다.

*utext를 통하면 필터링이 되지 않는다고 하여 차후 테스트 예정이다.

 

PHP의 경우 시큐어 코딩을 위해 XSS가 일어날 수 있는 변수에 htmlspecialchars() 함수를 사용했다.

* htmlspecialchars() 를 입력 값과 출력 값에 모두 사용하면 이중 적용이 된다.

위의 함수가 필터링 하는 함수는 다음과 같다.

특수 문자  변환된 문자
&(앰퍼샌드)  &
""(겹따옴표)  "
''(홑따옴표)   '
<(미만)   &lt;
>(이상)  &gt;

 

Case 1) Reflected XSS

Step 1. 검색 결과를 조회하는 부분에 htmlspecialchars() 함수를 적용한다.

Step 2. 게시 글 검색 기능에 스크립트를 삽입해도 적용되지 않는 것을 확인한다.

 

Case 2) Stored XSS

Step 1. DB에 저장되는 파라미터에 전부 htmlspecialchars() 함수를 적용한다.

Step 2. DB에 이스케이프된 HTML문이 잘 삽입된 것을 확인한다.

Step 3. 실제로 게시물에 스크립트를 넣어 테스트해본다.