미국 정부가 안전한 프로젝트를 위해 동적 언어를 허용하지 않는 이유는 무엇입니까? 보고서를 반환했습니다. 해결해야 할

나는 현재 미군을위한 프로젝트 (낮은 보안 수준, 비 전략 인적 자원 유형 데이터)를 수행하고있는 사람들을 알고 있습니다.

프로젝트 코드의 초기 상태는 검토를 위해 군대에 제출되었으며 일종의 보안 분석기 도구를 통해 프로그램을 실행했습니다. 코드에 알려진 보안 문제와 최종 제품을 제공하기 전에 구현해야하는 변경 사항에 대한 보고서를 반환했습니다.

해결해야 할 항목 중 하나는 동적 언어이므로 Ruby 로 작성된 프로젝트의 일부를 제거하는 것이 었 습니다.

보안 설정에서 동적 언어를 사용할 수없는 배경 / 이유는 무엇입니까? 정부가 새로운 기술을 채택하는 데 시간이 오래 걸립니까? 또는 동적 언어가 정적 언어 (ala C ++ 또는 Java )에 비해 추가 보안 위험이 있습니까?



답변

주어진 코드의 기능에 대해 다른 프로그래머 나 감사관에게 즉시 알 수없는 코드의 일부에 자리 잡을 수있는 동적 언어로 수행 할 수있는 여러 가지 ‘단순한’작업이 있습니다.

irb (대화식 루비 쉘)에서이 시퀀스를 고려하십시오.

irb(main):001:0> "bar".foo
NoMethodError: undefined method `foo' for "bar":String
        from (irb):1
        from /usr/bin/irb:12:in `<main>'
irb(main):002:0> class String
irb(main):003:1> def foo
irb(main):004:2> "foobar!"
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> "bar".foo
=> "foobar!"

거기에 일어난 일은 fooString 상수로 메소드를 호출하려고했습니다 . 실패했습니다. 그런 다음 String 클래스를 열고 메소드 fooo return을 정의한 "foobar!"후 호출했습니다. 이것은 효과가 있었다.

이것은 공개 클래스로 알려져 있으며 보안 또는 무결성이있는 루비로 코드를 작성할 때마다 악몽을 낳습니다. 물론 그것은 당신이 아주 깔끔한 일을 할 수있게 해줍니다 …하지만 누군가가 문자열을 저장할 때마다 파일에 저장하거나 네트워크를 통해 보낼 수 있습니다. 그리고 문자열을 재정의하는이 작은 부분은 코드의 어느 곳에 나 들어갈 수 있습니다.

다른 많은 동적 언어들도 비슷한 일을 할 수 있습니다. Perl에는 Tie :: Scalar 가있어 장면 뒤에서 주어진 스칼라의 작동 방식을 변경할 수 있습니다 (이것은 좀 더 분명하고 볼 수있는 특정 명령이 필요하지만 다른 곳에서 전달 된 스칼라는 문제가 될 수 있습니다). Perl Cookbook에 접근 할 수 있다면 Recipe 13.15-넥타이로 마법 변수 생성하기를 참조하십시오.

이러한 것들 (및 다른 언어는 종종 동적 언어의 일부) 때문에 코드에서 보안의 정적 분석에 대한 많은 접근 방식이 작동하지 않습니다. Perl과 Undecidability 는 이것이 사실임을 보여주고 구문 강조와 같은 사소한 문제조차 지적합니다 ( 런타임 에서 구문 강조 또는 정적 분석기를 완전히 물리 치는 인수를 취하거나 정의하지 whatever / 25 ; # / ; die "this dies!";않기 때문에 문제가 발생할 whatever수 있음 ).


이는 클로저가 정의 된 환경에 액세스 할 수있는 능력으로 Ruby에서 더욱 흥미로울 수 있습니다 ( YouTube : Joshua Ballanco의 RubyConf 2011에서 Ruby를 합리적 으로 유지하기 참조 ). MouseTheLuckyDogArs Technica 의견 에서이 비디오를 알게 되었습니다 .

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

def mal(&block)
    puts ">:)"
    block.call
    t = block.binding.eval('(self.methods - Object.methods).sample')
    block.binding.eval <<-END
        def #{t.to_s}
          raise 'MWHWAHAW!'
        end
    END
end

class Foo
    def bar
        puts "bar"
    end

    def qux
        mal do
            puts "qux"
        end
    end
end

f = Foo.new
f.bar
f.qux

f.bar
f.qux

이 코드는 완전히 보이지만 mal메소드는 다른 곳에있을 수 있습니다. 물론 열린 클래스를 사용하면 다른 곳에서 재정의 할 수 있습니다.

이 코드를 실행 :

~ / $ 루비 foo.rb
바
> :)
qux
바
b.rb : 20 :`qux ': MWHWAHAW! (런타임 에러)
    b.rb : 30 :에서` '
~ / $ 루비 foo.rb
바
> :)
qux
b.rb : 20 :`bar '에서 : MWHWAHAW! (런타임 에러)
    b.rb : 29 :에서` '

이 코드에서 클로저는 해당 범위의 클래스에 정의 된 모든 메서드 및 기타 바인딩 에 액세스 할 수있었습니다 . 임의의 방법을 선택하고 예외를 발생시키기 위해 재정의했습니다. ( 이 객체가 무엇을 액세스 할 수 있는지에 대한 아이디어를 얻으려면 Ruby 의 Binding 클래스를 참조하십시오 )

이 컨텍스트에서 액세스 할 수있는 변수, 메소드, 자체 값 및 가능한 반복자 블록이 모두 유지됩니다.

변수의 재정의를 보여주는 더 짧은 버전 :

def mal(&block)
    block.call
    block.binding.eval('a = 43')
end

a = 42
puts a
mal do
  puts 1
end
puts a

실행할 때 다음을 생성합니다.

42
1
43

이것은 정적 분석을 불가능하게 만드는 위에서 언급 한 공개 클래스 이상입니다. 위에서 설명한 것은 다른 곳으로 전달 된 클로저가 정의 된 전체 환경과 함께 전달된다는 것입니다. 이것은 첫 번째 클래스 환경 (함수를 전달할 수있을 때와 마찬가지로 첫 번째 클래스 함수입니다) 이것은 환경 과 당시 사용 가능한 모든 바인딩입니다. 클로저 범위에서 정의 된 모든 변수 를 재정의 수 있습니다.

루비에 대해 불평하는 것이 좋든 나쁘 든 ( 방법의 환경에서 접근하기를 원하는 용도 가있다 ( Perl의 Safe 참조 )) “정부 프로젝트에서 루비가 제한되는 이유는 무엇인가? “위에 링크 된 동영상에서 실제로 답변됩니다.

을 고려하면:

  1. 루비는 모든 클로저에서 환경을 추출 할 수 있습니다
  2. 루비는 클로저 범위의 모든 바인딩을 캡처합니다.
  3. 루비는 모든 바인딩을 실시간으로 변경 가능하게 유지합니다
  4. 루비는 환경을 복제하거나 리 바인딩을 금지하지 않고 새로운 바인딩을 낡은 바인딩으로 만듭니다.

이 네 가지 디자인 선택의 의미로 인해 어떤 코드가 어떤 역할을하는지 알 수 없습니다.

이에 대한 자세한 내용은 Abstract Heresies 블로그를 참조하십시오 . 특정 게시물은 그러한 토론이 있었던 계획에 관한 것입니다. (SO 관련 : Scheme이 왜 일류 환경을 지원하지 않습니까? )

그러나 시간이 지남에 따라, 나는 원래 생각했던 것보다 일류 환경에서 더 많은 어려움과 더 적은 힘이 있음을 깨달았습니다. 이 시점에서 나는 일류 환경이 전혀 쓸모없고 최악의 상황에서는 위험하다고 생각합니다.

이 섹션이 일류 환경의 위험 요소와 제공된 솔루션에서 Ruby를 제거하도록 요청되는 이유를 보여주기를 바랍니다. 루비는 동적 언어 일뿐 아니라 (다른 답변에서 언급 한 것처럼 다른 프로젝트에서 다른 동적 언어가 허용 되었음) 일부 동적 언어를 추론하기 어려운 특정 문제가 있습니다.


답변

평가가 승인 스캔이 아니라 보안 전용이라고 가정하면 (즉, 루비를 지원하지 않기 때문에 루비를 받아들이지 않음) 다음과 같습니다.

보안 분석 도구는 일반적으로 동적 동작으로 인해 시간이 오래 걸립니다.

예를 들면 다음과 같습니다.

Veracode 와 같은 것을 통해 ASP.NET MVCEntity Framework 와 같은 최신 기능으로 작성된 .NET 프로젝트를 실행하고 리포트에서 어떤 오 탐지 목록을 볼 수 있습니다.

Veracode는 .NET 4 핵심 라이브러리 내의 많은 기본 기술을 “지원되지 않는 프레임 워크”로 지원되지 않거나 베타 버전으로 기술하고 있습니다.

그러한 도구에 강한 의존을하는 기업을 다루는 경우, 기술 전문 지식과 리소스가없는 경우 안전하지 않은 사람들을 고려하여 프로젝트를 수동으로 평가하고 제대로 작성되었는지 확인해야합니다. 안전한.

컴퓨터 시스템이 일반적으로 위험하거나 엄청나게 비싼 것을 통제하지 않는 민간 사업장에서 완화 조치는 사용자가 오 탐지를 논의하고 일반적으로 대량으로 받아 들여진다는 것입니다.

은행 업무에서는 여전히 긍정 오류가 발생할 가능성이 있지만 각 항목의 세부 사항에 대해 더 많은 시간을 할애 할 것입니다. 비용이 엄청나게 높아지고 더 전통적인 방법을 사용하기 시작합니다.

군사, 항공, 중공업 등에서 시스템은 언어, 컴파일러 등에 대한 매우 엄격한 규칙을 가질 수 있도록 시스템이 끔찍한 실패 모드를 갖는 것을 제어 할 수 있습니다.

조직은 일반적으로 자신이 알고있는 최악의 경우에 대한 보안 정책을 작성하므로 사소한 것을 작성하더라도 사소한 시스템이있는 조직에 대해 작성하는 경우 일반적으로 기본값은 누군가 특정 예외를 요청하지 않는 한 더 높은 표준.


답변

동적 언어는 국방 및 군사 응용 프로그램에서 사용할 수 있습니다. 저는 개인적으로 Perl과 Python을 DoD 응용 프로그램에서 사용하고 제공했습니다. 또한 PHP와 JavaScript가 사용되고 배포되는 것을 보았습니다. 필자의 경험에 따르면 필자가 보았던 대부분의 컴파일되지 않은 코드는 쉘 스크립트와 Perl이었습니다. 필요한 환경이 다양한 대상 시스템에서 승인되고 설치 되었기 때문입니다.

이러한 언어가 동적이라는 사실은 문제가되지 않습니다. 이러한 언어의 통역사는 대상 시스템에서 사용하도록 승인되어야합니다. 인터프리터의 사용이 승인되지 않은 경우 (또는 어쩌면 대상 시스템에 배치되지 않은 경우) 언어를 사용할 수 없습니다. 보안 시스템에서 지정된 인터프리터 (또는 모든 응용 프로그램)를 사용하려면 소스 분석, 대상 환경을 위해 소스에서 컴파일 할 수있는 기능, 이진에 대한 추가 분석, 기존 인프라와의 충돌 방지 등 수많은 보안 장애물이 필요합니다.


답변

나는 F-16의 MMU 를위한 직책을 위해 국방부 (DOD)와 면담하는 데 시간을 보냈다 . 비공개를 위반하지 않고 MMU는 거의 모든 F-16의 기능을 제어하는 ​​컴퓨터 장치입니다. 비행 중에 런타임 버그와 같은 오류가 발생하지 않는 것이 (분명히) 중요합니다. 시스템이 실시간 컴퓨팅 작업을 수행하는 것도 마찬가지로 중요합니다.

이와 같은 역사적 이유 때문에이 시스템의 모든 코드 는 정적 객체 지향 프로그래밍 언어 인 ADA로 작성되거나 컴파일 됩니다 .

Ada의 안전 필수 지원 기능으로 인해 군사용 응용 프로그램뿐만 아니라 항공 전자 공학 및 항공 교통 관제, 상용 로켓 (예 : Ariane 4 및 5)과 같은 소프트웨어 버그가 심각한 결과를 초래할 수있는 상용 프로젝트에서도 사용됩니다. 위성 및 기타 우주 시스템, 철도 운송 및 은행 업무. 예를 들어, 보잉 777의 플라이 바이 와이어 시스템 소프트웨어는 Ada로 작성되었습니다.

나는 너무 많이 인용하는 것을 싫어하지만 이것은 왜 ADA와 같은 정적 언어가 다음과 같은 프로젝트에 사용되는지 실제로 잘 설명합니다.

다른 언어로 런타임까지 감지 할 수 없거나 소스 코드에 명시 적 검사를 추가해야하는 버그를 피하기 위해 많은 컴파일 타임 검사가 지원됩니다. 예를 들어 구문에 일치하지 않는 엔드 토큰으로 인한 오류를 방지하기 위해 명시 적으로 명명 된 블록 닫기가 필요합니다. 강력한 타이핑을 준수하면 컴파일 타임 또는 런타임 동안 많은 일반적인 소프트웨어 오류 (잘못된 매개 변수, 범위 위반, 잘못된 참조, 불일치 유형 등)를 감지 할 수 있습니다. 동시성은 언어 사양의 일부이므로 컴파일러는 잠재적 교착 상태를 감지 할 수 있습니다. 컴파일러는 일반적으로 철자가 잘못된 식별자, 패키지의 가시성, 중복 선언 등을 검사하며 오류를 해결하는 방법에 대한 경고 및 유용한 제안을 제공 할 수 있습니다.

Ada는 또한 할당되지 않은 메모리에 대한 액세스, 버퍼 오버 플로우 오류, 범위 위반, 일대일 오류, 어레이 액세스 오류 및 기타 감지 가능한 버그로부터 보호하기 위해 런타임 검사를 지원합니다. 이러한 검사는 런타임 효율성을 위해 비활성화 할 수 있지만 종종 효율적으로 컴파일 될 수 있습니다. 또한 프로그램 확인을 도와주는 기능도 포함되어 있습니다. 이러한 이유로, Ada는 중요한 시스템에서 널리 사용되며, 이로 인해 어떤 비정상적인 상황이 우발적 인 사망, 부상 또는 심각한 재정적 손실과 같은 매우 심각한 결과를 초래할 수 있습니다. Ada가 사용되는 시스템의 예로는 항공 전자 공학, 철도, 은행업, 군사 및 우주 기술이 있습니다.

Ada의 동적 메모리 관리는 수준이 높고 형식이 안전합니다. Ada는 일반적인 (그리고 모호한) “포인터”를 가지고 있지 않습니다. 또한 포인터 유형을 암시 적으로 선언하지도 않습니다. 대신, 모든 동적 메모리 할당 및 할당 해제는 명시 적으로 선언 된 액세스 유형을 통해 이루어져야합니다. 각 액세스 유형에는 메모리 관리의 하위 레벨 세부 사항을 처리하는 연관된 스토리지 풀이 있습니다. 프로그래머는 기본 스토리지 풀을 사용하거나 새 스토리지 풀을 정의 할 수 있습니다 (특히 비 균일 메모리 액세스와 관련됨). 모두 동일한 유형을 지정하지만 다른 스토리지 풀을 사용하는 여러 가지 액세스 유형을 선언 할 수도 있습니다. 또한이 언어는 컴파일 타임과 런타임에 모두 액세스 가능성 검사를 제공하여 액세스 값이 가리키는 객체 유형보다 액세스 값이 오래 지속되지 않도록합니다.


답변

DoD와 NASA는 오랜 시간 동안 프로그래밍 실패로 수십억 달러의 비용이 듭니다. 두 기관 모두 동일한 실수를 반복하지 않도록 보호해야하는 프로세스를 승인했습니다.

Is this the government being slow to adopting new technologies?

이것은 오해입니다. 다이나믹 언어는 새로운 기술이 아니며 상당히 오래되었습니다. 문제는 동적 언어 (예 : 약한 / 동적 타이핑)로 인해 문제가 발생하여 비용이 많이 드는 경우 같은 실수를 다시는하지 못하게하는 정책을 수락 할 수 있다는 것입니다. 민감한 시스템에서 동적 언어 사용을 금지합니다.

동적 언어는 종종 버그를 “삼키기”하며 예기치 않은 동작으로 끝납니다. 민감한 시스템에서는 매우 위험합니다. 문제가 발생하면 가능한 한 빨리 알고 자합니다.

보안이 우려되는 경우 실제 사용 사례를 확인해야합니다. 예를 들어, Ruby on Rails 웹 페이지가 Java 웹 페이지보다 자동으로 덜 안전하다고 생각하지 않습니다.


답변

Drupal의 SA-CORE-2014-005 를 설명하여 기존 답변에 추가하고 싶습니다. 이는 SQL 주입 및 궁극적으로 임의의 코드 실행을 가능하게하는 매우 중요한 취약점입니다. PHP의 동적 타이핑 및 lax 런타임 타이핑 규칙에 의해 발생합니다.

이 문제에 대한 패치 전체는 다음과 같습니다.

-      foreach ($data as $i => $value) {
+      foreach (array_values($data) as $i => $value) {

이 코드는 SQL 삽입을 방지하도록 설계된 SQL 추상화 계층의 일부입니다. 명명 된 매개 변수가있는 SQL 쿼리와 명명 된 각 매개 변수에 대한 값을 제공하는 연관 배열이 필요합니다. 값은 WHERE x IN (val1, val2, val3)단일 이름 매개 변수에 대한 단일 배열 값으로 세 개의 값을 모두 전달할 수있는 경우와 같이 배열 이 될 수 있습니다.

이 코드는 $iin $i => $value이 값의 정수 인덱스 여야 한다고 가정하기 때문에 취약점이 발생 합니다. 정수는 이스케이프가 필요하지 않기 때문에 매개 변수 이름의 일부로이 “인덱스”를 SQL 쿼리에 직접 연결합니다.

불행히도 Drupal의 경우, PHP는 그러한 보증을 제공하지 않습니다. 키가 문자열 인 다른 연관 배열을 전달할 수 있으며이 루프는 문자열 키를 쿼리에 그대로 연결합니다 (코드는 정수 일 수 있다고 생각합니다).

정적으로 유형이 지정된 언어에서 유사한 오류가 발생하는 방법이 있지만 그럴 가능성은 없습니다. 좋은 개발자는 $i쿼리에 연결하기 전에 가능한 일을 고려할 것 입니다. 정적으로 유형이 지정된 언어를 사용 $i하면 정수 여야하며, 이와 같은 보안에 민감한 코드에서는 가장 확실하게 수행해야합니다.

또한 코드는 실제로 항목을 반복하기 전에 값이 배열인지 확인합니다. 그리고 여기에이 취약점을 가능하게하는 실패의 두 번째 부분이 있습니다 : 연관 배열과 “정상”배열 모두가 true를 반환합니다 is_array. C #에서 사전과 배열이 모두 사실이지만 IEnumerable, 실수로도 물론 의도적으로 사전 키와 배열 색인을 배열 인덱스와 연결하는 코드를 작성하는 것은 어렵습니다.


답변

코드베이스의 보안 여부는 코드 작성 방법, 코드 테스트 방법 및 개발 및 배포 프로세스의 유효성을 검사하고 모니터링하는 방법에 따라 다릅니다. 언어는 안전하지도 안전하지도 않으며 코딩 방식입니다.

악의적 인 입력 (SQL 주입, 버퍼 오버플로), 바이러스, 루트킷 및 트로이 목마로 인한 대부분의 보안 사고. 어떤 언어도 당신을 보호 할 수 없습니다.

따라서 “안전하지 않은”언어 클래스를 금지하는 것은 유효한 이유가 아닙니다.

어떤 이유로 든, 정보를 얻든 말든 누군가가이 언어를 금지하기로 결정한 것 같습니다. 얼마 후 그것은 조직의 진실 이되었다 . 이 시점에서 일부 프로젝트의 경우에는 맞았 을지 모르지만, 통제 문화 는 의사 결정 변경에 열중하지 않고 (잘못 인정) 단순한 규칙을 선호합니다. 그들은 규칙과 규정에 따라 번성하며 그것이 의미 있든 없든 상관없이 인식되는 안전 이 중요합니다.

이것은 항상 통제 문화에서 발생합니다. 나는 매일 매일 그것을 본다. 말이되지 않지만, 그렇게됩니다. 관련성이 높은 주제에 대한 자세한 내용을 보려면 Schneider의 책 ” The Reengineering Alternative “을 참조하십시오. Schneider의 책을 기반으로 한 Michael Sahoto / Agilitrix문화 다이어그램 은 다음과 같습니다 .
여기에 이미지 설명을 입력하십시오