본문 바로가기
Security_study/CTF,WARGAME Write-up

[Dreamhack wargame] error based sql injection write-up

by 1M9ur1 2023. 9. 27.

https://dreamhack.io/wargame/challenges/412

 

error based sql injection

Description Simple Error Based SQL Injection ! 문제 수정 내역 2023.07.21 Dockerfile 제공

dreamhack.io

드림핵 wargame중 이름과 같이 error based sql injection을 활용하여 푸는 문제로 추측해볼 수 있습니다.

문제 설명

문제 설명에서도 이름과 같이 간단한 error based sql injection인 것을 알 수 있습니다. 

문제 사이트 화면

문제 서버에 접속하게 되면 위에 SELECT * FROM user WHERE uid='{uid}'; 라는 글자가 적혀있고 아래 uid에 값을 적어 submit을 누르면 제출되는 화면인것을 확인할 수 있습니다.

한번 확인해보기 위해 flag라는 문자를 제출해보았더니 {}부분에 flag라는 글씨가 들어간 것을 확인할 수 있었습니다.

글자를 추측해보면 user라는 테이블이 있고 where에서 uid라는 컬럼이 있는것을 추측해볼 수 있습니다. 

 

여기서 문제에서 제공된 파일을 확인해보겠습니다.

일단 파이썬코드를 보면 페이지에 제공된 것과 같이 get방식으로 입력받은 uid를 {}의 위치에 넣는 코드를 확인해볼 수 있습니다.

 

다음은 문제에서 제공된 SQL문을 확인해보겠습니다.

코드를 보면 use users;를 사용한것으로 보아 데이터베이스명은 users, 테이블 이름은 user, 칼럼은 idx, uid, upw가 있는것을 확인해볼 수 있습니다. 그리고 아래 INSERT는 테이블의 각 칼럼에 값을 넣어줄 수 있는 SQL문으로 볼 수 있습니다. 아래를 보면 uid와 upw에 값을 넣어주는 3개의 INSERT를 볼 수 있는데 첫 번째를 보면 admin이라는 uid를 넣고 그 upw에 플래그가 있는것을 확인할 수 있습니다.

 

결론적으로 admin이라는 계정의 비밀번호를 출력하면 flag를 얻을 수 있는것으로 확인할 수 있습니다.

그리하여 error based sql injection을 통해 admin의 비밀번호를 출력해야합니다.

error based sql injection을 사용하기 위해서는 extractvalue라는 함수를 사용하여서 공격할 수 있습니다.

 

 

기본 사용 문법은 extractvalue(xml_frag, xpath_expr)인 것을 확인할 수 있습니다.

error based sql injection은 sql문에 일부러 에러를 일으켜 에러에서 나오는 문장을 통해 정보를 얻을 수 있는 기법입니다.

 

왜 extractvalue가 이런 error based sql injection을 발생시킬 수 있냐면 이 함수의 인자 중 xpath_expr에 유효하지 않은 표현식으로 SQL쿼리를 지정해주면 해당 SQL문의 실행 결과가 오류에 포함되어 나오는 것을 이용하여 공격을 할 수 있습니다.

 

그러면 ERROR 1105 (HY000): XPATH syntax error: 'xpath_expr 인수의 값' 와 같은 형식으로 에러문이 출력되는 것을 확인할 수 있습니다. 이를 이용하려면 xpath_expr부분에 concat이라는 함수를 넣어 항상 유효하지 않은 표현식을 만들어서 에러를 일으킬 수 있습니다. concat은 앞과뒤를 이어주는 함수입니다.

 

그리하여

extractvalue(1, concat(0x3a, 실행할 SQL문))--

과 같은 형식으로 적어주면 SQL의 실행결과가 나오는것을 확인할 수 있습니다. 뒤의 --는 뒷 부분을 주석처리해주는 문자입니다. 0x3a는 아스키코드로 : 를 의미하는 것입니다. 앞의 1은 임의의 값을 적어주는 부분입니다.

 

그리하여 admin의 비밀번호를 알아내기 위해 다음과 같이 적어서 빈칸에 제출하면 admin의 비밀번호인 flag를 얻을 수 있었습니다.

1' and extractvalue(1,concat(0x3a, (select upw from user where uid='admin')));--

그러나 플래그가 너무 긴 바람에 전부 출력되지 않고 중간에 짤리는 현상을 발견하였습니다.

그리하여 substr이라는 함수를 이용하여 해당 admin의 비밀번호 문자열을 중간부터 출력해주기 위해 사용하여 다음과 같이 SQL문을 구성하여 제출하였더니 flag의 뒷 부분을 얻을 수 있었습니다.

1' and extractvalue(1,concat(0x3a, (select substr(upw,20,30) from user where uid='admin')));--