저장 프로시 저는 마술로 SQL 삽입을 방지하지는 않지만 훨씬 더 쉽게 방지 할 수 있습니다. 당신이해야 할 일은 다음과 같습니다 (Postgres 예제).
CREATE OR REPLACE FUNCTION my_func (
IN in_user_id INT
)
[snip]
SELECT user_id, name, address FROM my_table WHERE user_id = in_user_id; --BAM! SQL INJECTION IMMUNE!!
[snip]
그게 다야! 문자열 연결 (예 : 동적 SQL)을 통해 쿼리를 구성 할 때만 문제가 발생하며 이러한 경우에도 바인딩 할 수 있습니다! (데이터베이스에 따라 다릅니다.)
동적 쿼리에서 SQL 삽입을 피하는 방법 :
1 단계) 동적 쿼리가 정말로 필요한지 자문 해보십시오. 입력을 설정하기 위해 문자열을 묶는 경우 잘못 입력했을 수 있습니다. (이 규칙에는 예외가 있습니다. 일부 데이터베이스에서 쿼리를보고하는 경우는 예외입니다. 각 실행마다 새 쿼리를 강제로 컴파일하지 않으면 성능 문제가 발생할 수 있습니다. 그러나이 문제를 조사하기 전에 조사하십시오. )
2 단계) 특정 RDBMS에 변수를 설정하는 올바른 방법을 연구하십시오. 예를 들어, Oracle에서는 다음을 수행 할 수 있습니다 (문서에서 인용).
sql_stmt := 'UPDATE employees SET salary = salary + :1 WHERE '
|| v_column || ' = :2';
EXECUTE IMMEDIATE sql_stmt USING amount, column_value; --INJECTION IMMUNE!!
여기에서는 여전히 입력을 연결하지 않습니다. 당신은 안전하게 묶고 있습니다! 만세!
데이터베이스가 위와 같은 것을 지원하지 않는 경우 (바람직하게도 여전히 나쁘지는 않지만 놀라지 않을 것입니다) 또는 여전히 입력을 연결 해야하는 경우 (예 : 쿼리를보고하는 "때때로"의 경우) 위의 힌트), 적절한 탈출 기능을 사용해야합니다. 직접 쓰지 마십시오. 예를 들어 postgres는 quote_literal () 함수를 제공합니다. 그래서 당신은 실행할 것입니다 :
sql_stmt := 'SELECT salary FROM employees WHERE name = ' || quote_literal(in_name);
in_name이 '[snip] 또는 1 = 1'과 같은 악의적 인 경우 ( "or 1 = 1"부분은 모든 행을 선택하여 사용자가하지 말아야 할 급여를 볼 수 있도록합니다!), quote_literal은 엉덩이를 절약합니다. 결과 문자열 만들기 :
SELECT salary FROM employees WHERE name = '[snip] or 1=1'
이름이 이상한 직원이없는 한 결과가 없습니다.
그것이 요점입니다! 이제 Oracle Injection 전문가 Tom Kyte가 SQL 인젝션 주제에 대한 고전적인 게시물에 대한 링크를 남기도록하겠습니다. Linky