루비의 변수 "무효화"[중복]
보안상의 이유로 더 이상 필요하지 않은 순간에 일부 데이터를 폐기해야하는 사용 사례가 있습니다.
로그인과 비밀번호를 다루는 Ruby로 서버를 작성하고 있습니다. BCrypt를 사용하여 데이터베이스에 암호를 저장합니다. 내 서버는 암호를 받고 bcrypt 해시를 만든 다음 더 이상 원래 암호를 사용하지 않습니다.
RAM에서 바로 데이터를 훔치는 것과 관련된 일종의 사이버 공격에 대해 알고 있으며, 암호가 아직 메모리에있는 기간 동안 공격자가 원시 문자열 형식의 사용자 암호를 훔칠 수 있다는 점이 우려됩니다. 단순히 사용하는 password_in_string_form = nil
것으로 충분 할지 모르겠습니다 .
사용자 암호를 사용하는 순간 사용자의 암호를 보유하는 변수를 무효화하고 싶습니다 . nullify는 0으로 무언가를 채우기 위해 / dev / null을 사용하는 것과 비슷한 것을 의미합니다. 최종 목표는 데이터를 되돌릴 수없는 파괴입니다 .
답변
단순히 사용하는
password_in_string_form = nil
것으로 충분 할지 모르겠습니다 .
아니, 충분하지 않습니다. 객체는 즉시 가비지 수집 될 수도 있고 수집되지 않을 수도 있으며, 그렇더라도 메모리에서 내용이 지워지지는 않습니다.
그러나 고정되지 않은 경우 Ruby 문자열은 변경 가능 합니다. 따라서 암호 문자열을 고정하지 않는 한 그 내용을 0 또는 임의의 문자로 대체 할 수 있습니다. 특히, 이것은 나중에 다룰 몇 가지 단정을 주제로 작동합니다.
(0 ... password_in_string_form.length).each do |i|
password_in_string_form[i] = ' '
end
그러나 더 우상적으로 보일 수있는이 접근 방식 은 효과가 없기 때문에주의를 기울여야합니다 .
# SURPRISE! This does not reliably remove the password from memory!
password_in_string_form.replace(' ' * password_in_string_form.length)
대상 문자열의 내용을 제자리에서 업데이트하는 대신 replace()
내용을 Ruby의 내부 할당 자 (수정하지 않음)에 릴리스하고 교체 세부 정보를 기반으로 새 내용에 대한 전략을 선택합니다.
그러나이 두 가지 접근 방식 간의 효과 차이는 큰 경고 플래그가되어야합니다. Ruby는 매우 높은 수준의 언어입니다. 이는 많은 레버리지를 제공하지만 데이터가 메모리에 유지되는지 여부와 기간과 같은 세부 사항을 제어하는 비용이 발생합니다.
그리고 그것은 저를 provisos로 가져옵니다. 주요 내용은 다음과 같습니다.
암호 문자열을 처리 할 때 암호 문자열 또는 그 일부의 복사본을 만들지 않도록주의하거나 모든 복사본을 캡처하여 폐기해야합니다. 그러한 사본을 만드는 것이 매우 쉽기 때문에 세부 사항에 약간의 규율과주의가 필요합니다.
비밀번호 문자열 자체를 폐기하는 것만으로는 목표를 달성하기에 충분하지 않을 수 있습니다. 또한 암호 문자열을 분리하는 업스트림에서와 같이 메모리에있는 다른 암호 복사본을 폐기해야합니다. 예를 들어 웹 응용 프로그램 인 경우 암호가 응용 프로그램에 전달 된 HTTP 요청의 내용과 격리 된 암호 문자열보다 파생 된 문자열이 더 많을 것입니다. 다른 종류의 응용 프로그램에도 유사하게 적용됩니다.
암호 만 보호해야하는 것은 아닙니다. 공격자가 호스트 컴퓨터의 메모리에서 암호를 훔칠 수있는 위치에 있으면 사용자가 로그인 한 후 액세스하는 민감한 데이터를 훔칠 수있는 위치에 있습니다.
이러한 이유와 다른 이유로 서버에 대한 보안 요구 사항에 따라 사용자 암호의 메모리 내 복사본이 더 이상 필요하지 않은 즉시 폐기되어야하는 경우 (순수한) Ruby가 적절한 구현 언어가 아닐 수 있습니다.
반면에 적이 메모리 / 스왑에서 암호를 긁어 낼 수있는 충분한 액세스 권한을 얻으면 이미 게임이 끝났을 것입니다. 최소한 애플리케이션이 액세스 할 수있는 모든 것에 액세스 할 수 있습니다. 그렇다고해서 암호가 전혀 문제가되지는 않지만이 문제에 얼마나 많은 노력을 기울이는지를 평가할 때이를 고려해야합니다.
Ruby에서는 불가능합니다.
이를 보장하기 위해 각 구현 (Opal, TruffleRuby, JRuby, Rubinius, MRuby, YARV 등)에 특정한 코드를 작성해야합니다. 구현에 따라 사용자가 직접 관리하는 별도의 메모리가 없으면 구현의 관리되는 메모리 내부 에서 수행하는 것이 전혀 불가능할 수도 있습니다 .
즉, 자신의 작은 네이티브 메모리를 관리하고이를 Ruby 프로그램에 삽입하는 작은 네이티브 코드가 필요할 것입니다.