왜 나는 Haskell이 소프트웨어 안전 방면에서 좋은 선택이라고 생각합니까?

작성자: Ville Tirronen

타자 가능한 팀 감상 안전!우리는 Haskell을 좋아하지만, 보안 소프트웨어가 우리의 목표일 때,Haskell은 좋은 선택입니까?우리는 그렇다고 말하고 싶지만, 대부분의 소프트웨어 개발에 관한 실증 문제와 마찬가지로, Haskell이나 그 어떠한 통용 프로그래밍 언어가 그 어떤 다른 언어보다 안전하다는 확실한 증거는 없다.이것은 결코 안전 문제가 중요하지 않다고 말하는 것은 아니지만, 구체적으로 어떻게 해결하는지는 상세하게 설명해야 할 것이다.
5년 동안 소프트웨어 안전 입문 과정을 가르친 후에 나는 소프트웨어 안전에 의존할 수 있는 통용 이론이 없다는 것을 증명할 수 있다.안전성은 일반적으로 서로 다른 안전 문제, 완화 조치와 안전 모델을 열거함으로써 가르치고 학생들이 그 중에서 보편적인 이해를 얻기를 바란다.기존의 이론 저서라도 프로그래밍 언어와 안전에 대한 연계를 시도하는 사람은 드물다.
이 글에서 나는 내가 가장 좋아하는 시각을 그려내고 프로그래밍 언어의 선택과 안전성을 연결시킬 것이다.도메인 및 우연 취약점 간에 서로 다른 취약점을 볼 수 있습니다.
   Purely technical               Purely domain specific
    vulnerability                    vulnerability
        ↓                                  ↓
        ┠───────────╂───────────╂──────────┨
             ↑            ↑          ↑
        Tools should  Tools can  You have to
            fix         help       think
위의 축은 서로 다른 소프트웨어의 빈틈의 출처를 대표한다.극우익에서 우리는 순수하게 영역에 특정된 잘못이 있다. 즉, 이러한 실수는 사용하는 도구에 완전히 독립된다는 것이다.이러한 지역 오류의 한 예는 2000년대 초기의 많은 웹 서비스들이 암호 복구에 존재했던'안전 문제'다.보통 문제는'어머니의 친정 성은 무엇입니까?'그리고 2009~10년 전후로 소셜미디어라는 것이 등장하면서 갑자기 모든 사람의'어머니 친정 성'이 공공메시지로 바뀌었다.네가 어떤 기술로 이런 안전 문제 방안을 실현하는지는 결코 중요하지 않다.어쨌든 그것은 모두 고장났다.
천평의 가장 왼쪽에 우리는 순수한 기술적 원인의 착오가 있다.그것들은 완전히 문제 영역에서 독립한다.이런 문제의 좋은 예는 악명 높은 버퍼 넘침이다.버퍼에 무엇을 저장했는지는 중요하지 않다. 버퍼가 넘치면 공격자는 프로그램의 지원 구조를 마음대로 파괴할 수 있다.여기서 적어도 이론적으로 검사되지 않은 버퍼가 기록된 도구체인을 사용하면 버퍼가 넘치는 것을 피할 수 있다.
규모의 원단에서 우리는 일부 빈틈이 완전히 기술적이지는 않지만, 완전히 분야의 문제도 아니다.이런 빈틈의 전형적인 예는 일반적으로 파일을 업로드할 수 있는 서비스에 나타난다.
이러한 서비스에서는 일반적으로 사용자가 제공한 파일을 서버 파일 시스템에 직접 쓰기 쉽다.그런데 어떤 파일 이름을 사용합니까?사용자가 제공한 파일 이름을 직접 사용하면 ../../../etc/nginx/nginx.conf, ../../../etc/passwd/ 또는 서버가 만질 수 있지만 실제로는 만져서는 안 되는 수량의 파일일 수 있기 때문에 재난을 초래할 수 있다.
이런 위험은 기술과 분야의 혼합체이다. 비록 어떤 공구체인도 이런 '상자를 열면 바로 사용할 수 있는' 상황을 방지할 수 없지만, 일부 공구가 어떻게 다른 공구보다 이런 문제가 있는 행위를 통제하는 데 도움을 줄 수 있는지 쉽게 알 수 있다.

응용량표


이 양표의 용도는 프로그래밍 언어와 프레임워크 같은 도구를 평가하는 데 있다.당신의 도구 자체가 얼마나 순수한 기술 문제를 처리할 수 있습니까?그것은 어느 정도에 빈틈을 초래하는 오류를 방지하기 위해 당신에게 추가 지렛대를 제공했습니까?
이상적인 상황에서 현대 공구는 가장 순수한 기술적 빈틈을 거의 완전히 방지해야 한다.예를 들어 대부분의 현대 언어, 예를 들어Haskell, C#와Java는 기본적으로 메모리가 안전하고 버퍼 넘침, 이중 방출과 기타 기술 문제를 어느 정도 방지할 것이다.하지만 좋은 도구를 한층 더 활용할 수 있다.예를 들어 우리는 절대와 상대적인 파일 경로를 분리하는 기술적 수단을 가지고 있어 경로가 반복되는 공격을 제어하기 쉽다. 예를 들어 사용자가 특정한 관건적인 시스템 설정 파일에 파일을 업로드하는 것이다.

하스켈, 천평의 저단에서


대부분의 현대 언어와 마찬가지로, Haskell은 저급한 기술의 빈틈을 처리할 때 양호한 모습을 보였다.우선,Haskell은 메모리가 안전하기 때문에 잠재적인 공격자가 대량의 잠재적인 빈틈을 건드리지 못한다. 수조와 버퍼 넘침은 더욱 그렇다.그 다음으로Haskell은 정적 스케줄링으로 전체 잘못된 가족을 방지할 수 있다. 예를 들어 PHP의 유명한'유형 잡기'등이다.
// From imaginary CSRF token protection:
if ($tokenHash == $hashFromInternet->{'tokenHash'}) {
  echo "200 OK - Request accepted", PHP_EOL;
}
else {
 echo "403 DENIED - Bad CSRF token", PHP_EOL;
};
위에 질문 보이시나요?대부분의 동적 언어, 예를 들어 PHP는 실행할 때 JSON 기록의'유형'을 결정하는데 보통 입력 데이터의 구조를 바탕으로 한다.또한 대상 프로그래밍에서 '유형' 은 동적 분배를 통해 행동을 선택하여 공격자가 실행할 코드를 선택할 수 있도록 하는 데 사용된다.한 마디로 하면 PHP의 equality via==는 입력 유형에 의존하고 위의 예에서 공격자는 안전성을 완전히 돌아갈 수 있다.
자바 (기타 언어, 참조 https://frohoff.github.io/appseccali-marshalling-pickles/ 에도 비슷한 문제가 발생했습니다.자바는 모든 대상을 디스크에 서열화하고 원시적으로 복원할 수 있는 사용자 친화적인 방법을 제공합니다.유일한 불행한 문제는 당신이 원하는 상대가 무엇인지 말할 방법이 없다는 것이다!이로써 공격자는 사용자에게 대상을 보낼 수 있습니다. 이 대상들은 프로그램에서 반서열화된 후에 악의적으로 변하여 심각한 파괴를 초래하고 데이터를 훔칠 수 있습니다.
PHP에서 보안 코드가 없거나 하스켈에서 이런 오류가 있을 수 없다는 것은 아니지만 하스켈은 이런 빈틈에 타고난 경향이 없다.이러한 예제를 Haskell 코드에 넣으려면 다음과 같이 하십시오.
data Request = Request {csrfToken :: Token, ... other fields}
doSomething :: Session -> Request -> Handler ()
doSomething session request
  | csrfToken session == csrfToken request = ... do something
  | otherwise = throwM BadCsrfTokenError
여기서 유형 전환은 인터페이스 유형에 구체적이고 심지어 프로그램이 실행되기 전에 알고 있는 유형의 일반적인 실천을 통해 이루어진다.

하스켈, 중규모


'기술'과'영역'사이의 균형을 고려할 때 하스켈의 특징은 내가 보기에 매우 유리한 선택이다.
무엇보다 Haskell은 C, 자바스크립트, 심지어 자바 등 언어보다 더 정확하게 데이터를 모델링할 수 있다.이것은 주로 편리한 문법과 구화 유형 때문이다.정확한 데이터 모델링은 안전성과 관련이 있다. 대부분의 역 코드는 진실한 세계 현상의 모델이고 정확하지 않을수록 공격자는 공격을 받기 쉽기 때문이다.
정확한 모델링 도구를 갖추면 프로그래머가 영역을 돌아다니는 데 도움이 된다.예를 들어 하나의 간단한 기능을 고려한다. 즉, 한 줄로 간단하게 표현한다. 예를 들어 사회보험 번호는 알 수 없거나 편집을 거쳤거나'여기 이 값'이다.
data SSN = Unknown | Redacted | SSN Text
현재 문자열 값 "", "<REDACTED>", "191091C211A" 을 사용하여 모형을 만드는 것과 같은 생각을 비교합니다.사용자가 SSN 입력란에 ""를 입력하면 어떻게 됩니까?앞으로 문제 없을까요?Haskell이 있으니, 너는 이런 문제를 걱정할 필요가 없다.
유사한 기술은 프로그래머가 각지의 안전성을 향상시키는 데 도움을 줄 수 있다.마지막으로 서버에서 사용자 파일을 안전하게 저장한 예를 계속하려면 사용자가 저장 기능을 업로드하면
storeFileUpload :: Path Abs File -> ByteString -> IO ()
storeFileUpload path = ...
사용자가 시스템 파일을 덮어쓸 수 있는 상황을 만들 수 없습니다. 파일 경로가 실제로 경로 반복 공격을 포함하지 않을 수 없으면 이 코드는 컴파일할 수 없습니다.마찬가지로 사용자가 로그인에 실패하면 프로그램에서 사용자 데이터를 사용할 수 없거나 확인되지 않은 사용자 입력을 HTML 페이지에 포함할 수 없으면 오류가 발생하지 않습니다.
나는 다른 언어가 보안 코드를 작성하는 데 사용할 수 없다고 말하는 것도 아니고, Haskell이 자동으로 당신의 코드를 더욱 안전하게 할 것이라고 말하는 것도 아니다.다만 Haskell에는 당신의 안전을 위해 아주 편리한 도구가 있습니다.

Haskell 및 도메인 오류


이전에, 나는 순수한 영역 오류를 사용하는 도구와 무관한 오류로 정의했다.이것은 결코 완전히 정확하지 않다.사람들은 도구를 무작위로 선택하지 않고 사고가 비슷한 사람들은 종종 서로 다른 도구를 둘러싸고 지역사회를 형성한다.이 지역사회들은 안전에 대해 다른 견해를 가지고 있을지도 모른다.
여기서 Haskell이 선호하는 점은 우연히 Haskell을 잘할 수 없다는 것이다.Haskell은 현재 매우 보기 드문 기술로, 심지어 모든 대학이 그것을 가르치는 것은 아니며, 완전히 그것으로 가르치는 과정은 거의 없다.하스켈을 잘하는 사람이 있다면 정식 시스템을 사용하는 기술이나 컴퓨터 과학 주제에 흥미를 느낄 수 있다는 것은 불합리한 추측이 아니라는 것이다.Haskell 프로그래머가 안전성에 대해 아는 것은 아니지만, 필요할 때 안전성을 빨리 이해할 수 있음을 암시한다.
이것은 모두 추측이다.하스켈 커뮤니티는 규모가 작아 공격자의 목표가 되지 않지만, 하스켈 사람들은 자바스크립트나 파이톤 개발자처럼 안전 문제에 타 죽지 않는다.

결론


Haskell이 반드시 결점이 없는 것은 아니다. 나도 다른 언어가 비슷한 장점을 나눌 수 없다고 말하는 것은 아니다.어떤 경우, 예를 들어 정시와 다른 사이드 채널 공격, 다른 도구는 심지어 더 좋은 안전 설정을 제공할 수 있다.그 밖에 일부 언어 커뮤니티는 Haskell보다 안전성에 더 관심을 가진다.그러나 개인적으로 현재 실행 가능한 유니버설 프로그래밍 언어 선택에서 Haskell은 보안 소프트웨어를 작성하는 데 아주 좋은 패키지를 제공한다는 것을 알았다.

좋은 웹페이지 즐겨찾기