programing

Delphi - SQL 주입 방지

muds 2023. 7. 10. 22:57
반응형

Delphi - SQL 주입 방지

응용프로그램을 SQL 주입으로부터 보호해야 합니다.애플리케이션이 ADO를 사용하여 Oracle에 연결하고 인증을 수행할 사용자 이름과 암호를 검색합니다.

지금까지 읽은 바로는 전체 SQL을 문자열로 할당하지 않고 매개 변수를 사용하는 것이 가장 좋은 방법입니다.이와 같은 것:

query.SQL.Text := 'select * from table_name where name=:Name and id=:ID'; 
query.Prepare; 
query.ParamByName( 'Name' ).AsString := name; 
query.ParamByName( 'ID' ).AsInteger := id; 
query.Open;

또한 사용자의 입력 내용을 확인하고, delete, insert, select 등의 SQL 키워드를 삭제하려고 합니다.일반 ASCII 문자 및 숫자와 다른 입력 문자는 삭제됩니다.

이렇게 하면 최소한의 보안 수준을 보장할 수 있습니까?

저는 델파이 7 스탠다드와 제다이 이외의 다른 부품은 사용하고 싶지 않습니다.

안전한

query.SQL.Text := 'select * from table_name where name=:Name';

매개 변수를 사용하고 있으므로 이 코드는 안전합니다.
매개 변수는 항상 SQL 주입으로부터 안전합니다.

안전하지 않음

var Username: string;
...
query.SQL.Text := 'select * from table_name where name='+ UserName;

사용자 이름이 다음과 같을 수 있으므로 안전하지 않습니다.name; Drop table_name;결과적으로 다음 쿼리가 실행됩니다.

select * from table_name where name=name; Drop table_name;

또한 안전하지 않음

var Username: string;
...
query.SQL.Text := 'select * from table_name where name='''+ UserName+'''';

왜냐하면 사용자 이름이' or (1=1); Drop Table_name; --다음과 같은 쿼리가 발생합니다.

select * from table_name where name='' or (1=1); Drop Table_name; -- '

하지만 이 코드는 안전합니다.

var id: integer;
...
query.SQL.Text := 'select * from table_name where id='+IntToStr(id);

왜냐면IntToStr()정수만 허용하므로 쿼리 문자열에 SQL 코드를 주입할 수 없습니다. 숫자만 사용할 수 있습니다.

하지만 매개 변수로 수행할 수 없는 작업을 수행하고 싶습니다.

매개 변수는 값에만 사용할 수 있습니다.필드 이름이나 테이블 이름은 바꿀 수 없습니다.이 쿼리를 실행하려면

query:= 'SELECT * FROM :dynamic_table '; {doesn't work}
query:= 'SELECT * FROM '+tableName;      {works, but is unsafe}

테이블 또는 필드 이름에 매개 변수를 사용할 수 없으므로 첫 번째 쿼리가 실패합니다.
두 번째 쿼리는 안전하지 않지만 이 작업을 수행할 수 있는 유일한 방법입니다.
어떻게 안전하게 지내십니까?

당신은 문자열을 확인해야 합니다.tablename승인된 이름 목록과 비교하여.

Const
  ApprovedTables: array[0..1] of string = ('table1','table2');

procedure DoQuery(tablename: string);
var
  i: integer;
  Approved: boolean;
  query: string;
begin
  Approved:= false;
  for i:= lo(ApprovedTables) to hi(ApprovedTables) do begin
    Approved:= Approved or (lowercase(tablename) = ApprovedTables[i]);
  end; {for i}
  if not Approved then exit;
  query:= 'SELECT * FROM '+tablename;
  ...

그게 제가 아는 유일한 방법입니다.

BTW 원래 코드에 오류가 있습니다.

query.SQL.Text := 'select * from table_name where name=:Name where id=:ID'; 

그래야 한다

query.SQL.Text := 'select * from table_name where name=:Name and id=:ID'; 

두 개를 가질 수 없습니다.where한 번에 (하위) 항목에) 있습니다.

사용자가 자리 표시자를 사용하여 SQL 명령 텍스트에 바인딩될 매개 변수 값에만 영향을 미치도록 허용하면 사용자가 입력한 내용을 실제로 검사할 필요가 없습니다. 언급한 것처럼 SQL 주입을 방지하는 가장 간단한 방법은 연결된 SQL을 피하는 것입니다.그리고 경계 변수(또는 호출 절차)를 사용하면 이를 수행할 수 있습니다(또한 데이터베이스에 따라 마일리지/마일리지). 엔진이 쿼리 계획을 다시 사용할 수 있다는 이점도 있습니다.

Oracle을 사용하는 경우 바인딩된 변수를 사용하지 않는 는 충분한 이유가 있어야 합니다.Tom Kyte는 그의 사이트 http://asktom.oracle.com 에 이것에 대한 많은 좋은 정보를 가지고 있습니다.검색 상자에 "결합 변수"를 입력하기만 하면 됩니다.

이렇게 하면 최소한의 보안 수준을 보장할 수 있습니까?

테스트하기 .", "SQL"은 SQL 주입에서 를 보호합니다.위험한 문자열을 입력하기만 하면 됩니다.name변수를 사용하여 결과를 확인합니다.일반적으로 오류가 아니라 0개의 행이 반환되어야 합니다.

언급URL : https://stackoverflow.com/questions/6000648/delphi-prevent-against-sql-injection

반응형