WebGoat

WebGoat (6)

홍시뗄레 2025. 3. 18. 14:38

[실습2-12] SQL Injection(advanced) -3

퀴즈 형식으로 되어 있다. 

첫번째 문제부터 보면,

프리컴파일이 진행되고 메모리에 올라가게 된다. 그리고 사용자 입력값만 세팅돼서 컴파일을 진행하지 않고 사용자 입력값만 바인딩한다. 그래서 prepared statement 속도가 더 빠르다.

그래서 답이 두번째. 

 

컴파일 된 이후에 입력해도 사용자 데이터를 순수하게 받기 때문에 공격하기 어렵다.

그래서 답이 3번.

prepared statement가 적용되면 순수한 데이터가 그대로 입력된다. 

이렇게 다 선택하면 모두 정답! 

 

[실습2-13] SQL Injection(mitigation) -1

sql injection에 안전한 코드를 완성하자.

변수를 만들 때는 PreparedStatement로 써야 하고, 메소드는 prepareStatement임에 유의하자. 

[실습2-14] SQL Injection(mitigation) -2

안전한 코드를 작성하자. 

우선 데이터베이스에 연결해야 되고, sql injection에 안전해야 된다. 사용자의 입력값은 하나 이상으로 되어야 하고 

DBURL, DBUSER, DBPW가 주어졌다.

기존 코드에 오류가 있어서 이걸 안전하게 바꿔줘야 한다.

아까 사용하던 걸 참고해서 써보자. 여기서는 입력할 수 있는 로직이 없으므로 임의로 name은 hongsi로 지어줬다. 이렇게 제출하면 성공적으로 문제를 풀 수 있다! 

[실습2-15] SQL Injection(mitigation) -3

이전에 advanced에서 해결한 문제를 조치했다고 한다. 이 조치가 아직 취약해서 고쳐보라는 것 같다.

test 입력하니까 이런 결과가 나온다. 

' or '1'='1 이렇게 입력해보자.

공백값을 허용하지 않는다! 공백을 지워주고 다시 해보자.

다 나타난다. 결과가 참이 돼서 모든 결과가 나왔다. 

우리의 목표인 user_system_data를 보고 싶다면? user_name, password를 볼 수 있어야 한다! 

테이블: user_system_data

컬럼: user_name, password

 

UNION injection을 해봐야 하는데 컬럼 개수를 파악해야 된다. 

컬럼 개수를 확인해봐야 하므로

'order/**/by/**/1--

이렇게 해보자.

공백 문자를 허용하지 않기 때문에 공백 대신 /**/를 사용한 것이다. 이렇게 했을 때 결과는 나오지 않는데, 오류가 나진 않는다. 1을 계속 늘려서 언제부터 오류가 나는지 확인해보자.

7까진 잘 되다가 8일때는 오류가 났다. 

'or/**/1=1/**/order/**/by/**/1--

이렇게 치면 더 결과를 눈에 띄게 확인할 수 있으니 참고. 

상위 select 절 컬럼 개수가 7개임을 확인했다. 

'/**/union/**/select/**/null,null,null,null,null,null,null/**/from/**/user_system_data--

이제 컬럼 개수를 알았으니 이걸 입력해보자.

이렇게 거짓으로 나오면서 null 개수가 출력된다. 

다음으로 자료형 타입을 알아내기 위해 첫번째 null을 'a'로 바꿔보거나 1로 바꿔보는 등 자료형을 찾아본다. 'a'를 치면 안 나오고 1을 치면 나온다.

왼쪽은 'a'를 입력했을 때, 오른쪽은 1을 입력했을 때 나오는 결과이다. 

'/**/union/**/select/**/null,user_name,password,null,null,null,null/**/from/**/user_system_data/**/--

첫번째 컬럼은 숫자이므로 건너뛰고 두번째와 세번째에 입력해보면 나올 것이다.

성공! 이러면 user_name, password를 알아낼 수 있다. 

[실습2-16] SQL Injection(mitigation) -4

전에 사용했던

'/**/union/**/select/**/null,user_name,password,null,null,null,null/**/from/**/user_system_data/**/--

이걸 다시 입력해보자.

select절이랑 from절이 사라졌다. 전이랑 달라졌다. 

 select과 from이 나오면 지우는 로직이 발생하고 있으니까, select 중간에 select을 넣는 거다. 

예를 들어

selselectect

이렇게 하면 가운데 있는 select절이 지워져서 select문이 완성된다. 

'/**/union/**/selselectect/**/null,user_name,password,null,null,null,null/**/frfromom/**/user_system_data/**/--

이렇게 하면 완성! 성공했다. 

[실습2-17] SQL Injection(mitigation) -5

마지막 문제다! ip 3자리만 알아내면 된다. 

order by field를 통해 풀라고 하니까 column을 건드려야 한다. 정렬 방법 같은 걸 신경 써주면 된다.

hostname을 누르고 버프스위트를 통해 확인해보면 column=hostname으로 돼있는 것을 볼 수 있다. 이 request를 리피터로 보내준다.

그리고 이렇게 오름차순으로 배열된다. 

 

* CASE WHEN 구문 * 

CASE WHEN [조건문] THEN [TRUE] ELSE [FALSE] END

 

hostname일 때 webgoat-acc가 먼저 출력되고

ip 기반일 땐 webgoat-tst가 출력된다. 

True : hostname => webgoat-acc

False: ip -> webgoat-tst

 

(CASE+WHEN+1=1+THEN+hostname+ELSE+ip+END)

1=1이 참이니까 hostname 배열대로 출력된다. 1=2로 하면 ip대로 출력된다. 

case when으로 injection 수행이 가능하다는 것을 확인할 수 있다. 

 

* 목표 * 

webgoat-prd의 ip를 알아내기

 

column=a 이렇게 하면 a라는 컬럼이 없기 때문에 error가 발생한다. 임의의 문자를 넣을 경우 에러!

근데 이렇게 보면 에러 표시 메시지가 다 나온다. id, hostname, ip, mac, status, descriptin이 컬럼일 것이고 from 다음에 오는 servers가 테이블 명이라는 것을 확인할 수 있다. 에러를 통해 테이블명을 알아냈다. 

 

목표 쿼리 : select ip from servers where hostname='webgoat-prd'

 

(case+when+(select+count(ip)+from+servers+where+hostname='webgoat-prd')=1+then+hostname+else+ip+end)

확인해보면 webgoat-acc로 나온 걸 봐서 참인 값임을 알 수 있다. 

 

(case+when+substring((select+ip+from+servers+where+hostname='webgoat-prd'),1,1)=1+then+hostname+else+ip+end)

이렇게 가운데 값을 하나씩 늘려가며 숫자를 3개 맞추면 된다. 

 

하나씩 풀었더니 104가 나왔다.

이렇게 하면 성공! 

'WebGoat' 카테고리의 다른 글

WebGoat (5)  (0) 2025.03.17
WebGoat (4)  (0) 2025.03.17
WebGoat (3)  (0) 2025.03.12
WebGoat (2)  (0) 2025.03.10
WebGoat(1)  (0) 2025.03.10