매개 변수가 문자열이 아닌 경우 SQL 쿼리를 매개 변수화하지 않는 것이 안전합니까?


113

SQL 주입 측면 에서 매개 변수를 매개 변수화해야하는 필요성을 완전히 이해합니다 string. 그것은 책에서 가장 오래된 속임수 중 하나입니다. 그러나 매개 변수화 하지 않는 것이 언제 정당화 될 수 SqlCommand있습니까? 매개 변수화하지 않는 "안전한"데이터 유형이 있습니까?

예를 들면 : 난 아무데도 자신을 생각하지 않는다 근처 SQL 전문가,하지만 난 받아 SQL 주입에 잠재적으로 취약 할 것입니다 어떤 경우 생각할 수 없다 bool거나를 int하고 바로 질의로를 연결할.

내 가정이 맞습니까, 아니면 잠재적으로 내 프로그램에 큰 보안 취약점을 남길 수 있습니까?

설명을 위해이 질문에는 태그가 있습니다. 강력한 형식의 언어입니다. "매개 변수"라고 말하면 public int Query(int id) .


14
매개 변수를 사용하지 않으면 캐시 된 쿼리 계획의 이점을 얻지 못하며 제공하는 모든 새로운 입력 조합에 대해 별도의 쿼리 계획을 만들어야합니다.
Scott Chamberlain

5
@MatthewWhited 시간이 덜 걸린다는 것을 어떻게 알 수 있습니까? 이 상황은 현재 개발자와 이전 개발자의 특정 프로젝트에서 모든 곳에서 발생합니다. 실제로 보안이 향상되면 답변을 게시하십시오. 명확히하기 위해 분명히 매개 변수화하는 것이 더 낫다는 데 동의합니다. 하지만 그건 제 질문이 아닙니다.
johnnyRose

7
매개 변수화 된 쿼리는 주로 성능 및 최적화에 사용됩니다. SQL 주입 방지는 부작용입니다.
Salman A

13
OP가 유효한 질문을 한 것 같습니다. 그는 잠재적 인 위험을 수정하는 비용 / 편익을 평가하려고합니다. 그 방정식은 그 위험의 잠재력에 따라 변합니다. 위험이 전혀 없다면 나도 그렇게하지 않을 것입니다. 그는 당신이 시간의 가치가 있다고 생각하는지에 대한 주관적인 판단이 아니라 잠재력에 대한 기술적 질문을 요구합니다. OP는 그 전화를 걸 수있는 유일한 사람입니다.
Sir Swears-a-lot

10
나 자신을 설명하기 위해 : 나는 dba입니다. 모범 사례에 감사하고 존중하며 완벽한 세상에서는 모든 코드가 완벽 할 것입니다. 슬프게도 내가 일하는 세상에서 해결해야 할 문제가 해결해야 할 시간보다 더 많습니다. 이는 우선 순위를 의미합니다. 이미 작동하고 안전하며 허용 가능한 수준으로 수행되는 IMO 재 작성 코드는 사치처럼 들립니다. (내가 감당할 수)
경 맹세 - - 많이

답변:


101

기술적으로 는 안전하다고 생각 합니다만, 들어가는 것은 끔찍한 습관입니다. 정말로 이와 같은 쿼리를 작성하고 싶습니까?

var sqlCommand = new SqlCommand("SELECT * FROM People WHERE IsAlive = " + isAlive + 
" AND FirstName = @firstName");

sqlCommand.Parameters.AddWithValue("firstName", "Rob");

또한 유형이 정수에서 문자열로 변경되는 상황에서도 취약합니다 (이름에도 불구하고 문자를 포함 할 수있는 직원 번호를 생각해보십시오).

따라서 EmployeeNumber 유형을에서 int으로 변경 string했지만 SQL 쿼리를 업데이트하는 것을 잊었습니다. 죄송합니다.


24
AddWithValue 이미 사용을 중지 할 수 있습니까 ? blogs.msmvps.com/jcoehoorn/blog/2014/05/12/...
RemarkLima

5
@RemarkLima 값을 매개 변수에 매핑하는 코드를 동적으로 생성 할 때 해결책은 무엇입니까? 블로그 게시물은 해당 시나리오를 다루지 않습니다. 예, 알려진 경우 SQL 유형을 설정하는 한 줄이지 만 그렇지 않은 경우 문제가 있습니다 (또는 해당 정보로 모델에 주석을 추가해야 함).
casperOne 2015 년

1
그런 다음 AddWithValue명령문의 동적 작성의 일부로 데이터베이스 유형의 매핑이없는 한 계속 붙어 있습니다. 대상 열 목록이 있고 사전의 일부로 원하는 경우 유형을 가질 수 있다고 가정합니다. 그렇지 않으면 성능이 저하됩니다. 궁극적으로 제 생각을 아는 것은 좋은 정보입니다.
RemarkLima 2015 년

8
@RemarkLima 요점은 " AddWithValue이미 사용을 중지 할 수 있습니까 ?"입니다. 정말 당신이 유형을 알고 있다면, 당신은 사용을 자제해야한다 "이어야합니다 AddWithValue.
casperOne

2
이봐 요, 메신저를 쏘지 마세요, 제가 글을 쓰지 않았어요 ;-)하지만 요점은 남아 있습니다. 그리고 처음부터 당신의 디자인에 내장되어 있다면, 당신이 유형을 몰라 야 할 이유가 없습니다. 모범 사례 및 모든 재즈 :-)
RemarkLima

65

제어하는 컴퓨터 (예 : 웹 서버)에서 강력한 형식의 플랫폼을 사용하는 bool경우 DateTime, 또는 int(및 기타 숫자) 값만있는 쿼리에 대한 코드 삽입을 방지 할 수 있습니다 . 문제는 SQL Server가 모든 쿼리를 다시 컴파일하도록 강제하고 어떤 쿼리가 어떤 빈도로 실행되는지에 대한 좋은 통계를 얻지 못하도록함으로써 발생하는 성능 문제입니다 (캐시 관리에 문제가 있음).

그러나 "컴퓨터에서 제어하는"부분은 중요합니다. 그렇지 않으면 사용자가 임의의 텍스트를 포함하도록 해당 값에서 문자열을 생성하기 위해 시스템에서 사용하는 동작을 변경할 수 있기 때문입니다.

장기적으로 생각하는 것도 좋아합니다. 오늘날의 오래되고 파열 된 강력한 유형의 코드 기반이 자동 번역을 통해 새로운 인기 동적 언어로 이식되고 갑자기 유형 검사를 잃어 버리지 만 동적 코드에 대한 올바른 단위 테스트가 아직 없을 때 어떻게됩니까? ?

실제로 이러한 값에 쿼리 매개 변수를 사용하지 않을 이유가 없습니다. 이 문제를 해결하는 올바른 방법 입니다. 값이 실제로 상수 일 때 SQL 문자열에 하드 코딩하십시오. 그렇지 않으면 매개 변수를 사용하지 않는 이유는 무엇입니까? 어려운 게 아니에요.

궁극적으로 나는 이것을 버그 라고 부르지 않을 것이지만 냄새 라고 부를 것입니다. 그 자체로는 버그에 미치지 못하지만 버그가 근처에 있거나 결국있을 것이라는 강력한 표시입니다. 좋은 코드는 냄새를 남기지 않으며 좋은 정적 분석 도구는이를 표시합니다.

불행히도 이것은 당신이 바로 이길 수있는 종류의 논쟁이 아니라고 덧붙일 것입니다. "올바른"것으로는 더 이상 충분하지 않은 상황처럼 들리며,이 문제를 스스로 해결하기 위해 동료의 발걸음을 밟는 것은 좋은 팀 역학을 촉진하지 못할 것입니다. 궁극적으로 도움이되는 것보다 더 많은 상처를 입을 수 있습니다. 이 경우 더 나은 접근 방식은 정적 분석 도구의 사용을 촉진하는 것입니다. 그것은 목표로하고 되돌아 가고 기존 코드를 수정하는 노력에 정당성과 신뢰성을 줄 것입니다.


1
매개 변수화를 수행하는 것은 확실히 도전이 아닙니다. 내 질문은 동료가 정수 값을 연결하는 많은 쿼리를 작성했기 때문에 발생했으며, 모든 것을 검토하고 수정하는 것이 내 시간 낭비인지 궁금합니다.
johnnyRose

2
나는 "버그인가"라는 질문이 내 질문의 결론이라고 생각한다.
johnnyRose

7
그것은 "냄새"입니다. 버그 자체로는 부족하지만 근처에 버그가있을 가능성이 있음을 나타내는 것입니다. 좋은 코드는 냄새를 제거하려고합니다. 좋은 정적 분석 도구는 확실히 플래그를 지정합니다.
Joel Coehoorn 2015 년

1
나는 "냄새"라는 용어를 좋아합니다. 나는 대신에 "애벌레"와 같은 것을 사용했을 것인데, 아직 버그는 아니지만, 향후 업데이트는 그것을 부수거나 훈증 할 때까지 백엔드에서 먹을 구더기로 잡을 수 있습니다. 여러분은 분명히 프로덕션 환경에서 괴사 코드가 발생할 가능성을 원하지 않으며,이 경우와 같이 일정량의 기교로 개발되지 않은 무언가를 가질 수 있습니다.
CSS

1
이것은 단지 잘못된 것입니다. DateTime또는 사용하여 SQL 주입을 만드는 방법에 대한 내 대답을 참조하십시오.int
Kaspars Ozols

53

어떤 경우에는 문자열 값이 아닌 매개 변수화되지 않은 (연결된) 변수로 SQL 주입 공격을 수행 할 수 있습니다. Jon의이 기사를 참조하십시오. http://codeblog.jonskeet.uk/2014/08/08/the-bobbytables -culture / .

문제는를 ToString호출하면 일부 사용자 지정 문화 공급자가 문자열이 아닌 매개 변수를 문자열 표현으로 변환하여 일부 SQL을 쿼리에 삽입 할 수 있다는 것입니다.


14
나는 이것이 본질적으로 " ints로 어떻게 주입이 가능할 수 있습니까?"라는 질문에 대답하는 유일한 게시물이라고 생각합니다.
Arturo Torres Sánchez

3
booby와 같은 사용자 지정 코드를 삽입 할 수있는 위치에 있다면 CultureInfo어쨌든 SQL 삽입이 필요한 이유를 알기가 어렵습니다.
Martin Smith

플러스 1,있는 유일한 대답은 실제로는 응답 질문
ken2k

@MartinSmith : 외부에서 CultureInfo를 변경하는 한 가지 가능한 방법을 보여주는 내 대답을 참조하십시오.
user1027167

사람이 이러한 코드를 응용 프로그램에 작성할 수 있다면 왜 SQL 주입이 필요합니까?
Reza Aghaei 2015 년

51

입니다 하지 심지어 문자열이 아닌 유형에 대한 안전합니다. 항상 매개 변수를 사용하십시오. 기간.

다음 코드 예제를 고려하십시오.

var utcNow = DateTime.UtcNow;
var sqlCommand = new SqlCommand("SELECT * FROM People WHERE created_on <= '" + utcNow + "'");

언뜻보기에 코드는 안전 해 보이지만 Windows 국가 별 설정을 일부 변경하고 짧은 날짜 형식으로 삽입을 추가하면 모든 것이 변경됩니다.

날짜 시간 주입

이제 결과 명령 텍스트는 다음과 같습니다.

SELECT * FROM People WHERE created_on <= '26.09.2015' OR '1'<>' 21:21:43'

intSQL 인젝션으로 쉽게 변경할 수있는 사용자 정의 음의 부호를 사용자 정의 할 수 있으므로 유형에 대해서도 동일하게 수행 할 수 있습니다.

현재 문화 대신 불변 문화를 사용해야한다고 주장 할 수 있지만 이와 같은 문자열 연결을 너무 많이 보았고 +.


10
누가 서버 설정을 변경할 수 있습니까? 사람이 서버에서 할 수 있다면 데이터를 파괴하기 위해 SQL 주입이 필요하지 않습니다.
Reza Aghaei 2015 년

5
이것이 최선의 대답이며, 이것은 버그 / 보안 결함에 대한 OP 우려를 검증하는 한 가지 방법을 보여줍니다. 예를 들어 SQL에서 날짜 시간을 연결하는 것 외에 성능 및 미래 보장은 단순한 냄새기술 부채 가 아닙니다 . @RezaAghaei 질문은 Server-Side를 언급 한 적이 없습니다. SQLExpress가있는 Windows 앱일 수 있습니다. 어느 쪽이든 질문의 기준이 아닙니다. 누구나 말할 수 있지만, 누가 공유 서버 호스팅이나 Y2K 버그에 대해 말할 수있는 것처럼이 훌륭한 대답에 반박하기 위해 서버 설정에 액세스 할 수있는 사람입니다. 나는 당신에게 서버가 잠겨 있다는 것에 동의합니다-단지 전제 조건이 아닙니다.
Jeremy Thompson

2
int유형 에 대해 말한 예를 제공 할 수 있습니까?
johnnyRose 2015 년

1
답변하신 지 몇 주가 지났지 만 게시물을 편집하고 사용자 지정 음수 부호를 정의하는 방법에 대한 예를 추가 할 수 있습니까?
johnnyRose

23

"SELECT * FROM Table1 WHERE Id ="+ intVariable.ToString ()


보안
괜찮습니다.
공격자는 입력 한 int 변수에 아무것도 삽입 할 수 없습니다.

성능이
좋지 않습니다.

매개 변수를 사용하는 것이 더 좋으므로 쿼리가 한 번 컴파일되고 다음 사용을 위해 캐시됩니다. 다음에 다른 매개 변수 값을 사용해도 쿼리가 캐시되고 데이터베이스 서버에서 컴파일 할 필요가 없습니다.

코딩 스타일
나쁜 습관.

  • 매개 변수가 더 읽기 쉽습니다.
  • 매개 변수가없는 쿼리에 익숙해 지거나 한 번 실수를해서 이런 식으로 문자열 값을 사용한 다음 데이터에 작별 인사를해야 할 수도 있습니다. 나쁜 습관!


"SELECT * FROM Product WHERE Id ="+ TextBox1.Text


귀하의 질문은 아니지만 향후 독자에게 유용 할 수 있습니다.

보안
재난! 필드가 정수인
경우에도 Id쿼리에 SQL 주입이 적용될 수 있습니다. 애플리케이션에 쿼리가 있다고 가정하면 "SELECT * FROM Table1 WHERE Id=" + TextBox1.Text공격자가 텍스트 상자에 삽입 할 수 1; DELETE Table1있으며 쿼리는 다음과 같습니다.

"SELECT * FROM Table1 WHERE Id=1; DELETE Table1"

여기서 매개 변수화 된 쿼리를 사용하지 않으려면 입력 된 값을 사용해야합니다.

string.Format("SELECT * FROM Table1 WHERE Id={0}", int.Parse(TextBox1.Text))


귀하의 질문


내 질문은 동료가 정수 값을 연결하는 많은 쿼리를 작성했기 때문에 발생했으며, 모든 것을 검토하고 수정하는 것이 내 시간 낭비인지 궁금했습니다.

이 코드를 변경하는 것은 시간 낭비가 아니라고 생각합니다. 과연 변화를 추천합니다!

동료가 int 변수를 사용하는 경우 보안 위험은 없지만 해당 코드를 변경하는 것은 시간 낭비가 아니며 실제로 해당 코드를 변경하는 것이 좋습니다. 이는 코드를 더 읽기 쉽고, 유지 관리하기 쉽게 만들고, 실행 속도를 더 빠르게합니다.


첫 번째 옵션조차도 보안에 전혀 문제가 없습니다. 의 동작 .ToString()은 임의의 텍스트를 포함하도록 변경하기 쉬운 운영 체제 구성 항목에 의해 결정됩니다.
Joel Coehoorn

18

실제로 하나에 두 가지 질문이 있습니다. 그리고 제목의 질문은 이후 의견에서 OP가 표현한 우려와 거의 관련이 없습니다.

OP의 경우 중요한 것은 그들의 특별한 경우라는 것을 알고 있지만, Google에서 오는 독자에게는보다 일반적인 질문에 대답하는 것이 중요합니다. 내가 연결하는 모든 문자가 안전하다는 것을? ". 그래서 저는이 후자에 집중하고 싶습니다. 그리고 대답은

확실히 아니오.

대부분의 독자들이 바라는 것처럼 직접적인 설명은 아니지만 최선을 다하겠습니다.

나는 그 문제에 대해 잠시 숙고 해 왔고, 그 결과 모든 것을 요약하려고 노력한 기사 (PHP 환경을 기반으로 함)가 나왔다. SQL 인젝션으로부터의 보호에 대한 질문은 종종 문자열 이스케이프, 타입 캐스팅 등과 같은 관련이 있지만 더 좁은 주제로 빠져 나간다는 생각이 들었습니다. 일부 조치는 스스로 취하면 안전한 것으로 간주 될 수 있지만 시스템이 없으며 따라야 할 간단한 규칙도 없습니다. 이로 인해 개발자의 관심과 경험에 너무 많은 영향을 미치면서 매우 미끄러운 땅이됩니다.

SQL 주입 문제는 특정 구문 문제로 단순화 할 수 없습니다. 일반적인 개발자가 생각하는 것보다 넓습니다. 그것은의 방법 론적 아니라 질문입니다. "적용해야하는 특정 서식"뿐만 아니라 " 어떻게 수행해야 하는가 "도 중요합니다.

(이 관점에서 다른 답변에 인용 된 Jon Skeet의 기사는 일부 엣지 케이스를 다시 골라 내고 특정 구문 문제에 집중하고 문제를 전체적으로 해결하지 못하기 때문에 좋지 않은 것입니다.)

보호 문제를 전체가 아니라 다양한 구문 문제로 해결하려고 할 때 많은 문제에 직면하게됩니다.

  • 가능한 서식 선택 목록은 정말 엄청납니다. 쉽게 일부를 간과 할 수 있음을 의미합니다. 또는 ( 예를 들어 식별자문자열 이스케이프를 사용하여) 혼동하십시오 .
  • 연결은 모든 보호 조치가 프로그램이 아닌 프로그래머에 의해 수행되어야 함을 의미합니다. 이 문제만으로도 몇 가지 결과가 발생합니다.
    • 이러한 형식은 수동입니다. 수동은 오류가 매우 발생하기 쉽다 는 것을 의미 합니다. 신청하는 것을 잊을 수 있습니다.
    • 더욱이, 포맷팅 절차를 중앙 집중화 된 기능으로 옮기고, 일을 더 엉망으로 만들고, 데이터베이스로 보내지 않는 데이터를 망칠 유혹이 있습니다.
  • 둘 이상의 개발자가 참여하면 문제가 10 배로 증가합니다.
  • 연결을 사용하면 잠재적으로 위험한 쿼리를 한 눈에 알 수 없습니다. 모두 잠재적으로 위험합니다!

그 혼란과는 달리 준비된 진술은 실제로 성배입니다.

  • 따라하기 쉬운 하나의 간단한 규칙의 형태로 표현할 수 있습니다.
  • 이는 본질적으로 신뢰할 수없는 조치이며 개발자가 방해 할 수 없으며 기꺼이 또는 의도하지 않게 프로세스를 망칠 수 없음을 의미합니다.
  • 주입으로부터의 보호는 실제로 준비된 명령문 의 부작용 일 뿐이며 실제 목적은 구문 적으로 올바른 명령문을 생성하는 것입니다. 그리고 구문 상 올바른 진술은 100 % 주입 증명입니다. 그러나 주입 가능성에도 불구하고 올바른 구문이 필요합니다.
  • 끝까지 사용하면 개발자의 경험에 관계없이 응용 프로그램을 보호합니다. 2 차 주입 이라는 것이 있습니다. 그리고 "보호하기 위해 모든 사용자가 제공 한 입력을 이스케이프 "라는 매우 강력한 착각입니다 . 함께 결합하면 개발자가 자유로이 결정하여 보호해야 할 사항과 보호해야 할 사항을 결정하는 경우 주입으로 이어집니다.

(더 생각해 보면, 현재 자리 표시 자 세트는 실제 요구 사항에 충분하지 않으며 배열과 같은 복잡한 데이터 구조와 SQL 키워드 또는 식별자까지 확장해야합니다. 쿼리도 동적으로 수행되지만 개발자는 이러한 경우에 대해 비무장 상태로 남겨져 문자열 연결로 대체해야하지만 이는 다른 질문의 문제입니다).

흥미롭게도이 질문의 논란은 Stack Overflow의 매우 논란이 많은 성격에 의해 유발되었습니다. 이 사이트의 아이디어는 검색을 통해 오는 사용자에게 적합한 범용 답변 데이터베이스를 갖는 목표를 달성하기 위해 직접 요청하는 사용자특정 질문 을 활용하는 것입니다 . 아이디어 자체 는 나쁘지 않지만 다음과 같은 상황에서는 실패합니다. 사용자가 매우 좁은 질문을 할 때 , 특히 동료와의 분쟁에서 논쟁을 벌일 때 (또는 코드를 리팩토링 할 가치가 있는지 결정하기 위해) 실패합니다 . 경험이 많은 참가자 대부분이 답변을 작성하려고하지만 임무 를 염두에두고 전체적으로 스택 오버플로에 대한 답변은 OP뿐 아니라 가능한 한 많은 독자에게 좋은 답변을 제공합니다.


10
질문 응답 없음
edc65

대부분의 데이터베이스는 SQL 문자열 동등성에 의해 이미 사용 된 매개 변수화 된 쿼리를 감지하므로 이전 준비 및 사용 핸들 방법은 구식 인 것 같습니다. 이러한 핸들은 특정 범위 내에서만 사용할 수 있으며 핸들을 추적하려면 코딩이 필요합니다. 제 생각에는 매개 변수화 된 쿼리를 직접 사용해야하므로 핸들 추적없이 다른 애플리케이션에서도 쿼리 계획을 재사용 할 수 있습니다.
Erik Hart

15

보안 또는 형식 안전 고려 사항에 대해서만 생각하지 마십시오.

매개 변수화 된 쿼리를 사용하는 이유는 데이터베이스 수준에서 성능을 향상시키기 위해서입니다. 데이터베이스 관점에서 매개 변수화 된 쿼리는 SQL 버퍼에있는 하나의 쿼리입니다 (모든 데이터베이스가 내부적으로 유사한 개념을 가지고 있다고 생각하지만 Oracle의 용어를 사용하기 위해). 따라서 데이터베이스는 준비되고 실행할 준비가 된 메모리에 일정량의 쿼리를 저장할 수 있습니다. 이러한 쿼리는 구문 분석 할 필요가 없으며 더 빠릅니다. 자주 실행되는 쿼리는 일반적으로 버퍼에 있으며 사용할 때마다 구문 분석이 필요하지 않습니다.

제외

누군가 매개 변수화 된 쿼리를 사용하지 않습니다. 이 경우 버퍼는 거의 동일한 쿼리의 스트림을 통해 지속적으로 플러시되며, 각 쿼리는 데이터베이스 엔진에 의해 구문 분석되고 실행되어야하며 자주 실행되는 쿼리조차 여러 번 다시 구문 분석되므로 성능이 전반적으로 저하됩니다. 일. 저는 생계를 위해 데이터베이스를 조정했으며 이것이 가장 큰 열매를 맺는 가장 큰 원천 중 하나였습니다.

지금

질문에 답하기 위해 쿼리에 고유 한 숫자 값이 적 으면 문제가 발생하지 않고 실제로 성능이 극히 향상 될 수 있습니다. 그러나 잠재적으로 수백 개의 값이 있고 쿼리가 많이 호출되면 시스템 성능에 영향을 미치므로 그렇게하지 마십시오.

예, SQL 버퍼를 늘릴 수 있지만 궁극적으로 인덱스 또는 데이터 캐싱과 같은 메모리에 대한 다른 더 중요한 사용을 희생해야합니다. 도덕적, 매우 종교적으로 매개 변수화 된 쿼리를 사용하여 데이터베이스를 최적화하고 중요한 작업에 더 많은 서버 메모리를 사용할 수 있습니다.


8

Maciek 답변에 정보를 추가하려면 :

리플렉션을 통해 어셈블리의 주요 기능을 호출하여 .NET 타사 앱의 문화 정보를 쉽게 변경할 수 있습니다.

using System;
using System.Globalization;
using System.Reflection;
using System.Threading;

namespace ConsoleApplication2
{
  class Program
  {
    static void Main(string[] args)
    {
      Assembly asm = Assembly.LoadFile(@"C:\BobbysApp.exe");
      MethodInfo mi = asm.GetType("Test").GetMethod("Main");
      mi.Invoke(null, null);
      Console.ReadLine();
    }

    static Program()
    {
      InstallBobbyTablesCulture();
    }

    static void InstallBobbyTablesCulture()
    {
      CultureInfo bobby = (CultureInfo)CultureInfo.InvariantCulture.Clone();
      bobby.DateTimeFormat.ShortDatePattern = @"yyyy-MM-dd'' OR ' '=''";
      bobby.DateTimeFormat.LongTimePattern = "";
      bobby.NumberFormat.NegativeSign = "1 OR 1=1 OR 1=";
      Thread.CurrentThread.CurrentCulture = bobby;
    }
  }
}

이것은 BobbysApp의 주요 기능이 공개 된 경우에만 작동합니다. Main이 공용이 아닌 경우 호출 할 수있는 다른 공용 함수가있을 수 있습니다.


1
코드로 할 필요조차 없습니다. Windows 국가 별 설정에서 직접 주입을 추가 할 수 있습니다. 내 대답을 참조하십시오.
Kaspars Ozols 2015 년

2
누가 서버 설정을 변경할 수 있습니까? 또는 누가 그러한 코드를 서버에서 쓸 수 있습니까? 사람이 서버에서 할 수 있다면 데이터를 파괴하기 위해 SQL 주입이 필요하지 않습니다.
Reza Aghaei 2015 년

7

제 생각에는 작업하는 매개 변수에 문자열이 포함되지 않는다는 것을 보장 할 수 있다면 안전하지만 어떤 경우에도 그렇게하지 않을 것입니다. 또한 연결을 수행하고 있기 때문에 약간의 성능 저하를 볼 수 있습니다. 내가 물어볼 질문은 왜 매개 변수를 사용하고 싶지 않습니까?


1
매개 변수를 사용하고 싶지 않은 것이 아니라 매개 변수를 사용하고 있습니다. 동료가 오늘 매개 변수화되도록 수정 한 이와 같은 코드를 작성하여 질문을 생각하게되었습니다.
johnnyRose

확인. 큰. 매개 변수를 사용하는 것이 모범 사례입니다. 이렇게하면 SQL 주입과 같은 것에 대해 걱정할 필요가 없습니다. 또한 동적 쿼리를 작성하는 경우 쿼리의 복잡성에 관계없이 매개 변수를 사용할 수도 있습니다. 빌드 할 때 @ 1 ... @ n 스타일을 사용하면됩니다. 그리고 원하는 값으로 매개 변수 컬렉션에 추가합니다.
Max

@johnyRose 매개 변수를 사용하는 또 하나의 요점이 있습니다. 프로그램은 진화하고 변화하고 있습니다. 문자열에 대해서만 연결을 사용할 수 있지만 누군가가 일부 매개 변수 유형을 변경하는 리팩토링을 구현하고 변경으로 인해 SQL 주입 취약점이 발생할 수 있다는 보장은 없습니다.
lerthe61

3

괜찮지 만 절대 안전하지 않습니다 .. 보안은 항상 입력에 의존합니다. 예를 들어 입력 개체가 TextBox 인 경우 공격자는 텍스트 상자가 문자열을받을 수 있으므로 까다로운 작업을 수행 할 수 있으므로 일종의 유효성 검사 / 변환을 입력해야합니다. 사용자의 잘못된 입력을 방지 할 수 있습니다. 그러나 문제는 안전하지 않다는 것입니다. 그렇게 간단합니다.


그래도 문자열입니다. 정수, 부울 또는 날짜 시간과 같은 다른 데이터 유형에 대해 이야기하고 있습니다.
johnnyRose 2015 년

@johnnyRose Yup, 나는 Kaspards ..에 의해 답변 된 것으로 표시 한 아주 좋은 예를 보았습니다. 그리고 그가 드문 예로서 datetime 데이터 유형을 사용함에 따라 훌륭한 답변을 받았습니다. :) 난 당신이 이미 데이터 유형의 모든 종류에보다 효율적으로 사용하는 매개 변수가 안전하지 않습니다 확신과 희망
japzdivino

매개 변수를 사용하는 것이 더 안전하다는 사실을 의심하지 않았습니다. 내 질문은 강력한 형식의 구현을 언급했습니다.
johnnyRose

네 .. 동의합니다. 그것은 : 캔 도움말 미래의 리더가 좋은 질문도
japzdivino

-2

그런 식으로 SQL 주입 공격을받을 수 없습니다. 나는 여기에 방법을 보여주는 터키어로 오래된 기사를 썼다 . PHP 및 MySQL의 기사 예제이지만 개념은 C # 및 SQL Server에서 동일하게 작동합니다.

기본적으로 다음과 같은 방식으로 공격합니다. 정수 ID 값에 따라 정보를 표시하는 페이지가 있다고 가정 해 보겠습니다. 아래와 같이 값을 매개 변수화하지 않습니다.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=24

좋아, 나는 당신이 MySQL을 사용하고 있다고 가정하고 다음과 같은 방식으로 공격합니다.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=ASCII((SELECT%20DATABASE()))

여기에 삽입 된 값은 문자열이 아닙니다. ASCII 함수를 사용하여 char 값을 int로 변경합니다. SQL Server에서 "CAST (YourVarcharCol AS INT)"를 사용하여 동일한 작업을 수행 할 수 있습니다.

그 후 길이 및 하위 문자열 함수를 사용하여 데이터베이스 이름을 찾습니다.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=LEN((SELECT%20DATABASE()))

http://localhost/sqlEnjeksiyon//instructors.aspx?id=ASCII(SUBSTR(SELECT%20DATABASE(),1,1))

그런 다음 데이터베이스 이름을 사용하여 데이터베이스에서 테이블 이름을 가져 오기 시작합니다.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=ASCII(SUBSTR((SELECT table_name FROM INFORMATION_SCHEMA.TABLES LIMIT 1),1,1))

물론이 과정을 자동화해야합니다. 쿼리 당 하나의 문자 만 얻을 수 있기 때문입니다. 하지만 쉽게 자동화 할 수 있습니다. 내 기사는 watir의 한 예를 보여줍니다 . 매개 변수화 된 ID 값이 아닌 한 페이지 만 사용합니다. 나는 당신의 데이터베이스에있는 모든 테이블 이름을 배울 수 있습니다. 그 후에 중요한 테이블을 찾을 수 있습니다. 시간이 걸리 겠지만 가능합니다.


2
내 질문은 강력한 유형의 언어에 관한 것입니다. 유연한 타이핑을 사용하는 언어에 대한 설명은 훌륭하지만 삽입 된 값은 여전히 ​​문자열입니다.
johnnyRose 2015 년

주입 된 값은 정수가 아닙니다. char를 얻고 ASCII MySQL 함수를 사용하여 정수로 변경합니다. CAST (YourCharValue AS INT)를 사용하여 SQL Server에서 동일한 작업을 수행합니다.
Atilla Ozgur

나는 다음과 같은 것을 의미했습니다 :public void QuerySomething(int id) { // this will only accept an integer }
johnnyRose

-3

글쎄요 ... 한 가지는 확실합니다 : 보안은 당신이 SQL 명령 문자열과 문자열 (사용자가 가져간)을 연결할 때 괜찮지 않습니다. where 절이 Integer 또는 모든 유형을 참조 할 때마다 중요하지 않습니다. 주사가 발생할 수 있습니다.

SQL Injection에서 중요한 것은 사용자로부터 값을 가져 오는 데 사용되는 변수의 데이터 유형입니다.

where 절에 정수가 있다고 가정합니다.

  1. 사용자 변수는 문자열입니다. 그렇다면 (UNION을 사용하여) 주입하는 것은 그리 쉽지 않지만 'OR 1 = 1'을 사용하여 우회하는 것은 매우 쉽습니다.

  2. 사용자 변수가 정수인 경우. 그런 다음 다시 시스템 충돌 또는 숨겨진 버퍼 오버플로 (최종 문자열)에 대한 비정상적인 큰 숫자 테스트를 통과하여 시스템의 강도를 '테스트'할 수 있습니다 ...;)

쿼리에 대한 매개 변수 또는 저장 프로 시저에 대한 매개 변수 (더 나은-imo)가 100 % 위협에 안전하지는 않지만이를 최소화하는 데 필요한 최소한의 조치 (또는 선호하는 경우 기본 조치)입니다.


질문을 오해 하셨을 것 같습니다. 문자열이 아닌 유형 에 대해 이야기하고 있습니다.
johnnyRose 2015 년

안녕 JonnyRose ... 메모 감사합니다. 나는 귀하의 질문을 이해하지만 더 일반적인 형식으로 대답을 넣었습니다. 비 문자열 케이스의 경우 내 (2) 포인트를 확인하십시오. ;)
Andreas Venieris 2015 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.