2014-12-27 3 views
0

에 의해 쿼리와 SQL 주입을 피 ActiveRecord::Base.connection.execute(USER_INPUT) 쿼리 문자열 (그들은 어떤 time period과 URL에 의해 product_type를 조회 할 수 있습니다 사용자 입력에 의해 주어진다나는 방법으로 쿼리 할 필요가 액티브 :: Base.connection.execute

)

SQL 삽입을 방지하려면 어떻게합니까? 내 시스템 손상을 방지하려면?

은 가능한 사용자는

+0

그걸 갖고 싶어서 이상하게 보입니다. 가능한 세분화 된 명령 집합을 가질 수 있습니까? 또한 SQL 인젝션은 아무 것도 넣지 않는 방식으로, 사용자 입력입니다. 사용자 입력을 받아들이 기위한 정책을 생각해내는 몇 가지 규칙을 제공해야합니다. – xlembouras

+4

수 없습니다. 사용자로부터 SQL을 받아들입니다. 문을 열고 "들어 와서 원하는 SQL을 실행하십시오"라고 말하면 SQL "삽입"을 방지하는 것은 의미가 없습니다. 어떤 종류의 SQL 명령 *이 실행될 수 있는지 제한하기 위해 * 사용자 입력을 필터링하려고합니까? –

답변

1

DELETE, TRUNCATE, INSERT, UPDATE ... 난 당신이 찾고있는 무슨 생각을 제외하고 SELECT를 조회 할 수 quote

sql = ActiveRecord::Base.connection.quote(potentially harmful string) 
res = ActiveRecord::Base.connection.execute(sql) 

되는 제한 또한 사용할 수 있나요 sanitize_sql_array :

sql = ActiveRecord::Base.send(:sanitize_sql_array, sql_array) 
res = ActiveRecord::Base.connection.execute(sql) 
+0

OP는 단순히 위생 처리를 원하지 않습니다. - SELECT가 아닌 경우 쿼리를 거부하고 싶습니다. – Humza

0

실행할 수있는 권한을 부여한 다른 사용자를 해당 데이터베이스에 생성합니다. SELECT 검색어. 이 제한된 사용자 계정을 사용하여 사용자 입력에서 생성 된 쿼리를 실행합니다.

4

내가 원하는 것을 이해했다면, 실제로 SQL 주입을 전혀 원하지 않을 것입니다. 사실, 앱이 디자인에 따라 임의의 SQL을 실행할 수 있도록 허용하고 있습니다.

SQL이 실행되도록 제한하는 것이 좋습니다.

이것은 실패 할 운명입니다. 최소한 PostgreSQL에서 SELECT은 권한이있는 사용자가 호출 할 때 일반 사용자가 실행하지 못하도록하는 모든 종류의 기능을 실행할 수 있습니다. 또한 사용자는 반드시 알 필요가없는 정보로 가득 찬 시스템 카탈로그에 액세스 할 수 있습니다.

단일 SQL 문자열에 여러 명령을 포함 할 수 없도록하는 구문 분석기를 성공적으로 작성한 경우에도 명령 유형 으로 필터링하면이 작동하지 않습니다. 희망만큼이나 단순하지 않습니다. 당신은 standard_conforming_strings 리터럴을 위해 켜기와 끄기, $$ 따옴표, 식별자 따옴표, --, /* */ 등을 처리해야합니다. 이됩니다. 필터에 구멍이 있거나 완벽하게 합법적 인 명령을 금합니다.

사용자로부터 명령을 실행할 때 권한이 낮은 데이터베이스 역할을 사용하는 것이 조금 더 안전한 방법입니다. 이 역할은 명시 적으로 무엇을 읽을 권리가 있어야합니다. GRANTINSERT, UPDATE 또는 DELETE 권한이없고 테이블이나 다른 개체 소유권이 없어야하며 물론 수퍼 유저가 아니어야합니다. 사용자가 원하는 SQL을 보내거나 필터링을 시도 할 수는 있지만 데이터베이스의 액세스 권한을 사용하여 장난 치는 것을 막을 수 있습니다. SET TRANSACTION READ ONLY도 가능하지만 이러한 설정은 대부분 권장 사항이며 엄격한 제한 사항이 아니라는 것을 알고 있어야합니다.

필자가 아는 한 레일스는 권한없는 연결을 쉽게하거나 업그레이드보다 덜 특권있는 연결로 작업하도록 만들지 않습니다. 레일스는 모든 것을 하나의 데이터베이스 사용자, 일반적으로 모든 객체를 소유하는 매우 특권있는 사용자로 생각하여 언제든지 마이그레이션을 수행 할 수 있기를 바랍니다. Rails/ActiveRecord 철학의 일부입니다. 데이터베이스는 멍청한 행 저장소가 아닙니다.

더 유연한 프레임 워크 인 경우에도 다른 사용자 권한으로 연결하는 것이 여전히 고통 스럽습니다. SET ROLE 또는 SET SESSION AUTHORIZATION이 작동하지만 양쪽 모두 권한있는 연결을 얻으려면 재설정 할 수 있습니다. 현재는 PostgreSQL에서 권한을 삭제할 생각이 없습니다. 사용자가 RESET ROLE 또는 RESET SESSION AUTHORIZATION을 몰래 사용하여 임의의 SQL에서 편안하게 사용할 수있는 방법이 너무 많습니다. 따라서 실제로 다른 자격 증명으로 새 연결을 만들어야합니다.

그게 내가하는 일이다. 다른 자격 증명으로 새 연결을 만들고 SQL을 매우 제한된 사용자 계정으로 실행하십시오. REVOKE과 같이이 계정에서 pg_procpg_class을 볼 수 있으며 시스템 카탈로그의 표시량을 제한하고 실제로 필요한 테이블에 대한 최소 액세스 권한 만 부여 할 수 있습니다. (REVOKE CREATE ON SCHEMA public FROM public을 기억하고 GRANT은 테이블을 만들려는 사용자에게만 돌아갑니다).

+0

Rails ActiveRecord (필자가 작성한 ORM을 포함한 모든 ORM)는 스트레이트 재킷의 쓰레기입니다. "친숙한"및 "휴대용"모든 것을 우회하여 기본 [pg 인터페이스] (http://www.rubydoc.info/github/ged/ruby-pg)와 대화하면 더 많은 유연성을 누릴 수 있습니다. 전체 "데이터베이스에 사용자 제공 SQL 보내기"것은 여전히 ​​내게 의지를 제공합니다. –

+0

@muistooshort 예. 나는 대부분의 경우 그것을하지 않을 것입니다 - 가능한 경우 제한된 쿼리 DSL을 사용합니다. 필요한 상황을 상상할 수는 있지만 대부분의 경우 제한된 역할을 가진 psql을 통해 사용자를 직접 참여 시키려고합니다. –

1

내 응용 프로그램 내에서 일종의 "dataclips"(Heroku 스타일)를 만들려고 비슷한 문제가 발생했습니다. 내 문제는 "내 응용 프로그램 사용자가 임의의 SQL을 읽기 전용 모드로 실행하는 방법"이라고 설명 하겠지만.

는 특정 데이터베이스 사용자를위한 필요없이 가장 우아한 해결책이었다 :

ActiveRecord::Base.transaction do 
    results = ActiveRecord::Base.connection.select_all sql 
    do_your_stuff_here_with results 
    raise ActiveRecord::Rollback 
end 
액티브 :: 롤백 아무것도 방지 트랜잭션을 롤백됩니다 인상을 지속 할

의 외부 다시 발생하지에서 제외 트랜잭션 블록.

select_all은 libpq에서 준비된 명령문 인터페이스를 다루기 때문에 다중 명령문의 사용을 금지합니다.