SK shieldus Rookies 16기 (클라우드 기반 취약점 진단 및 대응 실무 #02)

만두다섯개·2023년 12월 12일

SK 루키즈 16기

목록 보기
30/52
post-thumbnail

주요 정보

  • 교육 과정명 : 클라우드기반 스마트융합보안 과정 16기
  • 교육 회차 정보 : '23. 12. 12. 클라우드 기반 취약점 진단 및 대응 실무 #02

학습 내용 요약

  • SQL Injection 취약점 실습
  • 위험한 파일 업로드 취약점 실습

SQL Injection

5. Lab: SQL injection vulnerability allowing login bypass

링크

perform a SQL injection attack that logs in to the application as the administrator user.

  • Boolean Based SQL Injection
  • Error Based SQL Injection
  • Time Based sql Injection (시간관련 함수) ...

접근

아래와 같은 기초적인 로그인 SQL 쿼리를 사용한다고 가정해보자.
SELECT * 는 모든 것을 가져오는 것이 아닌, 로그인을 위한 로직이 존재할 것이다.

SELECT * FROM member WHERE id = '$username' AND pass = '$userpass';

만약 $username 이 administrator'-- 가 들어간다면 어떻게 될까?

SELECT * FROM member WHERE id = 'administrator'--' AND pass = '$userpass';

-- 뒤에 있는 문장은 모두 주석처리가 된다. 즉, 비밀번호 입력 여부가 상관이 없어진다.

SELECT * FROM member WHERE id = 'administrator';

이 문장과 동일해진다. 따라서, member 라는 테이블에 administrator 라는 사용자가 있기만 한다면, 로그인 로직이 참이 되어 로그인이 된다.

해결 과정

  1. 로그인 ID 입력 폼에 administrator 입력 후 결과를 확인한다. (패스워드 임의 입력)

따로 암호화 없이 계정 정보가 전달되고 있다.
2. 로그인 ID 입력 폼에 administrator'-- 입력 시도 (패스워드 임의임력)
Burp Suite 는 아래와 같이 Request 전달하는 것을 확인 가능하다.

3. 로그인 완료

6. Lab: Blind SQL injection with conditional responses

링크

  1. 조건 : SQL 쿼리 결과 반환 없음. 에러 메시지 표시 없음. 'Welcom back' 이라는 메시지가 쿼리로부터 Row 반환시 출력. 분석 목적으로 tracking cookie 사용 및 해당 쿠키로 SQL query 사용한다.
    users 테이블 존재. username, password.
    - 계정 정보 : administrator:????
    - 추가 Hint : 비밀번호는 영어 소문자, 숫자로만 구성
  2. 실습 목표 : log in as the administrator user.

접근

  • SQL 쿼리 결과값이 'Welcom back' 출력 또는 없음 이라면 이는 Blind SQL Injection 의미한다.
    예/아니오 라는 걸로 어떻게 원하는 결과를 획득 가능한가? 라는 질문에는 아키네이터를 생각하면 된다.

    아키네이터는 점점 범위를 좁혀가며 사용자가 원하는 답을 알려준다.
    비밀번호 획득을 목표로 큰 범위에서 세세하게 범위를 좁혀가면 된다.
  1. 비밀번호의 개수는 몇자리?
  2. 비밀번호의 각 자리는 무엇으로 구성되어 있는가?
    Hint에서 비밀번호는 영어소문자, 숫자로 구성되어 있다고 했다. 따라서, 2번에서는 abcdefghijklmnopqrstuvwxyz0123456789 중 하나가 분명히 사용될 것이다.
  • Blind SQL Injection 결과 값인 O / X 를 얻기 위해서는 어떻게 해야 하는가?
    SQL 질의를 어떻게 & 어디로 입력해야 웹 서버가 응답을 해 줄까?

해결 과정

  1. Brup Suite Repeater에서 SQL 질의 쿼리를 입력할 곳을 찾아보자

    아이디 입력 폼에 administrator'-- 를 입력해도 'Welcome back!' 이 출력된다. 이는 username에는 다른 SQL 질의문을 입력해도 결과를 알 수 없다는 의미이다. 다른 곳을 찾아보자.

  2. 제시된 조건 중, tracking cookie 사용 및 해당 쿠키로 SQL query 사용한다는 조건이 있다.
    그리고 1번 Reqeust에서 TrackingId라는 이름으로 쿠키를 사용한다. 즉, TrackingId의 값이 query문 매개변수 값으로 사용된다는 의미이다. 확인해 보자

TrackingId 뒤에 쿼리문을 추가로 입력하고 결과를 확인해 보면, 'Welcome back!'이 출력된다. 이는 TrackingId이 쿼리 질의문의 매개변수로 사용되고, 해당 ID 값 뒤에 SQL Injection 공격이 가능하다는 의미이다. 여기에 접근 1번을 적용하면 된다.

oBpZ00yc4uWBCRSB' AND (SELECT 'a' FROM users LIMIT 1)='a; => 'Welcome back!' 출력

users 라는 테이블에서 1개의 컬럼이 존재한다. == users 테이블이 존재한다.

oBpZ00yc4uWBCRSB' AND (SELECT 'a' FROM password LIMIT 1)='a; => 'Welcome back!' 출력 없음

password 라는 테이블에서 1개의 컬럼이 존재하지 않는다. == password 테이블이 존재하지 않는다.
따라서 users 테이블만 사용해 쿼리문을 사용한다.

주어진 조건 중에는 user에 username 이라는 컬럼 존재한자. 확인해 보자.

1BWUQY' AND (SELECT 'a' FROM users WHERE username='administrator')='a;  => 'Welcome back!' 출력

  1. 비밀번호는 몇 개인가요?
    administrator 계정의 비밀번호 개수를 확인해 보자.
LENGTH(password)>1  => password 길이가 1보다 크면 참

이제 위의 조건문을 AND로 기존 조건문에 추가해 주자. (조건문이 거짓이라면 다 거짓일테니)

그리고 위의 조건문을 반복하기 위해 Intruder 사용한다. (자세한 설명은 생략한다)
20보다 크냐고 물어봤을때, 'Welcome back!' 출력되지 않았다. 이는 패스워드의 길이가 20자리를 의미한다.

  1. 비밀번호 각 자릿수는 뭔가요?
    주어진 조건에서는 20개의 문자로 이루어진 비밀번호는 각 자리에서 abcdefghijklmnopqrstuvwxyz0123456789 중 하나가 사용된다.
    비밀번호의 첫번째 자릿수를 떼어와서 비교하는 문장을 사용해보자.
WUQY' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='administrator')='a => SUBSTRING(password,2,1) ...

여기에서 a의 값에 7을 대입하고 Request를 날리자.
만약 패스워드의 첫 번째 자리수가 7이라면, 비밀번호는 7XXXX_XXXXX_XXXXX_XXXXX_XXXXX 이다.
Intruder 를 사용해서 하나씩 대입해 보면, Response 에서 'Welcome back!' 출력을 일일히 확인할 필요 없이, Length 만 확인하면 어떤 값에서 'Welcome back!' 출력인지 확인 가능하다.

이걸 반복해 조합하면 패스워드가 나온다. 끝!

  • 외부 변수로부터 받은 값이 직접 SQL 함수의 인자로 어떻게든 사용되었다.(전달 되거나, 문자열 복사)

결론

  1. SQL Injection 취약점 보완 방법
    외부 변수로부터 받은 값이 직접 SQL 함수의 인자로 어떻게든 사용되었다.(전달 되거나, 문자열 복사)
    - 따라서, 인자화된 질의문을 사용하는 것이 좋다.
  2. 보수적 보안 방법
    • 로그인 시도 횟수 제한

인자화된 질의문 VS 변수 직접 삽입 질의문

인자화된 질의문이란?

인자화란? 매개 변수나 인자를 사용해 어떤 값을 전달 혹은 대체하는 것을 의미한다.
변수 직접 사용 삽입 질의문과 어떤 차이가 있을까?

pstmtprepareStatement인터페이스의 객체이다.

prepareStatement pstmt = con.preparedStatement(sql);

? 는 preparedStatementplaceholder이다. 추후 쿼리 실행 시 실제 값으로 대체된다.
setString() 메소드는 이스케이프처리 기능으로 특수문자로부터 비교적 안전하다.

특정 값을 전달하려는 목적에서는 동일한 기능을 가진다.
그러나 인자화를 통한 질의문을 생성하면 SQL Injection을 방지하기 위해 사용 가능하다.

파일 업로드 취약점

7. Lab: Remote code execution via web shell upload

링크

  1. 조건 : 특정 파일 확장자 블랙리스트 사용으로 사용 불가.
  • 계정 정보 : wiener:peter
  1. 실습 목표 : upload a basic PHP web shell and use it to exfiltrate the contents of the file /home/carlos/secret.

접근

  1. 실습 목표를 획득하는 코드를 .php 확장자 파일로 생성해 업로드한다.

해결 과정

  1. 실습 목표를 출력하는 코드를 .php 확장자 파일로 생성하고 업로드한다.

  1. 웹 서버의 파일 결과를 확인한다.

결론

  • 파일 확장자를 필터링 하지 않는다면, 위험한 파일 업로드 취약점 가능성 존재한다.
  • 위험한 파일 확장자 취약점으로 인해 웹 서버 내부 파일 유출 가능

8. Lab: Web shell upload via extension blacklist bypass

링크

  1. 조건 : 특정 파일 확장자 블랙리스트 사용으로 사용 불가.
  • 계정 정보 : wiener:peter
  1. 실습 목표 : upload a basic PHP web shell, then use it to exfiltrate the contents of the file . Submit this secret using the button provided in the lab banner. /home/carlos/secret

접근 : 로그인 후 .php 확장자 파일 업로드 실패

해결 과정

  1. 블랙리스트 기반 확장자 금지 => 특정 확장자는 사용 가능하다. 따라서 .htaccess 확장자를 사용한 파일 업로드한다.
  2. 아래와 같은 파일을 생성한다 (메모장 사용, 저장 시 모든 확장자
AddType application/x-httpd-php .myphp 

.htaccess 확장자에 있는 코드는 아래와 같다.
.myphp 확장자를 php 스크립트와 관련시킨다. 즉, 웹 서버에서 .myphp 확장자를 가진 파일의 내용이 php 스크립트로 작동된다.
(application/x-httpd-php : PHP 스크립트를 나타내는 MIME 유형)
3. .htaccess 파일을 업로드 한다.

  1. .notphp 확장자를 가진 파일을 아래와 같이 생성한다.

  1. 해당 파일을 업로드 후 확인

  1. 업로드한 파일의 결과 확인목적으로 위해 아래 사진과 같이 RequestGet 요청을 보낸다.

  • /home/carlos/secret 내용을 획득했다.

결론

  • 블랙리스트 기반 필터링은 근본적으로 위험한 파일 업로드 문제를 해결 할 수 없다.
  • .htaccess 확장자를 가진 파일 필터링한다.
  • 화이트리스트 방식과 블랙리스트 방식을 조합해서 사용.
  • 업로드 디렉토리 장소를 웹 서버의 document 외부에 설정한다.

디렉토리 탐색 취약점

9. Lab: File path traversal, simple case

링크

  1. 조건 :
  • 계정 정보 :
  1. 실습 목표 : retrieve the contents of the /etc/passwd file.

접근

  1. 파일 경로로 접근해 특정 파일을 가져오고자 한다.
  2. 해당 Lab에서는 상품 페이지를 클릭하면, 상품 세부 정보 페이지로 이동한다.
  3. 2번의 과정의 Reqest, Response를 살펴보자.

    상품 선택 시, 발생하는 Request GET 요청에서 아래와 같이 확인할 수 있다.
    1. /product 경로에서 productId가 1인 데이터를 GET 하겠다.
    2. /image 경로에서 filename이 15.jpg 인 데이터를 Response
    클라이언트 => 데이터 요청(특정 경로)
    웹 서버 => 요청 경로 사용 후 내용물 응답에 넣는다. (검증 로직 없없음)
    => /etc/passwd 경로 지정 및 passwd 요청 시 응답 예상.

해결과정

  1. Brup Suite Reapeater에서 블로그의 특정 게시물 요청을 변조한다.


Request 요청을 확인하면, 게시물 요청 시, 특정 productId을 요청한다.

GET /product?productId=4 HTTP/1.1

해당 요청을 아래와 같이 파일 탐색으로 바꾸어 전송해보자.

GET /image?filename=../../etc/passwd HTTP/1.1

나오지 않는다. 탐색의 깊이가 깊지 않아서 그렇다. 더 많은 깊이로 가보자

GET /image?filename=../../../../../../etc/passwd HTTP/1.1

/etc/passwd 결과가 출력되었다.

결론

  • ../../.. 탐색 결과로부터 조금씩 탐색 깊이를 얕게하면, 정확한 파일의 디렉터리 깊이를 확인 가능하다.

10. Lab: File path traversal, traversal sequences stripped with superfluous URL-decode

링크

  1. 조건 : This lab contains a path traversal vulnerability in the display of product images.
    The application blocks input containing path traversal sequences. It then performs a URL-decode of the input before using it.
    To solve the lab, retrieve the contents of the /etc/passwd file.
  2. 실습 목표 : retrieve the contents of the /etc/passwd file.

접근

  1. 주어진 조건에서는 웹 서버에서 경로 조작을 방지하기 위해, 경로 조작 시퀸스를 막고, 요청 사용 전, 불필요한 URL 디코딩을 수행한다고 한다.

  2. 이로 인해 알 수 있는 것은 아래와 같다.

  3. ../../../etc/passwd 와 같은 직접적인 경로 조작 시퀸스를 사용 시, 막힌다.

  4. 웹 서버에는 URL 디코딩 후 Request를 사용하기 때문에, URL 인코딩 된 경로 조작 시퀸스를 사용한다.

  5. 단, 웹 서버에서 사용하는 디코딩 횟수는 알 수 없다.

인코딩

../../../etc/passwd 을 URL 안코딩 시,
%2e%2e%2f%2e%2e%2f%2e%2e%2f%65%74%63%2f%70%61%73%73%77%64 

디코딩

%2e%2e%2f%2e%2e%2f%2e%2e%2f%65%74%63%2f%70%61%73%73%77%64 을 URL 디코딩 시,
../../../etc/passwd 

Request 패킷에서는 일부 특수문자들이 URL인코딩 되어 있다.
왜 그럴까? HTTP 웹 서버이므로 RESTfull 설계로 인해 URL 을 인/디코딩 하여 사용한다. (참고)

해결과정

  1. 경로 조작에 사용되는 공격문을 1회 URL 인코딩 하여 Request 패킷을 수정한다.

GET //image?filename=%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%65%74%63%2f%70%61%73%73%77%64 HTTP/2

Response 확인 시, 아래 그림과 같이 1회 인코딩 시, 웹 서버에서 N회 디코딩 후 사용하려고 했으나 경로로 사용 불가 메시지가 나온다면,
웹 서버측에서는 1회 디코딩 후 Resquest 요청을 사용하지 않는다. 인코딩 횟수를 2회로 늘려 보자.

Response 결과 메시지 참고


한번 더 인코딩 해 사용해 보자.
위 그림과 아래 그림의 차이는?

Response 결과가 상이하다.
위 그림 : Not Found => 웹 서버에서 해당 리소스 없어. (잘못된 GET 문장 사용 // 사용함)
아래 그림 : No such file => 파일 시스템에서 특정 파일을 찾을 수 없을때 주로 나타난다.

  1. 경로 조작 공격문을 2회 URL 인코딩 하여 Request 패킷을 수정한다.

웹 서버 특정 위치의 /etc/passwd 파일이 나왔다.
웹 서버는 Reqest 패킷을 2회 디코딩해서 경로를 사용한다.

결론

경로 조작 취약점을 보호하기 위해
1. 경로 탐색 방지 목적으로 직접적인 경로 필터링
2. 2회 이상 URL 디코딩 후 사용
방법을 사용했다.
그러나, 이 방법은 2회 이상 URL 인코딩 경로 조작 시퀸스 문 사용으로 파회된다.

경로 순회 취약점 보안 대책

  1. 파일 위치 경로를 변수로 사용하지 않는다. 해당 파일의 키 값을 변수로 사용해 다운로드 한다.
    파일 위치 경로를 변수로 사용 시,
../와 ..\와 .\와 % 등

특수 문자 보안 필터링을 적용한다.

profile
磨斧爲針

0개의 댓글