webhacking 50번
포스팅에 앞서 내용이 틀릴 수도 있으며, 해당 부분 지적은 감사히 받겠습니다.
50번 문제이다.

sql injection 문제이다.
webhacking.kr에서는 sql injection 문제를 많고 다양하게 다뤄줘서 좋다.
소스코드를 보자.

id, pw를 addslashes 해주며, id를 euc-kr에서 utf-8로 인코딩해준다.
새로운 함수
1. foreach($_GET as $ck) // $_GET을 가져와서 ck에 변수로 하나씩 저장한다.
그리고 ck에서 from, pw (, ), 공백, %, =, <, >를 대소문자 구분하지 않고 필터링한다.
또한 id 값에서 union을 필터링한다.
lv가 3인 값을 띄우면 문제는 해결된다.
한번 풀어보자.

그냥 제출을 누른 상태이다.
guest id의 lv은 1이다.

id가 admin인 계정일까 싶어 찾아봤더니 admin은 lv이 2이다.
그렇다면 lv가 3인 계정이 무엇일까 생각하다, where 조건절을 lv로 줘봤다.
쿼리 : ?id=admin%fa%27||lv%09like%093--%09-&pw=admin

lv가 3 인건 뜨지 않는다.

문법은 잘못되지 않았다.
우리는 괄호, 비교 연산자 등 사용할 수 없기에 무슨 방법이 있나 많은 고민들을 했다.
그러다 소스코드에서 lv 1, 2와 3의 차이점을 발견했다.
바로 1과 2는 더블 쿼터가 없지만, 3에서는 더블 쿼터로 감싸져 있었다.
나는 이 차이점을 문자형과 숫자형의 차이로 추측했고, 그렇다면 어떻게 문자형 3을 줄 수 있을까 생각했다.
첫 번째, 16진수 형 변환으로 값을 준다.
일단 실패하였다.
쿼리 : ?id=admin%fa%27||lv%09like%090x33--%09-&pw=admin

사실 나의 추측으로는 여기서 풀렸어야 했는데 풀리지 않아 문제 해결은 다시 미궁 속으로 들어갔다.
혼자 생각하다가 admin도 16진수로 주면 들어가던데 3이 들어가지 않은걸 보아 이 방법 자체가 잘못되었다 싶었다.
어떻게 하면 string으로 값을 줄 수 있을까..
인터넷 검색을 했다.
union select란다.
union은 필터링된 거로 알고 있는데..
힌트가 생겼으니 일단 한번 풀어보자.
다시 소스코드를 자세히 보았다.
id에만 필터링되어있다.
그럼 pw부분에 삽입해야 한다.
md5() 함수는 인코딩 함수인데 이 부분의 뒷마무리는 그냥 주석처리로 날려주면 된다.
union으로 injection을 진행할 때 반드시 알아두어야 할 게 있다.
화면에서 보이는 칼럼과 쿼리문으로 조회하는 칼럼의 수가 반드시 같아야 한다.
그렇지 않으면 injection은 실패한다.
이제 풀어보자.
쿼리 : ?id=/*&pw=*/%fa%27union%09select%3--%09-
첫 번째 시도 쿼리이다.

실패했다.
필터링에 걸리는 문자열을 사용했거나 문법에 맞지 않는다거나 둘 중 하나이다.
후자인 것 같다.

? 그냥 바보다.
union select 뒤 3에 %를 붙였었다..
근데 wrong이 뜬다는 건 값이 비었거나, 쿼터 안 문법에 문제가 있거나 둘 중 하나이다.
근데 솔직히 아무리 봐도 왜 안되는지 모르겠다.
그래서 조금 더 검색했다.
나의 쿼리 : ?id=/*&pw=*/%fa%27union%09select%093--%09-
문제를 푼 다른 분의 쿼리 : ?id=guest%a1%27/*&pw=*/union%0aselect%0a3%23
출처 : https://ehdtn1219.tistory.com/151
Webhacking.kr 50번 문제풀이
안녕하세요. 웹 해킹 50번 문제풀이 하겠습니다. 문제를 확인해보면, SQL INJECTION 관련 문제인 것을 알 수 있습니다. 소스코드를 확인해보겠습니다. 위 소스코드에서 addslashes 함수는 매개변수로 넘
ehdtn1219.tistory.com
실제로 저 쿼리는 작동한다.
나의 쿼리와 차이점을 찾아보자.
1. 필터링 우회 멀티 바이트 코드
2. 공백 우회
3. 싱글 쿼터의 위치
4. 주석처리 방법
1, 2, 4번은 실질적으로 문제에 변수를 주는 요인이라 생각 들지 않아 배제시켰다.
남은 것은 싱글 쿼터의 위치이다.
어떤 것이 문제에서 변수를 주었을까 고민하다가 혹시 쿼리의 싱글 쿼터 내부에 주석이 처리되면 제대로 작동을 하지 않나..? 생각을 했다.
검증은 추후에 해야겠다..
쿼리 : ?id=guest%a1%27/*&pw=*/union%0aselect%0a3%23

문제 해결
글을 작성한 후 계속 생각하며 코드를 보다가 id부분에서만 utf-8로 인코딩 되는 것을 발견하였다.
따라서 pw부분에서 멀티 바이트를 통해 우회 시도를 해봤자 멀티 바이트를 인식 못하기 때문에 나의 풀이가 작동하지 않았던 것이다.
원인을 찾아서 기분이 좋다.
시행착오
1. 테이블 내부에 데이터가 없을 땐 union을 사용하여 외부 테이블을 조인하여 사용한다.
2. 아직 확실치는 않지만 싱글 쿼터 내부에 주석이 있을 경우 쿼리가 제대로 작동하지 않는 것 같다.
3. utf-8은 멀티 바이트가 포함되어있어 addslashes를 우회할 수 있다.
4. id값만 utf-8로 인코딩 된다. 따라서 pw값에서 싱글 쿼터를 멀티 바이트로 우회할 수 없다.
5. 항상 소스코드 안에 답이 있다.
6. euc-kr은 한글만 있고, utf-8은 유니코드이다.