이전 글에서는 프로그래머의 부적절한 코딩으로 인해 발생하는 SQL 인젝션 공격 취약점의 본질에 대해 이미 이야기한 바 있으며, 이에 앞서 SQL 인젝션 공격을 받지 않도록 올바르게 코딩하는 방법에 대해 계속해서 알아보겠습니다. 문제 먼저 코드를 살펴보겠습니다.
다음과 같이 코드 코드를 복사합니다.
희미한 sql_injdata,SQL_inj,SQL_Get,SQL_Data,Sql_Post
SQL_injdata = '|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare
SQL_inj = 분할(SQL_Injdata,|)
Request.QueryString<>이면
각 SQL_Get In Request.QueryString에 대해
SQL_Data=0인 경우 Ubound(SQL_inj)로
if instr(Request.QueryString(SQL_Get),Sql_Inj(Sql_DATA))>0 그러면
Response.Write <Script Language=javascript>alert('SQL 주입 방지 시스템 메시지가 표시됩니다. 다시 주입하지 마십시오!') History.back(-1)</Script>
응답.끝
종료하면
다음
다음
종료 조건
Request.Form<> 그렇다면
Request.Form의 각 Sql_Post에 대해
SQL_Data=0인 경우 Ubound(SQL_inj)로
if instr(Request.Form(Sql_Post),Sql_Inj(Sql_DATA))>0 그러면
Response.Write <Script Language=javascript>alert('SQL 주입 방지 시스템 메시지가 표시됩니다. 다시 주입하지 마십시오!') History.back(-1)</Script>
응답.끝
종료하면
다음
다음
종료하면
이는 인터넷상에서 널리 유행하고 있는 ASP 주입 방지 코드의 일종으로, Post 메소드와 Get 메소드로 제출된 데이터를 확인하고, Insert, Update, And 등의 민감한 문자를 필터링하여 SQL 주입을 방지하려는 아이디어입니다. 이론적으로는 충분한 문자를 필터링하면 SQL 주입 공격을 받지 않을 것이라고 확실히 보장할 수 있지만 주의하시기 바랍니다. 이 코드를 읽고 그것이 어떻게 판단되는지 주목하세요. instr 함수를 통해 판단됩니다. 즉, and 문자를 필터링하려면 And라는 단어뿐만 아니라 모든 단어도 필터링됩니다. and를 포함하는 섬, 본토, 손 등 다음 문자 조합이 포함된 단어는 모두 필터링되었습니다. 이러한 문자가 필터링되어도 계속 사용할 의향이 있는 사람이 있을까요? 그러므로 이러한 민감한 문자를 필터링하는 방법은 전혀 의미가 없습니다. 놀라운 것은 그러한 쓰레기가 실제로 인터넷에 고전으로 게시된다는 것입니다.
어떤 사람들은 SQL 주입 공격이 SQL 쿼리 문자열을 연결함으로써 발생한다고 말합니다. 따라서 SQL 쿼리 문자열을 연결하지 않고 저장 프로시저를 사용하면 SQL 주입 공격으로부터 보호할 수 있습니다. 이것이 사실입니까? 반드시 그런 것은 아니지만 저장 프로시저 주입 공격의 예를 살펴보겠습니다.
저장 프로시저 dt_GetNews의 코드는 다음과 같습니다.
절차 생성 dt_GetNews
@newstype 정수
처럼
newstype=@newstype인 뉴스에서 *를 선택하세요.
가다
호출 코드:
<%
희미한 관계
adoconnection=server.createobject(adodb.connection) 설정
'........여기서 데이터베이스 연결을 설정하는 관련 코드는 생략됩니다.
adoconnection.execute exec dt_GetNews +request(뉴스 유형)
adoconnection.close
%>
request(newstype) 값이 1이면 작업 결과는 뉴스 테이블의 newstype 필드가 1인 모든 레코드를 반환합니다. 그러나 request(newstype) 값이 1이면 drop table news; , 반환된 결과는 뉴스 테이블이 삭제되었다는 것입니다.
이 예에서 볼 수 있듯이 저장 프로시저를 사용해도 여전히 공격을 받을 수 있습니다. 또한 newstype=@newstype이 스플라이싱되지 않는 뉴스에서 *를 선택하면 스플라이싱 SQL 쿼리 문자열과 SQL 인젝션 공격 사이에 필연적인 연관성이 없습니다. 저장 프로시저는 주입 공격으로부터 보호하지 못할 수도 있습니다.
그럼 어떻게 하면 SQL 인젝션의 공격을 받지 않고 작성할 수 있을까? Oracle, Sql Server, mySql, Access 또는 기타 관계형 데이터베이스이든 필드 유형은 대략 숫자 유형(예: int, float 등)과 문자 유형(예: char, varchar 등)의 두 가지 범주로 나눌 수 있습니다. ) 해당 SQL 문은 다음과 같이 필드 유형에 따라 약간 다릅니다.
뉴스 유형이 1인 Select * from news의 뉴스 유형 필드는 숫자 필드여야 합니다.
newstype='social news'인 뉴스에서 *를 선택합니다. 뉴스 유형 필드는 문자 필드여야 합니다.
숫자 필드의 경우 매개변수의 데이터 유형을 확인해야 합니다. 예를 들어 newstype=+v_newstype에서 select *를 사용하여 쿼리 문을 구성하는 경우 v_newstype 변수의 데이터 유형을 확인해야 합니다. 최소한 정수 또는 부동 소수점 숫자일 수 있는 숫자여야 합니다. 그러한 확인이 이루어지면 newstype=+v_newstype이 newstype=1인 select *와 유사한 것을 결코 구성하지 않을 것입니다. ;떨어지다 테이블 뉴스와 같은 진술. ASP가 ASP.Net, JSP 등에 비해 공격에 더 취약한 이유는 ASP에서 변수를 선언할 필요가 없고 변수 유형이 불분명하기 때문입니다.
문자 필드의 경우 작은따옴표(')를 처리해야 합니다. 처리 방법은 작은따옴표 하나를 두 개의 작은따옴표('')로 바꾸는 것입니다. newstype='+v_newstype+'를 사용하여 쿼리 문을 구성하는 경우 v_newstype의 작은따옴표는 두 개의 작은따옴표로 바뀌어야 합니다. 왜냐하면 SQL에서 두 개의 작은따옴표로 묶인 부분은 문자열을 나타내고 두 개의 연속된 작은따옴표는 단일따옴표를 나타내기 때문입니다. quote는 작은따옴표 문자를 나타냅니다. v_newstype의 값이 다음과 같을 때, newstype='+v_newstype+'에서 select *의 구성 방법을 살펴보겠습니다.
소셜 뉴스';드롭 테이블 뉴스--
하나의 작은따옴표를 두 개의 작은따옴표로 바꾸면 v_newstype의 값은 다음과 같습니다.
소셜 뉴스'';드롭 테이블 뉴스--
구성된 SQL 문은 다음과 같습니다.
newstype='소셜 뉴스'';드롭 테이블 뉴스—'인 뉴스에서 *를 선택합니다.
쿼리 결과는 이전처럼 뉴스 테이블을 삭제하지 않고 뉴스 테이블의 newstype 필드 값이 social news';drop table news--인 레코드를 반환하는 것입니다.
또한, Insert, Update, Delete, Exec 등을 포함하여 처리해야 할 것은 Select 문뿐만 아니라 다음과 같은 주입 방법을 살펴볼 수 있습니다.
뉴스(제목) 값('+v_title+')에 삽입하는 구조에서,
v_title=123';테이블 뉴스 삭제--';
update news set /> when v_title=123'-- 또는 v_id=1;drop table news--일 때 Select 문에만 문제가 있는 것이 아니라 다른 문에도 문제가 있을 수 있으므로 Select에만 집중하지 마세요.
즉, 데이터 유형을 확인하고 작은따옴표 문자를 처리한 후에 모든 능력을 갖추고 있더라도 내 여래의 손바닥 밖으로 날아갈 수는 없습니다.