출처: http://msdn.microsoft.com/ko-kr/magazine/cc982153.aspx

Windows 파일 및 레지스트리의 사용 권한 이해
John R. Michener

이 기사에서는 다음 내용에 대해 설명합니다.
  • 액세스 제어 목록
  • 사용자 권한
  • 파일 시스템 사용 권한
  • 레지스트리와 사용 권한
이 기사에서 사용하는 기술:
Windows Server 2008
시스템에서 어떤 일이 일어나면 매번 주체(사용자나 서비스 대신 작업을 수행하는 프로세스나 스레드)가 개체에 어떤 작업을 수행합니다. 파일, 디렉터리 및 레지스트리 키는 일반적으로 알려진 개체의 예입니다. Windows의 기본 보안 메커니즘에는 작업 진행을 허용하기 전에 신뢰할 수 있는 시스템 구성 요소가 사용 권한과 권한(AccessCheck)을 확인하는 과정이 포함됩니다. 따라서 사용 권한과 권한을 설정하여 시스템 동작을 관리할 수 있습니다. 내부적으로 어떤 일이 일어나는지 이해하지 못하면 사용 권한을 적절하게 설정할 수 없으므로 우선 개체의 보안 설정과 이를 처리하는 방법을 설명한 다음 해당 값을 설정하는 방법을 살펴보겠습니다.
기 술적인 세부 사항으로 들어가기 전에 Windows ACL(액세스 제어 목록) GUI를 사용하여 Windows Server 2008의 시스템 드라이브 루트의 사용 권한을 살펴보겠습니다. Windows 탐색기를 열고 보안 탭을 선택한 다음 로컬 디스크(C:)를 마우스 오른쪽 단추로 클릭하고 속성을 선택하면 관리자가 모든 권한을 가진다는 것을 알 수 있습니다. 그룹이나 사용자 이름에서 SYSTEM을 클릭하면 SYSTEM도 모든 권한을 가진다는 것을 알 수 있습니다. 그룹이나 사용자 이름에서 사용자를 클릭하면 사용 권한 상황이 그리 간단하지 않다는 것을 알 수 있습니다. 그림 1에 있는 시스템의 사용자 그룹은 읽기 및 실행, 목록, 읽기 등의 사용 권한을 가집니다. 고급 단추를 클릭하면 사용자 그룹과 연관된 사용 권한에 대한 더 세부적인 보기가 제공됩니다(그림 2 참조).
그림 1 로컬 디스크 C의 사용자 권한
그림 2 드라이브 C의 사용자 권한에 대한 고급 보기 (더 크게 보려면 이미지를 클릭하십시오.)
여기에서 사용자 그룹의 구성원은 시스템 드라이브의 루트에 폴더를 만들고 파일에 데이터를 추가할 수 있습니다. 편집 단추를 클릭하면 그림 3에 나온 것처럼 하위 폴더에 대한 다른 "특수한" 권한 부여를 볼 수 있습니다. 이 작업에는 관리자 권한이 필요합니다.
그림 3 사용자 특수 권한 편집 보기
따 라서 Windows Server 2008에서는 기본적으로 일반 사용자가 시스템 드라이브의 루트에 하위 폴더를 만들고 이러한 폴더에 콘텐츠를 추가할 수 있습니다. Windows Server 2008에서 사용자 그룹의 구성원에 이 기능이 제공된 이유는 일부 타사 소프트웨어가 이러한 권한을 전제로 동작하기 때문입니다. Microsoft로서는 응용 프로그램 호환성을 깨고 싶지 않았던 것이지요.
이 제 이러한 문제에 대한 기술적인 내용으로 들어가서, 사용자에게 제공되는 GUI 인터페이스의 내부에서 어떤 방식으로 동작하는지 알아보겠습니다. Windows의 모든 명명된 개체에는 보안 설명자가 있습니다. 보안 설명자는 소유자에 대한 정보를 제공하고 지정된 사용 권한이 있는 사용자 및 대상을 나열합니다. 또한 보안 설명자는 어떤 개체에 대한 액세스를 시스템 이벤트 로그에 기록해야 하는지도 지정할 수 있습니다.
대 상(사용자, 프로세스 등)이 개체 또는 리소스에 대해 수행할 수 있는 작업에 대한 정보는 ACL이라는 데이터 구조에 지정됩니다. ACL은 특정 개체에 대해 누가(주체), 어떤 액세스 권한을 가지는지 열거합니다. DACL(임의 ACL)은 개체 소유자가 개체를 변경할 수 있도록 허용하는 ACL 유형입니다. 개체가 액세스될 때마다 요청된 액세스가 허용되는지 확인하기 위해 보안 설명자가 주체의 사용 권한과 비교됩니다.
Windows 는 개체에 대한 SACL(시스템 ACL)도 지원하며, 감사 로그에 어떤 이벤트가 기록되는지 설정하기 위한 용도로 여러 릴리스에 걸쳐 SACL을 사용해왔습니다. Windows Server 2008과 Windows Vista에서는 무결성 수준 정보를 제공하도록 SACL이 확장되었습니다.
이 무결성 레이블은 LowRights Internet Explorer에서 사용되는 Internet Explorer 프로세스를 표시하는 "낮음" 레이블을 설정하는 데 사용됩니다. "시스템"과 "높음" 레이블은 중요한 시스템 리소스를 보호하는 데 사용됩니다. Windows 메시지 펌프는 메시지의 무결성 수준을 바탕으로 메시지를 필터링합니다. 예를 들어 중간 수준 프로세스는 낮은 수준 프로세스에서 보낸 메시지를 받지 않으며, 높은 수준 프로세스는 낮은 또는 중간 수준 프로세스에서 보낸 메시지를 받지 않습니다.
현재로서는 무결성 수준 보호는 보안을 보장할 수 있는 진정한 보안 방어막은 아니며 과속 방지턱에 가깝습니다. 이 방지턱의 높이는 향후 릴리스에서는 더 높아질 예정이며, 그러면 진정한 보안 방어막이 될 수 있을 것입니다.
Windows 는 다른 최신 OS와 마찬가지로 일반적인 액세스 제어 결정을 위해 DACL을 사용합니다. 이번 칼럼에서는 DACL에 초점을 맞추겠습니다. 주체가 개체를 대상으로 작업을 수행하도록 허용되는지 여부를 시스템에서 확인하기 위해서는 몇 가지 항목에 대한 검사가 필요합니다. 주체의 권한, 주체의 토큰, 그리고 개체의 보안 설명자가 이러한 항목에 해당합니다. 개체의 이진 보안 설명자는 주체의 토큰과 함께 AccessCheck 루틴으로 전달됩니다. 요청된 액세스 마스크 비트 벡터가 준비되는데, 이는 액세스 검사에 통과하기 위해 반드시 부여되어야 하는 액세스 권한을 나타냅니다. 이는 주체의 보안 설명자와 함께 AccessCheck 루틴에 전달되며 이 루틴에서는 사용자의 보안 토큰을 검사하고, 주체의 권한(관리자와 같이 일반적으로 역할 또는 멤버 자격에 바탕을 둠)을 요청된 액세스 및 개체의 DACL과 조합하여 고려합니다.
요 청된 액세스가 주체의 권한에 의해 충족되는 경우 액세스가 허용됩니다. 그렇지 않으면 DACL ACE(액세스 제어 항목)가 순서대로 검사됩니다. 요청된 모든 액세스 구성 요소가 허용되는지, 아니면 일부가 거부되는지를 보여줄 수 있게 되는 즉시 보안 시스템은 전자의 경우 성공을 반환하고 후자의 경우 실패를 반환합니다.
따 라서 DACL의 ACE 목록이 올바르게 정렬되어야 합니다. 표준(정식) 정렬은 명시적 거부를 가장 먼저 배치하고 그 다음으로 명시적 허용, 일반(그룹) 거부, 그룹 허용을 차례대로 배치합니다. 정식 정렬을 사용하지 않으면 예상하지 못한 허용이나 거부가 발생할 수 있습니다.

개체 보안 설명자
보 안 설명자는 이진 데이터 구조이지만 사람이 읽을 수 있는 텍스트 형식을 제공하기 위해 보안 설명자 문자열 형식을 사용합니다. 문자열 형식 보안 설명자는 네 가지 기본 구성 요소, 즉 소유자(O:), 주 그룹(G:), DACL(D:) 및 SACL(S:)을 나타내는 토큰이 포함된, null로 끝나는 문자열로 표현됩니다(그림 4 참조).
그림 4 보안 설명자
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\fig04a.gif
SID (보안 식별자)는 구문 분석 정보를 제공하도록 구성되며 소유자의 고유 식별자 역할을 하기 위한 임의의 96비트 정보를 포함합니다(32비트의 시퀀스 카운트도 포함할 수 있음). string_ace(문자열 형식으로 표현되는 ACE)는 DACL에서 명시적으로 사용 권한을 부여 또는 거부하고 SACL에서 정책을 설정하는 구조입니다. 각 string_ace는 괄호 안에 포함되며 다음과 같은 구조를 가집니다.
   (ace_type;ace_flags;rights;object_guid;inherit_
   object_guid;account_sid)
해 당 개체에 대한 올바른 액세스에 필요한 권한 부여만 있어야 합니다. owner_sid와 group_sid는 보안 설명자에서 생략되는 경우가 많습니다. 생성될 때 명시적으로 지정되지 않으면 보안 설명자의 owner 필드는 개체 생성을 호출하는 주체의 SID로 설정됩니다. group 필드는 주체 보안 토큰의 주 그룹으로 설정됩니다. 개체를 감사하거나 무결성 레이블을 설정할 필요가 없는 경우에는 SACL이 제공되지 않습니다.
string_ace 내에는 필요한 필드만 포함됩니다. 최소한의 집합은 ace_type, rights, subject이며 일반적으로 account_sid도 포함됩니다. 일반적으로 object_guid와 inherit_object_guid는 없습니다. 시스템은 액세스가 부여되거나 거부될 때까지 순서대로 ACE를 처음부터 끝까지 구문 분석합니다. 따라서 ACE의 순서가 중요합니다. "사용 권한 거부"가 "사용 권한 허용"보다 앞에 배치되어야 합니다.
내 부에 ACE가 없는 ACL은 빈 DACL입니다. ACE는 지정된 대상에게 개체에 대한 액세스를 부여하므로 빈 DACL로는 아무도 개체에 액세스할 수 없습니다. DACL이 없는 개체를 NULL DACL을 가진 개체라고 합니다. NULL DACL을 가진 개체는 보호되지 않으며 모든 사용자가 이에 대한 모든 권한을 가집니다. 따라서 빈 DACL이나 NULL DACL을 설정하면 안 됩니다.
이 쯤에서 실제 보안 설명자는 어떻게 생겼는지 살펴보는 것이 좋겠습니다. 다음은 Windows Server 2008 시스템 드라이브의 루트에 대한 보안 설명자입니다(cacls는 ACL을 조사하고 설정하기 위한 레거시 명령줄 루틴이며 icacls로 대체됨). 아쉽게도 icacls는 결과를 표준 SDDL(Security Descriptor Definition Language)로 출력하기 위한 명령줄 스위치를 지원하지 않습니다. cacls에는 이 스위치(/S 플래그)가 있습니다.
C:\>cacls c:/ /s
c:\"D:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;BU)(A;CI;LC;;;BU)(A;CIIO;DC;;;BU)(A;OICIIO;GA;;;CO)"
보 안 설명자에 대해 현재 알고 있는 내용을 바탕으로 앞부분의 "D:"를 통해 소유권이나 그룹 멤버 자격이 선언되지 않았으며 설명자가 DACL임을 알 수 있습니다. DACL은 보호됩니다("P"와 Windows NT 5.0 상속 플래그가 설정됨). 그 다음에는 해석이 필요한 여러 개의 ace_string이 나옵니다.

보안 설명자 string_aces의 이해
앞에서 본 string_aces 형식을 떠올려 보십시오. 허용되는 ace_types는 그림 5에 정의되어 있고 허용되는 ace_flags는 그림 6에 정의되어 있습니다. 상속을 위한 ace_flags는 ACE 상속의 핵심 요인입니다.
그림 5 허용되는 ace_types
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\fig05.gif
그림 6 허용되는 ace_flags
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\fig06.gif
ACE 권한은 ACE에 의해 제어되는 액세스 권한을 표시하는 문자열로 표시됩니다. 이 문자열은 액세스 권한을 나타내는 16진수 문자열이거나(예: "0x7800003F") 권한 문자열을 연결한 형태일 수 있으며(예: "CCLCSWLOCRRC") 잠시 후에 이를 해석해 보겠습니다. 그림 7에는 16진수 표현 및 이와 연결된 비트 값이 나와 있습니다.
그림 7 ACL 액세스 마스크
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\fig07.gif
시 스템은 모든 개체에 대해 ACE 권한의 단일 비트맵 표현을 사용합니다. 다양한 개체에서 모든 비트가 의미가 있는 것은 아닙니다. 개체에 해당되는 권한만 적용됩니다. 표준 권한은 모든 보안 개체에 공통적인 권한입니다. 일반 권한은 다양한 개체에 비슷한 목적의 권한을 지정하는 데 편리합니다. 일반 권한의 사양은 해당되는 구체적인 권한 집합에 매핑됩니다. 무결성 레이블도 SACL을 지정할 때 ACE 권한 필드를 사용하여 인코딩됩니다. 다양한 개체에 사용할 수 있는 권한은 그림 8에 나와 있습니다.
그림 8 일반 권한
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\fig08.gif
거 의 동일한 몇 가지 권한 매핑은 구분 없이 사용됩니다. Full Control(FC)은 Generic_All(GA)과 동일합니다. 파일 시스템에서 적절한 모든 권한 선언은 File All(FA)입니다. Key All(KA)은 레지스트리에 적절한 모든 권한 선언입니다. 일반 선언은 보다 적절한 선언을 대신하여 사용되는 경우가 많지만 해당하는 파일 시스템이나 레지스트리 키 선언으로 적절히 매핑됩니다. SDDL 식에서는 이러한 용어를 혼용하는 경우가 많으므로 의미의 동일성을 알고 있어야 합니다.

표준 권한 및 구체적인 권한
다양한 개체에 권한을 할당할 수 있습니다. 이러한 개체에는 파일과 디렉터리 외에도 레지스트리 키, 프로세스, 바탕 화면 등이 있습니다. 전체 목록은 그림 A - J를 참조하십시오. 여기에서는 파일 시스템과 레지스트리에 대한 사용 권한을 설명하며, 이러한 개체에 대한 구체적인 권한은 910에 나와 있습니다.
그림 9 구체적인 파일 권한
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\fig09.gif
그림 10 구체적인 레지스트리 권한
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\fig10.gif
무결성 레이블과 그 용도
앞 서 언급했듯이 무결성 레이블은(있는 경우) 개체의 SACL에 저장됩니다. 개체는 암시적으로 중간 무결성을 가지므로 무결성 레이블이 없으면 개체는 중간 무결성을 가집니다. 마찬가지로, 무결성 레이블이 없는 보안 토큰 역시 중간 무결성을 가집니다. 낮은 무결성 레이블은 LowRights Internet Explorer 및 이와 연관된 신뢰되지 않은 개체와 같은 낮은 권한의 프로세스에 레이블을 지정하는 데 사용됩니다. "높음" 및 "시스템" 수준은 이러한 개체를 중간/낮은 프로세스 및 개체로부터 격리하는 데 사용됩니다. 무결성 레이블은 그림 11에 나와 있습니다.
그림 11 무결성 레이블
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\fig11.gif
object_guid와 inherit_object_guid
object_guid 와 inherit_object_guid는 Active Directory에서 개체의 보안을 지정하는 데 사용되며 파일 시스템 또는 레지스트리 보안에는 사용되지 않습니다. ACE 문자열에서 ace_type 필드의 "OA"와 "OD"는 각각 object-allow와 object-deny에 해당합니다. 이 경우에 object_guid는 사용 권한이 부여되는 개체의 guid를 포함하며 inherit_object_guid는 사용 권한을 상속하는 개체의 guid를 포함합니다.
ACE 구조의 account_sid 필드는 ACE에 지정된 액세스 권한이 허용 또는 거부되는 보안 주체를 나타냅니다. account_sid 필드는 SID(기본적으로 사람이 이해할 수 없는, 구조화된 긴 식별자) 또는 공용 계정을 위한 단축 "SID 문자열" 표기를 포함합니다. 공용 계정을 위한 SID 문자열 표기는 시스템의 가독성을 더 높이기 위해 가능한 경우 항상 사용됩니다. 그림 J에는 공용 또는 잘 알려진 계정과 이에 해당하는 SID 문자열이 나와 있습니다.
소 유자 권한의 OW 선언은 Windows Server 2008 및 Windows Vista에 새로 추가되었습니다. 이전에는 개체의 CO(Creator/Owner)는 개체에 대해 RC(Read Control) 및 WD(Write_DAC) 표준 권한을 가졌으므로 소유자가 개체의 보안을 설정할 수 있었습니다. 사용자가 그룹의 구성원이고 많은 수의 개체를 만들 경우 이것이 문제가 됩니다. 해당 사용자가 그룹에서 나가더라도 여전히 이러한 개체의 소유자이므로 RC와 Write_DAC 사용 권한이 부여되고, 따라서 계속 개체를 제어할 수 있습니다. OW 소유자 ACE 제한이 있으면 소유자에 대한 암시적인 RC/WD 부여가 차단됩니다(ACL에 있는 다른 관련 ACE의 소유자 ACE에 명시적으로 부여되는 경우 제외). 이렇게 하면 이 보안 문제를 완화할 수 있습니다.

보안 설명자 string_aces의 해석
시스템 드라이브 루트에 대한 cacls 출력은 다음과 같습니다.
"D:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;BU)(A;CI;LC;;;BU)(A;CIIO;DC;;;BU)
    (A;OICIIO;GA;;;CO)"
이를 구문 분석하여 가독성을 높이면 다음과 같습니다.
"D:PAI
(A;OICI;FA;;;SY)
(A;OICI;FA;;;BA)
(A;OICI;0x1200a9;;;BU)(A;CI;LC;;;BU)(A;CIIO;DC;;;BU)
(A;OICIIO;GA;;;CO)"
이 것은 최신 파일 시스템의 auto-inherit 플래그가 설정된 보호되는 DACL입니다. protected 플래그는 상속 가능한 부모의 권한 부여가 상속되지 않음을 의미합니다. 즉, DACL은 개체 부모의 상속으로부터 보호됩니다. 이 경우에는 루트이기 때문에 부모가 없습니다.
기 본 제공 관리자와 시스템에는 파일(개체 상속에 의해)과 디렉터리(컨테이너 상속 또는 CI에 의해)에 대해 모두 상속 가능한 File All이 부여됩니다. 즉, 이 DACL은 루트 아래의 모든 파일과 디렉터리에 재귀적으로 File All을 부여합니다(보호되는 DACL의 권한 부여를 검사해야 할 때 보호되는 DACL에 의해 상속이 중단되는 경우 제외). CO에는 루트 디렉터리 아래의 파일과 디렉터리 모두에 대한 Generic_All이 부여되며(inherit-only 플래그에 의해) 이는 File All로 매핑됩니다.
기 본 제공 사용자에 대한 권한 부여는 훨씬 더 흥미롭습니다. 첫 번째 string_ace는 루트 및 그 아래의 파일과 디렉터리에 모두 적용되며 List, Read, ReadEA, Traverse, Execute, ReadAttr, ReadControl 및 Sync를 허용합니다. 두 번째 string_ace는 루트 및 그 아래에 AddSubDir을 부여하며(IO—inherit-only 플래그에 의해), 세 번째 string_ace는 루트 아래의 디렉터리에 AddFile을 부여합니다. Windows 탐색기의 ACL 그래픽 인터페이스를 사용하여 이러한 사용 권한을 확인해도 동일한 내용을 볼 수 있습니다.

Windows 리소스 보호
Windows Server 2008 및 Windows Vista부터 구성 요소는 필요한 보안 설정을 해당 매니페스트에 선언하며 이는 Microsoft 코드 서명 루트에 의해 서명됩니다. 매니페스트는 파일과 연관된 다른 사용 권한 및 ACL을 지정합니다. 따라서 구성 요소가 설치되면 적절한 보안 설정도 함께 제공됩니다. 또한 OS 파일은 WRP(Windows 리소스 보호)를 통해 시스템 관리자의 의도하지 않은 실수로부터 보호됩니다. WRP는 새로운 시스템 수준 엔터티인 신뢰할 수 있는 설치 관리자를 사용하여 시스템 파일과 폴더를 소유하고 관리합니다.
Windows Vista에는 일반 사용자가 권한이 부여된 구성 요소를 설치할 수 있도록 허용하는 유용한 기능이 추가되었습니다. 따라서 고급 사용자 역할이 더 이상 필요 없으며 고급 사용자 SID를 포함하는 ACE 인스턴스가 제거되었습니다. 고급 사용자 그룹은 여전히 존재하지만 구성 요소 매니페스트를 검색하여 PU에 대해 발견되는 모든 권한 부여 인스턴스를 삭제했습니다.
시스템 디렉터리에서 새로운 사용 권한을 살펴보겠습니다. 다음 역시 SDDL 읽기 연습용으로 좋습니다.
C:\>cacls c:\windows /s
C:\Windows "D:PAI(A;;FA;;;S-1-5-80-956008885-3418522649-18310
38044-1853292631-2271478464)(A;CIIO;GA;;;S-1-5-80-956008885-3
418522649-1831038044-1853292631-2271478464)(A;;0x1301bf;;;SY}
(A;OICIIO;GA;;;SY)(A;;0x1301bf;;;BA)(A;OICIIO;GA;;;BA)(A;;0x1200a9;;;BU)
(A;OICIIO;GXGR;;;BU)(A;OICIIO;GA;;;CO)"
신뢰할 수 있는 설치 관리자의 SID는 S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464입니다. TI를 축약형으로 사용하여 다음과 같은 항목을 얻을 수 있습니다.
C:\Windows "D:PAI
(A;;FA;;;TI)(A;CIIO;GA;;;TI)
(A;;0x1301bf;;;SY)(A;OICIIO;GA;;;SY)
(A;;0x1301bf;;;BA)(A;OICIIO;GA;;;BA)
(A;;0x1200a9;;;BU)(A;OICIIO;GXGR;;;BU)
(A;OICIIO;GA;;;CO)" 
해석하면 Windows NT 5.0 상속 모델을 사용하여 C:\Windows에 적용되는 보호되는 ACE임을 알 수 있습니다.
신뢰할 수 있는 설치 관리자에는 C:\Windows에 대한 모든 권한이 부여되며 C:\Windows 아래의 모든 자식 컨테이너에 대한 Generic_All이 부여됩니다(CI이므로 상속만 해당).
시 스템과 관리자에게는 C:\Windows에 대한 Read, Write, Append, ReadEA, WriteEA, Execute, ReadAttr, WriteAttr, Del, RCtl 및 Sync, = SDGRGWGX가 부여됩니다. 이것은 Generic_All에서 Write_Owner 및 Write_DAC를 제외한 것입니다. 관리자와 시스템에는 소유자 또는 ACL을 변경할 수 있는 능력을 제외한 모든 권한이 부여됩니다. "BA"와 "SY"는 자식 파일과 디렉터리 개체에 대한 Generic_All을 가집니다.
관 리자는 소유 권한을 가지므로 여전히 WriteOwnership을 주장하고 제어 권한을 취할 수 있습니다. 관리자와 시스템은 보안상 동일합니다. 그러나 이 권한이 있는 경우 관리자는 마음만 먹으면 WRP ACL 제어를 속일 수 있습니다.
CO 도 자식 파일과 디렉터리 개체에 대한 Generic_All을 가집니다. 기본 제공 사용자는 C:\Windows에 대한 Read, ReadEA, Execute, ReadAttr, RCtl 및 Sync, = GRGX를 가지며 C:\Windows 아래의 하위 디렉터리와 파일에 대한 GRGX를 가집니다.
모 든 시스템 파일과 폴더는 신뢰할 수 있는 설치 관리자에게 모든 권한을 부여하는 보호되는 ACL을 가집니다. 신뢰할 수 있는 설치 관리자에 의한 파일 제어는 시스템 루트 디렉터리의 선언이 아닌 Windows 구성 요소의 개별 선언에 나타납니다.

안전한 파일 시스템 사용 권한 설정
이 제 파일 시스템 ACL의 작동 방식과 이를 읽는 방법을 어느 정도 살펴보았으므로 다음은 이를 설정하는 방법을 알아보겠습니다. 응용 프로그램을 설치하는 경우 기본 Program Files 위치에 설치해야 합니다. 이 위치에 대한 기본 ACL은 관리자와 로컬 시스템에 모든 권한을 제공하며, 이는 적절합니다.
응 용 프로그램을 다른 위치에 설치하는 경우, 또는 원하는 위치에 응용 프로그램을 설치할 수 있는 권한을 사용자에게 부여하는 경우 문제가 발생합니다. 다른 드라이브에 대한 기본 ACL, 그리고 시스템 드라이브에서 시스템 및 응용 프로그램 영역이 아닌 영역에 대한 기본 ACL은 충분히 안전하지 않습니다. 이러한 경우에는 적절하게 보호되는 DACL로 폴더의 ACL을 명시적으로 지정해야 합니다. 응용 프로그램을 설치하기 위한 가장 간단하고 안전한 선택은 Program Files 폴더의 보안 설정을 복제하는 것입니다. 이 방법을 사용하지 않을 경우 관리자가 아닌 사람은 DACL이나 실행 파일의 소유권을 변경할 수 없도록, 그리고 실행 파일이 포함된 디렉터리에 파일을 작성, 추가 또는 삭제하지 못하도록 DACL을 설정하십시오.
DACL 을 설정할 때 기본적인 규칙은 사용자가 작성한 코드를 관리자 또는 다른 사용자가 실행하지 못하도록 하는 것입니다. 이러한 실행이 특히 문제가 되는 경우는 일반적으로 신뢰할 수 있는 영역(Windows, Program Files 등)에 존재한다는 이유로 해당 폴더가 신뢰할 수 있는 폴더로 간주되는 경우입니다. 이 경우 관리자로의 EoP(권한 상승)가 허용되어 사용자 간 공격의 위험성이 높아집니다. 따라서 사용자가 이러한 폴더에 파일을 쓸 수 있다면 다른 사용자와 관리자가 이를 실행할 수 없도록 해야 합니다.
얼 핏 생각하기에는 사용자에게 Windows, System, Program Files 등의 폴더에 대한 쓰기를 전혀 허용하지 않아야 되는 것 같습니다. 그러나 사용자가 이러한 위치에 쓸 수 있어야 하는 합당한 이유가 있습니다. 가장 일반적인 이유는 오류 로그 데이터 기록입니다. 실행 파일이 사용자의 자격 증명으로 실행되고 오류를 기록해야 하는 경우 이 파일에는 오류 로그/로깅 폴더에 대한 쓰기/추가 액세스가 필요합니다. 다중 사용자 시스템에서 사용자별 위치에 오류를 기록하면 로깅 데이터가 실행 파일과 연결되지 않고 시스템 이곳저곳에 분산됩니다. 응용 프로그램과 서비스는 일반적으로 공유 폴더나 레지스트리 키에 씁니다. 사용자 권한으로 실행되는 프로세스가 지정된 시스템 레지스트리 키에 오류 정보를 저장하는 경우가 많으므로 레지스트리에서도 동일한 문제가 발생합니다.
사 용자가 쓸 수 있는 파일과 실행할 수 있는 파일을 구분해야 합니다. 신뢰되어야 하는 파일(예: 실행 파일)과 신뢰되지 않아야 하는 파일(신뢰되지 않은 사용자가 쓸 수 있는 모든 파일)에 각기 별도의 디렉터리를 사용하십시오. 디렉터리에 적절하게 ACL을 지정하십시오. 실행 파일에 대한 관리자 제어와 사용자 읽기/실행을 포함하고 쓰기는 제외하십시오. 레지스트리 키와 하위 키에도 같은 지침이 적용됩니다.
여 기에서 클라이언트와 서버에는 차이가 있습니다. 서버 관리자는 관리자로 실행하는 사용자에 비해 지식 수준이 훨씬 높은 것으로 간주됩니다. 서버 관리자는 신뢰되지 않는 시스템 영역의 코드를 실행하면 안 된다는 것을 알고 있습니다. 시스템에서 실행 파일로부터 데이터 파일을 격리하는 명명 규칙을 설정하면 관리자에게 실행 파일의 신뢰성에 대한 지침을 제공할 수 있습니다. 로깅 하위 디렉터리는 신뢰할 수 없으므로 사용자가 이러한 하위 디렉터리를 만들거나 수정할 수 없도록 해야 합니다. 그렇지 않으면 사용자가 안전한 명명 규칙을 스푸핑할 수 있기 때문입니다.
클 라이언트 환경에서는 코드를 실행하도록 관리자를 속이기가 훨씬 쉽습니다. 이렇게 속이기 쉬운 관리자 있는 경우 사용자가 실행 파일을 설치한 후 이러한 코드를 실행하도록 관리자를 속여 시스템을 손상시킬 수 없도록 사용자 쓰기가 가능한 디렉터리에 대해 관리자 실행 권한을 허용하지 말아야 합니다. 예를 들어 응용 프로그램이나 서비스에서 사용자 권한으로 작성되는 로그 정보를 저장해야 하는 경우 이 데이터를 저장할 로깅 하위 디렉터리를 만들어야 합니다. 이 하위 디렉터리는 관리자 실행을 허용하지 않아야 합니다. 이렇게 하는 한 가지 방법은 D;OI;WP;;;WD와 같이 모든 사용자에 대해 앞에 명시적인 파일 실행 거부를 추가하는 것입니다. 이렇게 하면 사용자에게 파일 쓰기 또는 수정을 허용하는 디렉터리에서 사용자 간 공격을 방지할 수 있습니다.
사 용자가 데이터를 공유해야 하는 경우가 많이 있습니다(공유 영역에서 코드를 공유하고 실행하는 것은 바람직하지 않지만). 예를 들어 집에서는 사용자(또는 사용자의 사진 보기 응용 프로그램)가 C:\Photos와 같은 폴더를 만드는 경우가 있습니다. 사용자는 여러 사용자에게 이 폴더에 대한 쓰기를 허용하고 여러 사용자가 이 폴더의 다양한 사진을 편집할 수 있도록 허용하기를 원합니다. Windows Vista 시스템 드라이브의 루트에 있는 기본 ACL은 이를 지원합니다. 한 폴더에 데이터를 넣어 두고 다른 사용자가 이를 읽을 수 있도록 하는 것도 흔히 볼 수 있는 공유 상황입니다. 삭제 또는 수정은 해당 데이터를 만든 사람에게만 허용되지만 다른 사용자가 이를 복사하여 복사본을 편집할 수 있습니다. 이는 공유 읽기 시나리오이며 Windows Server 2008 시스템 드라이브의 기본 상태입니다.
시 스템 드라이브를 잠그고, 특히 공유용 ACL 폴더를 잠그는 경우를 고려해 보겠습니다. 이러한 두 가지 일반적인 시나리오에 적합한 ACL을 선택해야 합니다. 관리자는 개체를 관리할 수 있어야 하고, 이러한 폴더에서의 코드 실행과 관련된 보안 문제는 방지해야 합니다(여기에서 ACE는 이러한 폴더에서 소유자조차 코드를 실행하지 못하도록 함).
다음은 공유 읽기 ACE입니다.
D:P(D;OI;WP;;;WD)(A;OICI;FA;;;BA)(A;OICI;FA;;;SY)(A;OICI;FA;;;CO)(A;CI;0x1200af;;;AU)(A;OI;GR;;;AU)
다음은 공동 작업 ACE입니다.
D:P(D;OI;WP;;;WD)(A;OICI;FA;;;BA)(A;OICI;FA;;;SY)(A;OICI;FA;;;CO)(A;OICI;SDGRGW;;;AU)
두 ACL 모두 사용자 시스템 및 사용자 간 공격을 방지하기 위해 모든 사용자에 대한 실행 거부 ACE, 개체 상속(파일에 적용하기 위함)으로 시작합니다. 그런 다음 관리자, 시스템 및 CO에 모든 권한, 즉 File All을 부여합니다(사실 시스템에는 필요 없음).
공 유 읽기 시나리오의 경우 인증된 사용자에게는 CI에 대한, 그리고 디렉터리에 대한 권한 부여의 제한에 의해 List, AddFile, AddSubDir, ReadEA, Traverse, ReadAttr, RCtl 및 Sync가 부여되며, 모든 파일에 대해 Generic Read가 별도로 부여됩니다. 공동 작업 시나리오의 경우 인증된 사용자에게는 파일 및 디렉터리에 대한 Delete, Generic Read, 및 Generic Write가 부여됩니다.

레지스트리 및 해당 사용 권한 관리
Windows는 상태 정보의 대부분을 Windows 레지스트리에 저장합니다. 레지스트리 데이터 저장소는 하이브라고 하며, 하이브에서 데이터는 컨테이너라고 할 수 있는 키 및 하위 키에 저장됩니다(하위 키는 개체로 볼 수 없음).
사 용자별 데이터는 Hive Key Users(HKEY_USERS)의 적절한 사용자 섹션에 저장됩니다. 누구나 예상하듯이 이 데이터의 대부분은 사용자가 쓸 수 있습니다. 모든 세션에서 HKey_Current_User(HKCU)는 적절한 HKEY_USERS 섹션을 가리킵니다.
시 스템과 컴퓨터 정보는 HKEY_LOCAL_MACHINE(HKLM) 하이브에 저장됩니다. HKLM에는 모든 시스템 서비스에 대한 정보가 포함되어 있으며, 현재 이러한 서비스의 대부분은 다양한 로컬 서비스 또는 네트워크 서비스 그룹에서 제한된 사용 권한으로 실행됩니다. 서비스와 응용 프로그램은 해당 레지스트리 키에 상태 정보를 저장할 수 있습니다. 이 정보는 서비스 키 또는 서비스 키 아래의 키로 하위 키에 저장되어야 합니다. 서비스 키에는 서비스가 자체 서비스 키 대신 SetKey를 가지도록 ACL을 지정하면 안 됩니다(또는 이러한 공격을 가능하게 하는 WDac 또는 WOwn). 이렇게 할 경우 서비스가 다른 실행 파일을 가리킬 수 있기 때문입니다. 이러한 오류가 있을 경우 시스템이 로드될 때 서비스 제어 관리자가 이 실행 파일을 로드하게 되므로 서비스 호스트에 대한 잠재적인 EoP가 발생합니다.
HKLM 의 DACL에 대한 일반적인 지침은 이 데이터 또는 관련된 ACL 및 소유권을 사용자가 쓰거나 수정하도록 하면 안 된다는 것입니다. 시스템 영역에서의 파일 시스템 DACL 설정에 대한 지침과 마찬가지로, 사용자 또는 제한된 컨텍스트에서 실행되는 응용 프로그램이나 서비스가 오류 정보를 기록해야 하는 경우 오류 로깅에 대해 예외가 발생합니다. 이러한 경우에 대한 지침은 파일 시스템의 해당 문제에 대한 지침과 비슷합니다. 즉, 이러한 정보를 위한 별도의 키를 만들고 적절하게 ACL을 지정해야 합니다. 따라서 중요한 정보는 신뢰되는 대상(관리자, 시스템 등)에 ACL을 지정하고 로깅 데이터는 필요에 따라 쓰기 가능하도록 지정할 수 있습니다.
사 용자가 사용자 또는 관리자용 도구를 통해 신뢰되는 매개 변수를 수정(예: 바이러스 방지 또는 맬웨어 방지 서비스를 해제)하거나 변조하지 못하도록 해야 합니다. 메모장이 호출되면 C:\windows\notepad.exe가 로드된다고 가정해 보겠습니다. C:\windows에 대한 기본 ACL은 공격자가 이 실행 파일을 수정하도록 허용하지 않습니다. 공격자가 메모장 아이콘에서 해당 실행 파일에 대한 링크를 수정할 수 있다면 이 공격자는 다른 파일(예: C:\tools\load_rootkit.exe)을 로드할 수 있습니다. 이렇게 하면 루트킷을 로드한 다음 메모장을 로드하여 사용자가 침해 사실을 인식하지 못하도록 할 수 있습니다.
공 격자가 레지스트리를 통해 링크를 조작할 수 있다면 파일 시스템에 대한 보호 ACL이 무력화됩니다. 제한된 시스템 서비스의 다른 시스템 서비스에 대한 공격에도 주의해야 합니다. Windows Vista와 Windows Server 2008에서 서비스는 필요한 권한에 따라 별도로 그룹화됩니다. 이 서비스 격리에서 제공하는 심층적인 보호를 위해서는 특히 다른 서비스 그룹 간에 서비스가 다른 서비스를 조작하지 못하도록 서비스 사용 권한을 구성해야 합니다.
사 용자가 악성 실행 파일을 추가하거나 연결하지 못하도록 방지하는 데 주의를 기울이는 것과 마찬가지로 서비스가 자체 사용 권한과 기능을 변경하지 못하도록 방지해야 합니다. 서비스에 대한 ChangeConf 권한은 관리자, 시스템 또는 신뢰할 수 있는 설치 관리자에게만 허용해야 합니다. 이 권한이 있으면 권한 소유자가 서비스에 대한 사용 권한을 변경할 수 있기 때문입니다.

요약
Windows에서 제공하는 풍부한 사용 권한 제어 집합을 사용하면 작업을 허용 및 차단하고 새로운 위협에 대한 심층적인 방어책을 제공할 수 있습니다. 그러나 이러한 풍부한 액세스 제어에는 복잡성이라는 문제가 필연적으로 수반됩니다.
몇 가지 일반적인 지침을 따르면 문제를 방지하는 데 도움이 됩니다. 예를 들어 시스템 기본값은 적절한 타협점이므로 이러한 기본값을 사용해야 합니다. Program Files 폴더 외부에 응용 프로그램을 설치하는 경우 프로그램 파일 ACL을 사용해야 합니다. 드라이브에 대한 기본적인 사용자 권한 부여와 같은 기본값을 조금 더 엄격하게 조정해야 하는 경우도 있지만, 이 경우 잠재적인 응용 프로그램 호환성 문제를 해결해야 한다는 점을 기억하십시오.
가 장 중요한 지침은 관리자 또는 시스템 계정은 사용자가 쓰거나 수정할 수 있는 코드를 실행하거나 이러한 코드로 연결되는 포인터를 따라가면 안 된다는 것입니다. 또한 사용자는 다른 사용자가 쓰거나 수정할 수 있는 코드를 실행하거나 이러한 코드로 연결되는 포인터를 따라가면 안 된다는 점 역시 이에 못지않게 중요합니다. 이러한 지침을 통해 여기에서 설명한 모든 문제를 처리할 수 있습니다. 모든 변경 작업이 이 지침에 부합한다면 가장 심각한 보안 문제를 피해갈 수 있습니다.
액세스 제어 구성 요소에 대한 자세한 내용은 MSDN에서 "액세스 제어 구성 요소"를 참조하십시오. ace_string 액세스 마스크 구성 요소에 대한 내용은 MSDN "ACCESS_MASK" 기사를 참조하십시오. 이 기사에는 파일, 디렉터리, 레지스트리 키 및 공유 섹션의 구체적인 권한에 대한 포인터가 포함되어 있습니다. 제한된 SID에 대한 자세한 내용은 MSDN "제한된 토큰" 기사를 참조하십시오.

전체 권한 목록
그림 A 표준 권한
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\figa.gif
그림 B 파일 및 디렉터리에 대한 구체적인 권한
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\figb.gif
그림 C 파일 맵 및 레지스트리에 대한 구체적인 권한
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\figc.gif
그림 D 서비스 제어 관리자 및 서비스에 대한 구체적인 권한
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\figd.gif
그림 E 프로세스 및 스레드에 대한 구체적인 권한
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\fige.gif
그림 F WindowStations 및 바탕 화면에 대한 구체적인 권한
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\figf.gif
그림 G 기호화된 링크 및 이벤트에 대한 구체적인 권한
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\figg.gif
그림 H 세마포 및 뮤텍스에 대한 구체적인 권한
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\figh.gif
그림 I 파이프 및 토큰에 대한 구체적인 권한
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\figi.gif
그림 J 일반적이거나 잘 알려진 계정 및 해당 SID 설정
\\msdnmagtst\MTPS\MSDN\issues\en\08\11\Michener - WinPermissions.1108\FIGURES\figj.gif
John R. Michener는 Microsoft의 선임 보안 프로그램 관리자이며 약 5년 전에 Microsoft Windows Security에 합류했습니다. John은 시스템 보안 분야에 20년 이상의 경력을 보유하고 있으며 3개의 보안 업체를 설립했습니다. 현재 Windows Software Assurance 팀에서 암호화 및 사용 권한 전문가로 일하고 있습니다. 문의 사항이 있으면 jmichene@microsoft.com으로 연락하십시오.



AND

출처: http://blog.naver.com/knuabhoony?Redirect=Log&logNo=40014321712

일반적으로 ACL 이라고만 하면 DACL를 뜻함.

DACL = discretionary access control list

SACL = security access control list

 

DACL에는 ACEs = access control entries 가 있음.

 

둘은 비슷해 보이나 DACL은 권한을 설정하는 역할 SACL은 파일이나 폴더 혹은 주변기기 오프젝트에 접근하는 이벤트 발생시 기록(log)을 할수있다. 따라서 개발자는 DACL을 SA는 SACL쪽을 더 깊게 공부하게 된다. 따라서 MCSD 트랙에서는 SACL은 공부하지 않고 뭔지만 알면 된다.

 

DACL은 명시된것이 누적되는 구조이다. 무조건 allow 하는쪽으로 합해지지도 않고 무조건 deny하는쪽으로 합해지는 것도 아니고 explicit한 명제의 교집합이라고 보면 된다.

 

DACL의 ACE에는 통상적인 것과 special 한것이 있는데, 통상적인 것과 special 한것의 관계는 포함관계이다. 통상적인 것은 Full permission, modify permission ...... read permission 등이 있는데

Full 은 모든 special ACE가 포함된 것, modify는 권한변동에 관련된것 두개만 빠진 나머지 모두 read는 read와 execute 두개만 포함된 것이다.

 

DACL을 수정하는 방법에는 3가지가 있다.

1. 오브젝트를 오른쪽 클릭하여, 속성(혹은 등록정보), 보안탭을 클릭하여

   윗쪽의 user를 선택한 다음 아랫쪽에서 그 user에 맞는 권한을 주면 된다.

 

2. cacl.exe 나 xcacl.exe를 사용한다. (xcacl.exe가 없는 OS는 마소 사이트에서 받을수 있음)

    cacl은 통상적인 권한 부여, 수정, Xcacl은 special한 권한의 부여, 수정을 할수있다.

    다양한 옵션을 쓸수 있는데 /T는 하위폴더 전체포함 /G 유저:F 하면 해당 유저에 Full 퍼미션 Grant 허용 /D 하면 deny 등등이 있다.

 

3. win32 API에서 어플리케이션에서 직접 조정(범위를 벗어나므로 방법이 있다는 것만 알아두면됨)

 

 

이상의 내용은 마소 공식 어플리케이션 보안 MOC의 4장 1절 ACL 부분을 공부하고 책을 보지않은채로 머릿속의 내용을 정리한 것이므로 영어와 한국어가 마구마구 섞여 있음(아직 번역판이 안나와있음) 가장 중요한것은 DACL이 뭔지, 어떤 ACE가 있는지, 어떻게 부여, 수정할수 있는지 아는 것.

 

수거!


AND

출처: http://blog.naver.com/blue7red?Redirect=Log&logNo=100054684295

1.NT의 보안

(1)NT의 보안모델

-시스템의 자원을 사용잡로 허가하거나 거부할 수 있어야 한다.

-프로세스에서 해제된 메모리 내용은 읽을 수 없도록  보호되어야 한다.

-시스템을 사용하는 사람은 반드시 로긴 과정을 거쳐 자신의 신분을 밝혀야 한다.

-관리자는 보안과 관련된 이벤트를 감시할 수 있다.

-운영체제는 스스로 자신의 실행코드를 보호할 수 있어야 한다.

 

(2)보안실습

-

 

2.보안설명자

(1)보안설명자

-

[보안오브젝트]

-파일/파이프/콘솔화면버퍼/프로세스/스레드/파일맵핑/액세스토큰/

 레지스트리/서비스/프린터/공유폴더/이벤트/뮤텍스/세마포어

 

(2)SID와 액세스 토큰

-SID : 보안식별자 ,로긴하는 사용자나 그룹에 붙이는 ID

 

 

(3)ACL

-보안설명자는 두 개의 ACL을 가지고 있다. 하나는 액세스권한에 대한 목록인 DACL이며

 나머지 하나는 감사 기록 작성을 통제하는 SACL이다.

 

(4)액세스 권한

-ACE의 정보는 누구에게 어떤 액세스 권한을 허가 또는 금지할 것인가를 지정한다.

 

3.보안 설명자 프로그래밍

(1)GetSecurity

-

#include <windows.h>
#include <aclapi.h>

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
HWND hWndMain;
LPCTSTR lpszClass=TEXT("GetSecurity");

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
   ,LPSTR lpszCmdParam,int nCmdShow)
{
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 g_hInst=hInstance;

 WndClass.cbClsExtra=0;
 WndClass.cbWndExtra=0;
 WndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
 WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
 WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
 WndClass.hInstance=hInstance;
 WndClass.lpfnWndProc=WndProc;
 WndClass.lpszClassName=lpszClass;
 WndClass.lpszMenuName=NULL;
 WndClass.style=CS_HREDRAW | CS_VREDRAW;
 RegisterClass(&WndClass);

 hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
  NULL,(HMENU)NULL,hInstance,NULL);
 ShowWindow(hWnd,nCmdShow);

 while (GetMessage(&Message,NULL,0,0)) {
  TranslateMessage(&Message);
  DispatchMessage(&Message);
 }
 return (int)Message.wParam;
}

TCHAR gMes[1024]="마우스 왼쪽 버튼을 눌러 보안 정보를 보고자"
 " 하는 파일을 선택하십시오";
void GetSecurity()
{
 OPENFILENAME OFN;
 TCHAR lpstrFile[MAX_PATH]="";
 HANDLE hFile;
 TCHAR Mes[255];
 PSECURITY_DESCRIPTOR pSD;
 PSID pOwner;
 PACL pDacl;
 int i;
 DWORD cbName, cbDomain;
 TCHAR *Name, *Domain;
 SID_NAME_USE peUse;
 ULONG nAce;
 PEXPLICIT_ACCESS pEntry;

 // 대상 파일의 이름을 얻는다.
 memset(&OFN, 0, sizeof(OPENFILENAME));
 OFN.lStructSize = sizeof(OPENFILENAME);
 OFN.hwndOwner=hWndMain;
 OFN.lpstrFilter="Every File(*.*)\0*.*\0";
 OFN.lpstrFile=lpstrFile;
 OFN.nMaxFile=256;
 OFN.lpstrInitialDir="c:\\";
 if (GetOpenFileName(&OFN)==0) {
  return;
 }

 // 파일을 연다.
 hFile=CreateFile(lpstrFile, GENERIC_READ, 0, NULL,
  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 if (hFile == INVALID_HANDLE_VALUE)
  return;

 // 파일명을 출력한다.
 wsprintf(Mes, "파일명=%s\n", lpstrFile);
 lstrcpy(gMes,Mes);

 // 보안 설명자를 읽는다.
 if (GetSecurityInfo(hFile,SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION |
  DACL_SECURITY_INFORMATION,&pOwner,NULL,&pDacl,NULL,
  (LPVOID *)&pSD)!=ERROR_SUCCESS) {
  MessageBox(hWndMain, "보안 설명자를 읽을 수 없습니다","에러",MB_OK);
  return;
 }
 CloseHandle(hFile);

 // 소유자 정보 보여주기
 cbName=0;
 cbDomain=0;
 LookupAccountSid(NULL, pOwner, NULL, &cbName, NULL, &cbDomain, &peUse);
 Name=(TCHAR *)malloc(cbName);
 Domain=(TCHAR *)malloc(cbDomain);
 LookupAccountSid(NULL, pOwner, Name, &cbName, Domain, &cbDomain, &peUse);

 wsprintf(Mes, "소유자=%s\n", Name);
 lstrcat(gMes,Mes);

 wsprintf(Mes, "소유자 도메인=%s\n", Domain);
 lstrcat(gMes,Mes);

 free(Name);
 free(Domain);

 // DACL의 정보 보여주기
 GetExplicitEntriesFromAcl(pDacl, &nAce, &pEntry);
 wsprintf(Mes, "ACE의 개수=%d\n", nAce);
 lstrcat(gMes,Mes);

 for (i=0;i<(int)nAce;i++) {
  cbName=0;
  cbDomain=0;
  LookupAccountSid(NULL, pEntry[i].Trustee.ptstrName, NULL, &cbName,
   NULL, &cbDomain, &peUse);
  Name=(TCHAR *)malloc(cbName);
  Domain=(TCHAR *)malloc(cbDomain);
  LookupAccountSid(NULL, pEntry[i].Trustee.ptstrName, Name, &cbName,
   Domain, &cbDomain, &peUse);

  wsprintf(Mes, "%s사용자에게 %x 액세스 권한을 %s한다.\n", Name, 
   pEntry[i].grfAccessPermissions
   pEntry[i].grfAccessMode == GRANT_ACCESS ? "허가":"거부");
  lstrcat(gMes,Mes);
  free(Name);
  free(Domain);
 }

 // 메모리 해제하고 결과를 화면으로 출력한다.
 LocalFree(pEntry);
 LocalFree(pSD);
 InvalidateRect(hWndMain, NULL, TRUE);
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
 HDC hdc;
 PAINTSTRUCT ps;
 RECT crt;

 switch (iMessage) {
 case WM_CREATE:
  hWndMain=hWnd;
  return 0;
 case WM_LBUTTONDOWN:
  GetSecurity();
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd, &ps);
  GetClientRect(hWnd,&crt);
  DrawText(hdc,gMes,-1,&crt,0);
  EndPaint(hWnd, &ps);
  return 0;
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 }
 return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

 

(2)보안설명자 읽기

-

 

(3)소유자 정보 조사

-LookupAccountSid

 

 

(4)DACL 읽기

-GetExplicitEntriesFromAcl

 

(5)보안설명자 생성

-

#include <windows.h>
#include <aclapi.h>

void SetSecurity();
HINSTANCE g_hInst;

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
    ,LPSTR lpszCmdParam,int nCmdShow)
{
 g_hInst=hInstance;

 SetSecurity();

 MessageBox(NULL, "보안 설명자를 생성했습니다","알림",MB_OK);
 return 0;
 
}

void SetSecurity()
{
 HANDLE hFile;
 TCHAR *str="누구나 읽을 수 있으며 User1만 쓸 수 있습니다";
 DWORD dwWritten;
 EXPLICIT_ACCESS EA[2];
 TCHAR pSid[255];
 TCHAR pDomain[255];
 DWORD cbSid=255,cbDomain=255;
 SID_NAME_USE peUse;
 PACL pAcl;
 SECURITY_DESCRIPTOR SD;
 SECURITY_ATTRIBUTES SA;

 // Everyone의 SID를 구한다.
 SID_IDENTIFIER_AUTHORITY SIDEvery=SECURITY_WORLD_SID_AUTHORITY;
 PSID pEverySID;
 AllocateAndInitializeSid(&SIDEvery,1,SECURITY_WORLD_RID,0,0,0,0,0,0,0,&pEverySID);

 memset(EA,0,sizeof(EXPLICIT_ACCESS)*2);
 EA[0].grfAccessPermissions=GENERIC_READ;
 EA[0].grfAccessMode=SET_ACCESS;
 EA[0].grfInheritance=NO_INHERITANCE;
 EA[0].Trustee.TrusteeForm=TRUSTEE_IS_SID;
 EA[0].Trustee.TrusteeType=TRUSTEE_IS_WELL_KNOWN_GROUP;
 EA[0].Trustee.ptstrName=(LPTSTR)pEverySID;

 // User1의 SID를 구한다.
 LookupAccountName(NULL,"User1",(PSID)pSid,&cbSid,pDomain,

&cbDomain, &peUse);

 // ACE를 만든다.
 EA[1].grfAccessPermissions=GENERIC_ALL;
 EA[1].grfAccessMode=SET_ACCESS;
 EA[1].grfInheritance=NO_INHERITANCE;
 EA[1].Trustee.TrusteeForm=TRUSTEE_IS_SID;
 EA[1].Trustee.TrusteeType=TRUSTEE_IS_USER;
 EA[1].Trustee.ptstrName=(LPTSTR)pSid;

 // ACE를 ACL에 포함시키고 새 ACL을 만든다.
 SetEntriesInAcl(2,EA,NULL,&pAcl);

 // SD를 초기화한다.
 InitializeSecurityDescriptor(&SD, SECURITY_DESCRIPTOR_REVISION);

 // ACL을 SD에 포함시킨다.
 SetSecurityDescriptorDacl(&SD,TRUE,pAcl,FALSE);

 // 보안 속성을 만든다.
 SA.nLength=sizeof(SECURITY_ATTRIBUTES);
 SA.lpSecurityDescriptor=&SD;
 SA.bInheritHandle=FALSE;

 // 파일을 생성한다.
 hFile=CreateFile("c:\\User1Only.txt", GENERIC_ALL, 0, &SA,
  CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
 WriteFile(hFile,str,lstrlen(str),&dwWritten,NULL);
 CloseHandle(hFile);

 // 실행중에 할당한 메모리를 해제한다.
 FreeSid(pEverySID);
 LocalFree(pAcl);
}

 

4.특권

(1)특권의 종류

-

void EnumPrivileges(HDC hdc)
{
 int i;
 int y=10;
 TCHAR buf[255],Mes[255];
 DWORD size;
 DWORD LangID;
 
 TCHAR arPri[][50]={
  SE_CREATE_TOKEN_NAME,SE_ASSIGNPRIMARYTOKEN_NAME,SE_LOCK_MEMORY_NAME,
  SE_INCREASE_QUOTA_NAME,SE_UNSOLICITED_INPUT_NAME,SE_MACHINE_ACCOUNT_NAME,
  SE_TCB_NAME,SE_SECURITY_NAME,SE_TAKE_OWNERSHIP_NAME,SE_LOAD_DRIVER_NAME,
  SE_SYSTEM_PROFILE_NAME,SE_SYSTEMTIME_NAME,SE_PROF_SINGLE_PROCESS_NAME,
  SE_INC_BASE_PRIORITY_NAME,SE_CREATE_PAGEFILE_NAME,SE_CREATE_PERMANENT_NAME,
  SE_BACKUP_NAME,SE_RESTORE_NAME,SE_SHUTDOWN_NAME,SE_DEBUG_NAME,SE_AUDIT_NAME,
  SE_SYSTEM_ENVIRONMENT_NAME,SE_CHANGE_NOTIFY_NAME,SE_REMOTE_SHUTDOWN_NAME
 };
 
 for (i=0;i<sizeof(arPri)/sizeof(arPri[0]);i++) {
  size=255;
  LookupPrivilegeDisplayName(NULL,arPri[i],buf,&size,&LangID);
  wsprintf(Mes,"특권=%s,설명=%s",arPri[i],buf);
  TextOut(hdc,10,y,Mes,lstrlen(Mes));
  y+=20;
 }
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
 HDC hdc;
 PAINTSTRUCT ps;
 switch (iMessage) {
 case WM_CREATE:
  hWndMain=hWnd;
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd, &ps);
  EnumPrivileges(hdc);
  EndPaint(hWnd, &ps);
  return 0;
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 }
 return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

 

(2)시스템 재부팅

-

void MyRebootSystem()
{
 HANDLE hToken;
 TOKEN_PRIVILEGES tp;
 LUID luid;

 OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES |
  TOKEN_QUERY, &hToken);
 LookupPrivilegeValue(NULL,"SeShutdownPrivilege",&luid);

 tp.PrivilegeCount = 1;
 tp.Privileges[0].Luid = luid;
 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

 AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);

 ExitWindowsEx(EWX_REBOOT,0);
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
 HDC hdc;
 PAINTSTRUCT ps;
 TCHAR *Mes="마우스 왼쪽 버튼을 누르면 재부팅합니다";

 switch (iMessage) {
 case WM_LBUTTONDOWN:
  if (MessageBox(hWnd, "지금 재부팅하시겠습니까?","질문",
   MB_YESNO) == IDYES) {
   MyRebootSystem();
  }
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd, &ps);
  TextOut(hdc,50,50,Mes,lstrlen(Mes));
  EndPaint(hWnd, &ps);
  return 0;
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 }
 return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}




AND

출처: http://blog.daum.net/network_goshen60/6278682

 

임의 엑세스 제어(DACL)과 시스템 엑세스 제어(SACL), 통칭 ACL은 Security Descriptor에 포함되는 요소이다.

Security Descriptor는 가변 길이의 이진데이터 구조를 가지고 있고. ACL은 개체에 적용할 수 있는 보안 보호, 일련의 개체 등록 정보, 개체의 개별적인 등록 정보를 정의하는 액세스 제어 항목(ACE)의 정렬된 목록이다.

 

Security Descriptor의 데이터 구조

 

- Header : 헤더 필드에는 수정 횟수와 메모리 레이아웃, 표시될 요소, 특정 요소가 추가되거나 수정되는 방법 등 보안 설명자의 특성을

   설명하는 일련의 제어 플래그가 포함된다.

- Owner : 소유자 필드에는 개체 소유자의 SID가 포함된다. 개체의 소유자는 사용 권한을 수정하고 다른 사용자에게 소유권을 허가할

   수 있다

- Group SID(Primary Group) : 주 그룹 필드에는 소유자의 주 그룹 SID가 포함된다. 이정보는 Macintosh 서비스와 POSIX 하위

  시스템에 의해 사용된다.

- DACL : DACL은 액세스가 허가되거나 거부된 사용자와 허가되거나 거부된 엑세스 수준을 식별하는 0개 이상의 ACE 목록이다.

- SACL : SACL은 개체 엑세스를 감사하는 방법을 제어한다. 감사된 작업은 보안 로그에 이벤트가 기록된다.

 

 DACL의 ACE(Access Control Entity) 데이터 구조

 

액세스 제어 항목(ACE) : 보안 사용자가 개체에 수행할 수 있는 작업 또는 SACL에 있는 경우 어떤 작업을 감사할 것인지를 결정

 

DACL의 ACE

- 특정 사용자나 보안 그룹을 지정하는 SID

- ACE의 액세스 허용 여부를 지정하는 헤더

- 허가되거나 거부된 작업을 나열하는 액세스 마스크

- 하위 개체가 ACE를 상속할 수 있는지를 결정하는 일련의 비트 플래그

- 상속 플래그 : ACE 헤더에 위치, 상되되는 방법과 이를 상속한 하위 개체에 주는 영향을 제어

- ACE 유형을 나타내는 플래그

 

 

ACE의 유형

- Access denined : DACL에서 액세스를 거부하는데 사용

- Access Allowed : DACL에서 액세스를 허용하는데 사용

- System audit : SACL에서 액세스 시도를 기록하는데 사용

- Access denied, Obeject specific : DACL에서 등록 정보나 등록 정보 집합에 대한 엑세스를 거부하거나 특정 유형의 하위 개체에 대한

  상속을 제한하는데 사용

- Access allowed, Obeject specific : DACL에서 등록 정보나 등록 정보 집함에 대한 액세스를 허용하거나 특정 유형의 하위 개체에 개

  한 상속을 제한하는 데 사용

- System audit, Object specific : SACL에서 등록 정보나 등록 정보 집합에 액세스하려는 시도를 기록하거나 특정 유형의 하위 개체에

  대한 상속을 제한하는데 사용



AND

출처: http://blog.daum.net/jay74jung/4702712

Certificate Server의 설치 와 Client인증

국승수 sskuk@sskuk.cataegu.ac.kr

V0.1 2000년 11월 11일


이 문서는 제가 applet!사인과 관련하여 이것저것 조사하다가, OpenSSL이라는 것을 알게되서, OpenSSL을 이용한 Certificate Server(rootCA)를 설치하기 까지의 과정을 정리한 것이다. OpenSSL의 설치와, apache, mod_ssl, php, mysql등을 이용하여 Certificate Server를 운용하기 위한 방법론과, Netscape, MS Internet Explorer, JDK등의 Client에 대한 인증서를 발행하는 방법론을 담고 있다.


1. 저작권

이 문서에 나오는 등록상표의 소유권은 각각 그 소유자에게 있다. 이 문서의 내용에 대해 본인은 어떤 보증도 하지 않으며 (틀리는 내용도 있으니깐..^^;), 모든사람들이 공유할 수 있고, 배포할 수 있지만 다른곳에 배포할 때에는 원문이 어디에 있는지는 알려주시고, 문서의 내용을 수정 할 때에는 본인에게 메일을 주시길 바란다. (이렇게 쓰는거 맞아여?...^^;)

2. 준비물

  1. OpenSSL
  2. Apache
  3. Perl
  4. mod_ssl
  5. PHP
  6. Client Browser(Netscape나 Explorer)
  7. Java2 SDK
  8. ...
  9. 담배 한두갑 과 찐한 커피(필수!)
  10. 담배안피면 껌이나 사탕(^^)

OpenSSL만 있어도 Certificate Service를 처리하는데에는 문제가 없지만, 좀더 사용자를 편하게 할려면 나머지 들도 있는것이 좋다.

3. Certificate Server란?

Certificate Server는 인터넷에서 메일이나 프로그램(applet!, script같은것)등의 송신자를 믿을만한 사람이 보냈는지 인증해주는 서버이다. 쉽게 말하면 철수가 은행에 개인적인 문서를 Sign을 하여 보냈다고 하면, 은행의 입장에서는 이 메세지가 정말로 철수에게서 온것인지를 확인할 필요가 있다. 이때 PGP나 GPG처럼 비밀키와 공개키를 이용하여 철수는 비밀키로 사인하고 은행에서는 철수의 공개키를 이용하여, 수신된 메세지가 철수가 보낸것이 맞는지 확인할수 있다. 또한 은행에서 철수 한테 보내는 메세지인 경우에도 마찬가지 이지만, 서로간의 공개키가 정확하게 전달이 되었는지 확인할 필요가 있다. (보통 메일이나, 홈페이지등을 통하여 확인할수도 있고, 직접 만나서 finger print등을 적어와서 비교해볼수도 있다.)

만약 서로 상대방의 공개키가 정말로 믿을만한 인증기관에서 인증해준것 이라면, 상대방의 공개키가 맞다는것을 확인하는 수고를 덜수가 있는데, 이 인증기관을 Certificate Authority(CA)라고 부르며, CA에의해서 상대방의 공개키가 인증되어 있으면, 서로간에 직접 확인할 필요없이 공개키를 믿을 수 있게 되는것이다.

(OpenSSL에는 이것뿐만이 아니고 상당히 많은 기능을 가지고 있으나 제가 아는게 별로없네요...^^;) 또 Applet!을 작성해 보신분은 아시겠지만 인증서에의한 사인이 되어있는 경우에는 일부 시스템의 제한된 자원(프린터, 디스크, 사운드등)에 접근할수 있는 Applet!을 생성할수 있습니다. (다이얼패드를 사용할 때에 나타나는 창을 생각해보세요...^^)

위에서 나타난것 처럼, 인터넷에서 특정개인이나 기관에대한 인증을 해주는 곳이 CA이며, 이런 역활을 수행하는 서버가 Certificate Server이다. VeriSign이나 Thawte Consulting등에서 이런 서비스를 하고 있고, 기본적으로 Netscape나 MS Internet Explorer등의 신뢰된 인증기관에 나타난다. 본 문서는 VeriSign이나 Thawte Consulting등과 같은 서비스를 OpenSSL을 이용하여 실행할 수 있는 방법에 대하여 기술하고 있다.

OpenSSL은 Secure Sockets Layer와 Transport Layer Security프로토콜을 만족하는 Open Source 툴킷이다. OpenSSL은 Eric A. Young과 Tim J. Hudson에의해 만들어진 SSLeay 라이브러리를 기초로하여 만들어 졌고, 현재 OpenSSL-0.9.6이 사용가능하며, Unix와 Windows, OpenVMS, MacOS등의 플랫폼에서 실행된다.

4. Certificate Server의 설치

Certificate Server의 구성은 OpenSSLApache가 필요하며, 개인의 신상정보가 Web을 이용하여 전송됨으로 Apache 서버에 mod_ssl을 설치하거나 Apache + SSL의 형태로 Apache서버를 설치하여 Browser와의 통신시 sniffing되지 않도록 하여야 할 것이다. 또한 자동화된 서비스를 위해서 Perl이나 php등이 필요하다. (Perl이나 PHP는 module로 설치해도 좋으며 CGI형태로 실행해도 상관이 없으나 보안을 위한 부분을 생각해보고 설치하는것이 좋을것 같다.) 인증을 요구하는 Client등의 관리를 위하여 MySQL등을 설치하는 것도 좋을것 같다. 그리고 mod_ssl의 INSTALL화일을 살펴보면 선택적으로 설치하는 화일이 있는데(mm같은것) 이것들도 필요하면 같이 설치할 수 있다. Perl은 5.6버젼을 필요로 한다고 되어있는것 같은데, 5.6을 굳이 설치할 필요는 없었던것 같다.

4.1 OpenSSL의 설치

OpenSSL을 설치하기 위해서는 Perl 5와 ANSI C컴파일러가 필요하다. 기본적인 설치 방법은 인터넷상의 다른 패키지들처럼 다음과 같이하여 설치할수 있다.

        $ ./config
        $ make
        $ make test
        $ make install

config에서 prefix를 주지 않았을 때에는 /usr/local/ssl디랙토리에 설치가 되니 다른 디랙토리에 설치를 하고자 한다면 다음과 같이 한다. $ ./config --prefix=/usr/local --openssldir=/usr/local/openssl 이렇게 하면 OpenSSL의 실행화일은 /usr/local/bin에 설치되고 Certificate Service를 위한 화일들은 /usr/local/openssl아래의 디랙토리에 생성된다. 또한 rsaref를 선택사항으로 줄수가 있는데 이것은 librsaref.a라는 라이브러리가 라이브러리 Search경로에 있어야 한다. (법적으로 문제가 되는부분이 아닌가 모르겠네요..어디서 읽은것 같아서..-.-; ftp search에서 rsaref20으로 검색하시면 찾을수 있습니다...그런데, 넣고 컴파일하면 에러가 나더라구요..)

make를 실행하면 OpenSSL라이브러리(libcrypto.a와 libssl.a)와 실행화일 (openssl)이 생성되고, 라이브러리는 make를 실행한 디랙토리에, OpenSSL실행화일은 apps디랙토리에 생성된다. make를 실행하는 도중 에러가 생기면, 에러메세지를 살펴보아야 한다. 대부분 OpenSSL의 문제가 아니라고 하며, 정말로 OpenSSL의 문제라고 판단된다면 make report명령을 이용하여 출력된 내용을 openssl-bugs@openssl.org에 송신한다.

다음은 make test를 실행하여 OpenSSL이 정상적으로 동작하는지 확인한다. 실패한 내용이 있다면, CFLAGS등을 수정하고 "make clean; make"명령을 이용하여 다시 컴파일한후 make test를 실행해 본다.

모든 시험이 정상적으로 성공한다면, make install명령어를 이용하여 설치디랙토리(/usr/local/ssl이나 /usr/local/bin, /usr/local/openssl등)에 실행화일과 도움말 화일, 환경설정화일등을 설치한다. 여기까지 별 문제 없이 실행되었다면, Certificate Server를 실행하기 위한 기본적인 준비는 완료된 것이다. 다음은 OpenSSL을 이용한 Certificate Server운용을 위한 키생성과 환경설정을 실시한다.

4.2 rootCA의 생성

Certificate Server를 운용하는 곳은 Tree구조의 형태로 이루어져 있다. 제일 처음에 나타나는 CA를 rootCA라고 하고 자기 자신이 생성한 인증요구서를 자기자신이 sign하여 개인이나, 기관에게 배포한다. rootCA로부터 인증을 받은 인증기관은 중계인증기관이라고 하며, 인증요구서를 rootCA로 부터 인증받아서 다른사람이나 기관의 인증요구서를 인증해주는 역활을 한다. 지금부터는 앞에서 생성된 OpenSSL의 실행화일들을 이용해서 자신만의 rootCA를 생성한다.

(아래에서 설명하는 내용은 /path/to/openssldir/misc에 보시면 CA.pl과 CA.sh 가 있습니다. CA.xx를 적절히 수정하고 ./CA.xx -newca로 하여 rootCA를 생성하셔도 됩니다. Perl과 shell의 script임으로 크게 어려운것은 없을 겁니다...^^; "CATOP"변수를 적절히 수정하시면 됩니다. 또한 Client들의 Sign Request가 있을때에도 사용하실수 있으므로 자세히 살펴보시는것이 좋습니다.)

  1. 비밀키의 생성

    $ openssl genrsa -des3 -out ca.key 1024

    1024비트의 보안도를 가지는 RSA키를 생성한다. Certificate Server자체의 비밀키가 됨으로 받드시 다른사람이 볼수 없는곳에 보관하고 빽업을 받은후에 사용하는것이 좋다.

  2. 생성된 비밀키를 이용하여 Self Sign된 인증서 화일을 생성한다.

    $ openssl req -new -x509 -days 365 -key ca.key -out ca.crt

    위의 명령어를 이용하면 Certificate Server의 Distinguished Name을 물어온다. 질문에 대한 답을 정확하게 입력하고나면 rootCA의 Certificate Server의 인증서가 생성된다. 그리고 필요에 따라 days같은 항목은 수정해서 사용하도록 한다. (비밀번호 잊어먹지 않도록 주의하세요..T.T)

  3. openssl디랙토리의 openssl.cnf화일을 수정한다.

    openssl.cnf화일은 Certificate Service를 운용하기 위한 환경설정을 담고 있는 화일로 make install을 했을때에는 sample 자료가 들어있다. 이 화일은 편집하여 여러분의 Certificate Service를 할 수 있도록 수정 하여야 한다.

    1. CA_default 부분에 "dir"을 여러분이 사용할 디랙토리를 적는다.(보통은 "/path/to/openssldir/자기CA"의 형태)
    2. usr_cert부분의 nsCertType이 모두 #으로 막혀있으므로 필요한 내용을 골라서 풀어준다.(Netscape Client의 인증종류를 결정하는 부분인것 같다.)
    3. Ca_default의 dir에 필요한 디랙토리와 화일을 생성한다. 디랙토리는 certs, crl, newcerts, private이고 화일은 "01"의 내용을 담고있는 serial과 내용이 없는 index.txt이다. (CA.xx의 내용과 openssl.cnf를 참고하시면 됩니다.)
              $ mkdir /usr/local/openssl/MyCA
              $ mkdir /usr/local/openssl/MyCA/certs
              $ mkdir /usr/local/openssl/MyCA/crl
              $ mkdir /usr/local/openssl/MyCA/newcerts
              $ mkdir /usr/local/openssl/MyCA/private
              $ echo "01" > /usr/local/openssl/MyCA/serial
              $ touch /usr/local/openssl/MyCA/index.txt
      
    4. keyUsage부분의 #을 풀어준다.
    5. 필요하다면 nsComment를 원하는것으로 바꾼다.
  4. 생성된 비밀키와 공개키를 openssl.cnf에서 지정한 디랙토리에 복사한다.

    ca.key는 /path/to/openssldir/자기CA/private/cakey.pem으로 복사하고 ca.crt는 /path/to/openssldir/자기CA/cacert.pem정도로 복사하면 됩니다.

  5. 공개키는 application/x-x509-ca-cert의 MIME형태로 Client Browser에 전송할 수 있으며, Client에서는 "신뢰된 루트인증기관"으로 import!할 수 있다.

여기까지 하셨으면, 불편하지만 수동(?)으로 Certificate Service를 할 수 있습니다. 다음은 조금이나마 편안하게 Service를 하기 위해서 Apache에서 몇가지 작업을 합니다.(나중에 Client와 연결해서 CSR을 생성할때 사용합니다.)

4.3 Apache + mod_ssl/OpenSSL + PHP4/MySQL의 설치

일반적인 Apache 와 php의 설치 방법에 큰 차이는 없으니, 여기에서는 순서만 기술하고 넘어 가도록 한다. 또한 이 내용은 mod_ssl의 INSTALL화일에 설명이 되어 있으므로 그것을 읽어보는 것이 정확할 것이다. mod_ssl은 버젼별로 Apache와 연결이 됨으로 자신이 설치하는 Apache버젼과 일치하는 mod_ssl을 설치하여야 한다. 이는 mod_ssl의 화일명을 보면 알 수가 있는데, "mod_ssl-자신버젼-아파치버젼"의 형태로 되어있다.

        $ tar xvfz apache_1.3.x.tar.gz
        $ tar xvfz mod_ssl-2.7.x-1.3.x.tar.gz
        $ tar xvfz php-4.0.x.tar.gz
        $ cd apache_1.3.x
        $ ./configure
        $ cd ../mod_ssl-2.7.x-1.3.x
        $ ./configure --with-apache=../apache_1.3.x
        $ cd ../apache_1.3.x
        $ .configure --prefix=/path/to/apache
        $ cd ../php-4.0.x
        $ CFLAGS='-O2 -I/path/to/openssl/include' \
          ./configure \
                --with-apache=../apache_1.3.x \
                --with-mysql \
                --enable-memory-limit=yes \
                --enable-debug=no
        $ make
        $ make install
        $ cd ../apache_1.3.x
        $ SSL_BASE=/path/to/openssl \
          ./configure \
                --prefix=/path/to/apache \
                --enable-module=ssl \
                --activate-module=src/modules/php4/libphp4.a \
                --enable-module=php4
        $ make
        $ make certificate
        $ make install

컴파일 과정중 주의할 점은 마지막의 Apache의 환경설정을 할때에 SSL_BASE는 OpenSSL을 설치할때에 prefix에 주어진 디랙토리를 주어야 한다. (openssldir이 아니다.)

상기의 컴파일 과정을 거쳐서 생성된 Apache서버는 apachectl start명령을 이용하여 실행을 하게 되면 일반 Apache서버와 동일한 기능을 하게 되고 apachectl startssl 명령을 이용하면 mod_ssl을 이용한 https프로토콜을 사용할수 있게 된다. Client에서 사용법은 url에 "https://server/path/"라고 적게되며, 이때 Server와 Client간의 암호화 방법에 대한 협상이 이루어 지게 되고 이후에 Server와 Client간의 자료는 암호화 되어 전송이 됨으로, sniffer를 이용한 방법으로는 자료를 훔쳐볼수 없게 된다. 자세한것은 kldp.org에서 mod_ssl을 검색어로 찾아보길 바란다.

4.4 Apache Server의 키 생성과 인증

Apache + mod_ssl을 설치하면 기본적으로 30일간 사용할수 있는 Certificate가 /path/to/apache/conf/ssl.crt 디랙토리에 설치되어 있다. 이것을 여러분의 CA에서 인증한다면 여러분이 원하는 기간동안 사용할수 있는 Certificate가 생성된다.(1년이든 10년이든...^^;) (아래의 과정을 진행하다 보면 기존에 설치된 OpenSSL과 충돌하는 경우가 있습니다. 이때에는 기존에 설치된 OpenSSL을 제거 하시거나, "-config /path/to/openssldir/openssl.cnf"를 추가로 입력해서 사용하십시요.) 설치과정중 make certificate TYPE=custom으로 실행하는 경우에는 openssl에서 생성시킨 rootCA의 key와 certificate화일을 다시 설치해야 한다. 이때 생성된 rootCA에는 object sign(S/W에 사인하는것(?))이 빠져 있으므로 rootCA를 운영하는 데에는 부적합 할 수도 있다.

  1. openssl명령어를 이용하여 Web Server의 RSA키를 생성한다.

    $ openssl genrsa -des3 -out server.key 1024

    이때 생성되는 키는 Web Server를 운용하기위한 비밀키가 됨으로 반드시 백업을 받아놓고 사용하는 것이 좋다. 생성된 키는 다음 명령을 이용하여 내용을 확인할수 있다.

    $ openssl rsa -noout -text -in server.key

  2. 생성된 RSA키를 이용하여 Certificate Signing Request(CSR)을 생성한다.

    $ openssl req -new -days 365 -key server.key -out server.csr

    위의 명령어를 수행하는 도중 CommonName을 물어볼때에 Server의 FQDN(Fully Qualified Domain Name --> host.domain.com의 형태)로 적어야 한다. 생성된 화일은 다음 명령으로 내용을 확인 할 수 있다.

    $ openssl req -noout -text -in server.csr

  3. 생성된 CSR화일은 유료서비스를 하는 VeriSign이나 Thawte등의 rootCA로 보내면 server.crt화일을 받을수 있다. OpenSSL을 이용할 때에는 위에서 Self Sign할 때처럼 "openssl ca"명령을 이용한다. 이때 반드시 /path/to/openssldir/openssl.cnf의 내용중 nsCertType을 Server로 해놓아야 한다.( nsCertType = Server) (요거 빼먹으면 Netscape에서 https로 접속 할 수가 없어요.. -.-)

    $ openssl ca -in server.csr -out server.crt

    (CA.pl이나 CA.sh를 적절히 수정하였다면 "CA.xx -sign"을 이용해도 됩니다. 그리고 기존의 OpenSSL과 충돌하지 않는지 확인하시고 사용하십시요.)

  4. 생성된 server.crt와 server.key화일을 적절한 위치에 복사하고 빽업한다.

    Apache의 conf/httpd.conf에 보면, SSLCertificateFile 항목이 지시하는곳이 server.crt화일을 나타내는 곳이고 SSLCertificateKeyFile 항목이 server.key화일을 지시한다.

5. Client의 인증

인증을 받기위해서는 DN(Distinguished Name)을 포함하고 있는 인증요구서(CSR)를 생성하여 CA에 송신해야 한다. DN은 개인이나, 기관, 서버등을 구분하기위한 것으로 이름, 부서, 직장, 주소, 나라등의 필드로 이루어져 있고, CN, OU, O, L, ST, C등의 필드로 표현된다. 인증을 받기위한 Client들의 인증요구서(CSR)화일이 각각 다른형태로 생성이 되고, Client들이 인증서를 수령하는 방법이 제각기 다름으로 Client별로 각각의 사용방법을 설명한다.

Client들이 자신의 인증서를 수령할 때나, 다른사람이 사인한 코드를 실행할 때에는 rootCA의 인증서가 미리 설치되어 있어야 한다. 따라서 앞에서 생성한 rootCA의 Certificate를 미리 수신해서 설치해야 한다. Netscape와 MS Explorer는 application/x-x509-ca-cert MIME을 이용해서 서버에서 서비스하는곳에 접속하면 설치할수 있고, JAVA의 SDK인 경우에는 미리 다운로드 한다음 "keytool -import!"명령을 이용해서 설치해야 한다. 또한 다음의 Netscape나 MS Interne Explorer에서 인증요구서(Certificate Signing Request:CSR)을 생성할 때에는 개인의 정보가 Network을 이용하여 전송됨으로 반드시 https 프로토콜을 이용하도록 한다.

5.1 Netscape 사용자인증

Netscape에서는 CSR화일을 위해서 SPKAC형태의 자료를 생성한다. CSR화일을 생성하기 위해서는 Web Server에서 KEYGEN TAG를 사용한 Form을 생성하여야 한다. 다음은 KEYGEN TAG를 사용한 FORM의 예이다.


<FORM name="CSR_request" method="post" action="user_cert.cgi"> 
<table border=1>
<tr><td> 성명   </td><td><input name="CN" type=input></td>
<tr><td> E-mail </td><td><input name="Email" type=input></td>
<tr><td> 부서   </td><td><input name="OU" type=input></td>
<tr><td> 회사   </td><td><input name="O" type=input></td>
<tr><td> 시     </td><td><input name="L" type=input></td>
<tr><td> 도     </td><td><input name="ST" type=input></td>
<tr><td> 국가   </td><td><input name="C" type=input></td>
<tr><td> 키생성 </td><td><keygen name="SPKAC" type="RSA"></td>
</table>
</FORM>

KEYGEN TAG의 기본문법은 다음과 같다.

<KEYGEN NAME="name" CHALENGE="challenge string" KEYTYPE="type" PQG="pqg-params" >

NAME항목은 필수이고(cgi에서 처리하여야 함) KEYTYPE은 RSA와 DSA중에 하나를 선택할수 있다. PQG는 DSA에서만 사용한다. keygen tag는 form tag안에서만 유효하며, 특정한 길이의 key크기를 선택할 수 있다. 미국내에서는 512, 768, 1024비트의 키를 사용할 수 있고, 그외 국가에서는 512비트의 키를 사용할 수 있다. Form을 전송하면 512비트의 보안도를 가지는 Key Pair가 생성되면 비밀키는 로컬DB에 암호화 되어서 저장되고 공개키와 challenge스트링은 DER encode되고 비밀키로 sign된다음 base64로 encode되고 서버로 전송된다. 서버측에서는 DN과 SPKAC스트링을 cgi를 이용하여 화일로 만들고 다음과 같은 명령을 이용하여 Sign한다. (이때 SPKAC스트링은 1줄로 되어 있어야 한다.)

openssl ca -spkac 생성한화일 -out 인증서.crt

생성된 인증서는 application/x-x509-user-cert의 MIME형태로 Netscape Browser로 전송하여 import!할수 있도록 한다. 이때 Netscape의 로컬DB에 인증서에 해당하는 비밀키가 존재하지 않으면 import!할수 없다.

5.2 MS Internet Explorer 사용자인증

MS Internet Explorer는 PKCS#10형태의 인증요구서를 발행하며, PKCS#7형태의 인증서를 수령할수 있다. 따라서 Server측 입장에서 볼때에는 약간 귀찮은 작업을 하나더 해줘야 한다. 그리고 Explorer에서는 Netscape처럼 KEYGEN TAG를 사용하지 않고 Microsoft에서 정의한 CryptoAPI(CAPI)를 이용한다.(좀더 유연하다고 하는데...정말일까요?..^^;) CAPI는 기본적인 암호화 작업을 위한 함수를 제공한다.(키 생성, 자료의 암호화, 문서의 서명, 인증서의 요구등)

CAPI는 다음의 4단계를 이용하여 인증요구서를 발행하고 인증서를 수령한다.

  1. CAPI함수가 당신을 위한 Key Pair를 생성하고 인증서 창고에 저장한다.
  2. DN(Distinguished Name)을 생성한다.(?)
  3. CA로 전송을 하기위한 PKCS#10형태의 자료를 생성한다.
  4. CA에서 인증한 자료를 인증서 창고에 저장한다.

Explorer의 인증서는 "HKEY_CURRENT_USER/Software/Microsoft/Cryptography/"에 저장된다. CAPI함수는 OBJECT TAG를 이용하여 로컬디스크에 있는 DLL을 읽어들인후에 사용 할 수 있다. 다음은 CAPI를 위한 xenroll.dll을 읽어들이는 예이다. (예전에는 certenr3.dll이라는 화일에서 지원했었는데 지금은 사용되지 않고 있고, 사용했을경우에 OpenSSL에서 사인방법이 틀려진다.)


<OBJECT classid="clsid:43F8F289-7A20-11D0-8F06-00C04FC295E1"
           codebase="xenroll.dll"
           id=Enroll>
</OBJECT>

정상적으로 xenroll.dll이 불려졌으면 DN스트링을 만들고 xenroll의 createPKCS10함수를 불러서 PKCS#10형태의 인증 요구서를 만든다. DN스트링의 문자열의 구성과 createPKCS10함수콜은 다음과 같이 한다.

$szStr="CN=SeungSu KUK; C=KR; ST=KyungBook; L=Kyungsan; O=Catholic University of DAEGU; OU=Computer Center";

$result=Enroll.createPKCS10(szStr, "1.3.6.1.4.1.311.2.1.21");

생성된 $result에는 PKCS#10형태의 문자열이 들어 있고 이것을 CA로 전송한다. CA측에서는 이것에 사인하고 PKCS#7의 형태로 인증서를 돌려준다.

OpenSSL에서는 다음과 같은 방법을 이용하여 사인하고 인증서를 생성한다. 먼저 $result에서 들어오는 자료에는 "BEGIN CERTIFICATE REQUEST"라는 문자열이 없는 상태임으로 $result를 이용하여 다음과 같은 형태의 화일을 생성한다.

-----BEGIN CERTIFICATE REQUEST-----

$result에서 ^M을 삭제한 내용

-----END CERTIFICATE REQUEST-----

생성된 화일은 다음과 같이 사인하고 PKCS#7형태의 화일을 생성한다.

openssl ca -in 생성된화일 -out cert결과화일

openssl crl2pkcs7 -certfile cert결과화일 -in /path/to/crl.pem -out pkcs7화일

(crl.pem화일은 미리 생성되어 있어야 하는데 "openssl ca -gencrl"명령을 이용하여 생성한다.) pkcs7화일을 Explorer로 전송할 때에는 "BEGIN PKCS7"와 "END PKCS7"이라는 문자열(첫줄과 끝줄)을 지운상태로 전송해야 한다. (않그러면 에러가 발생한다.) 전송된 PKCS7화일(VBScript!나 JavaScript의 변수로 전송)은 AcceptPKCS7함수에 의해서 import!되며 다음과 같이 한다.

$szStr="전송된 PKCS7화일의 내용"

$result=Enroll.AcceptPKCS7(szStr);

5.3 JDK2 사용자인증

(여기는 1년전의 내용입니다..-.- 따라서 간단한 개념만 적어보겠습니다. 그리고 빠른시간내에 전제적인 내용을 정리하겠습니다.)

JDK2에서는 applet!이나 javascript등을 사인하기 위해서 인증서를 사용한다. 비밀키와 공개키의 생성은 keytool을 통해서 이루어지며 keytool을 통하여 import!/export기능을 수행한다. keytool을 이용한 공개키/비밀키의 생성은 다음과 같이 한다.

keytool -genkey -alias 사용자명 -keypass 해당키의비밀번호

keytool에서 "-genkey"를 이용하면 Distinguished-Name을 요구하고 시험용으로 사용하는 Self-Signed Certificate를 생성한다. 이것은 나중에 "import!"에의해 CA에서 인증한 키로 대체된다. keytool에서 사용할수 있는 옵션은 다음과 같다.

  • -certreq : CSR화일을 생성한다.
  • -delete : keystore에서 해당키를 삭제한다.
  • -export : 공개키를 추출한다.
  • -genkey : keystore entry를 생성한다.
  • -import! : CA에서 인증한 인증서를 import!한다.
  • -list : keystore의 내용을 보여준다.
  • -keypasswd: 비밀키에 암호를 설정한다.
  • -storepasswd: (요건모지?)

인증요구서를 만들기 위해서는 "-certreq"를 사용한다. (이때 genkey에서 입력한 비밀번호를 넣어야 한다.)

keytool -certreq -keystore keystore이름 -alias 사용자명 -file CSR화일명

생성된 CSR화일은 CA에서 인증하고 "-import!"를 이용해서 keystore에 저장한다.

keytool -import! -alias 사용자명 -file CERT화일명 -keystore keystore명

내용을 확인하고 싶으면 keytool -printcert -file CERT화일명이렇게 입력한다.

OpenSSL에서 J2sdk에서 요구한 인증서를 처리할 때에는 다음과 같이하여 인증서를 생성하고 E-mail등을 이용하여 돌려주면 된다.

openssl ca -in certreq화일 -out 결과cert화일

6. 기타

6.1 참고자료

  1. www.openssl.org
  2. www.modssl.org
  3. www.apache.org
  4. Frederick J. Hirsch의 cookbook (cookbook은 SSLeay에 관한내용이 많습니다만 OpenSSL이 ssleay를 기초로하기 때문에 참고가 많이 될것 같습니다. 저는 이런게 있는지도 모르고 맨땅에 해딩함서 만들었는디...정리하면서 찾아보니 좋은자료가 있네요..)

6.2 헛소리..^^

옛날에(1년전쯤..^^) 자료를 여기저기서 참고해서 만들었던 것인데... 참고 자료를 찾을려니, 어디에 있는지 잘 모르겠군요. 원고 마감할때까지 찾아놔야 할 텐데...-.-;

저도 아직 OpenSSL을 이용한 Certificate Server운용방법에는 익숙하지 않습니다. CRL(Certificate Revoke List(?))나 사용자의 CSR화일을 자동화하여 처리하는 방법론등 여러가지를 아직 제대로 하지 못하고 있습니다. 이 글을 쓰게되면서 더이상 썩히지말고 써먹어야 되겠다는 생각이 드는군요...아직 덜 된 부분들(Client등에서의 사용법)은 제가 시험해보구 정리가 되면 이문서를 버젼업(^^) 해서 다시 올리도록 하겠습니다. 본문에 틀린내용이 있거나 건의사항이 있으면 언제든지 환영합니다. 메일주시면 착실히 답은 못해드려도 받드시 수정하도록 하겠습니다.

6.3 감사의 말

업무와 관계없는 일을 하는 저를 옆에서 지켜봐주고 여러가지 시험을 해주는 박상수님께 감사하며, 볼품없는 제글을 끝까지 읽어주신 여러분께 감사드립니다..^^

AND

출처: http://www.certkorea.co.kr/doc.asp?g_ssl_client

클라이언트(Client Certificate) 인증서의 활용

인증을 받기위해서는 DN(Distinguished Name)을 포함하고 있는 인증요구서(CSR)를 생성하여 CA에 송신해야 한다. DN은 개인이나, 기관, 서버등을 구분하기위한 것으로 이름, 부서, 직장, 주소, 나라등의 필드로 이루어져 있고, CN, OU, O, L, ST, C등의 필드로 표현된다. 인증을 받기위한 Client들의 인증요구서(CSR)화일이 각각 다른형태로 생성이 되고, Client들이 인증서를 수령하는 방법이 제각기 다름으로 Client별로 각각의 사용방법을 설명한다.

Client들이 자신의 인증서를 수령할 때나, 다른사람이 사인한 코드를 실행할 때에는 rootCA의 인증서가 미리 설치되어 있어야 한다. 따라서 앞에서 생성한 rootCA의 Certificate를 미리 수신해서 설치해야 한다. Netscape와 MS Explorer는 application/x-x509-ca-cert MIME을 이용해서 서버에서 서비스하는곳에 접속하면 설치할수 있고, JAVA의 SDK인 경우에는 미리 다운로드 한다음 "keytool -import"명령을 이용해서 설치해야 한다. 또한 다음의 Netscape나 MS Interne Explorer에서 인증요구서(Certificate Signing Request:CSR)을 생성할 때에는 개인의 정보가 Network을 이용하여 전송됨으로 반드시 https 프로토콜을 이용하도록 한다.

1 Netscape 사용자인증

Netscape에서는 CSR화일을 위해서 SPKAC형태의 자료를 생성한다. CSR화일을 생성하기 위해서는 Web Server에서 KEYGEN TAG를 사용한 Form을 생성하여야 한다. 다음은 KEYGEN TAG를 사용한 FORM의 예이다.


<FORM name="CSR_request" method="post" action="user_cert.cgi"> 
<table border=1>
<tr><td> 성명   </td><td><input name="CN" type=input></td>
<tr><td> E-mail </td><td><input name="Email" type=input></td>
<tr><td> 부서   </td><td><input name="OU" type=input></td>
<tr><td> 회사   </td><td><input name="O" type=input></td>
<tr><td> 시     </td><td><input name="L" type=input></td>
<tr><td> 도     </td><td><input name="ST" type=input></td>
<tr><td> 국가   </td><td><input name="C" type=input></td>
<tr><td> 키생성 </td><td><keygen name="SPKAC" type="RSA"></td>
</table>
</FORM>

KEYGEN TAG의 기본문법은 다음과 같다.

<KEYGEN NAME="name" CHALENGE="challenge string" KEYTYPE="type" PQG="pqg-params" >

NAME항목은 필수이고(cgi에서 처리하여야 함) KEYTYPE은 RSA와 DSA중에 하나를 선택할수 있다. PQG는 DSA에서만 사용한다. keygen tag는 form tag안에서만 유효하며, 특정한 길이의 key크기를 선택할 수 있다. 미국내에서는 512, 768, 1024비트의 키를 사용할 수 있고, 그외 국가에서는 512비트의 키를 사용할 수 있다. Form을 전송하면 512비트의 보안도를 가지는 Key Pair가 생성되면 비밀키는 로컬DB에 암호화 되어서 저장되고 공개키와 challenge스트링은 DER encode되고 비밀키로 sign된다음 base64로 encode되고 서버로 전송된다. 서버측에서는 DN과 SPKAC스트링을 cgi를 이용하여 화일로 만들고 다음과 같은 명령을 이용하여 Sign한다. (이때 SPKAC스트링은 1줄로 되어 있어야 한다.)

openssl ca -spkac 생성한화일 -out 인증서.crt

생성된 인증서는 application/x-x509-user-cert의 MIME형태로 Netscape Browser로 전송하여 import할수 있도록 한다. 이때 Netscape의 로컬DB에 인증서에 해당하는 비밀키가 존재하지 않으면 import할수 없다.

2 MS Internet Explorer 사용자인증

MS Internet Explorer는 PKCS#10형태의 인증요구서를 발행하며, PKCS#7형태의 인증서를 수령할수 있다. 따라서 Server측 입장에서 볼때에는 약간 귀찮은 작업을 하나더 해줘야 한다. 그리고 Explorer에서는 Netscape처럼 KEYGEN TAG를 사용하지 않고 Microsoft에서 정의한 CryptoAPI(CAPI)를 이용한다.(좀더 유연하다고 하는데...정말일까요?..^^;) CAPI는 기본적인 암호화 작업을 위한 함수를 제공한다.(키 생성, 자료의 암호화, 문서의 서명, 인증서의 요구등)

CAPI는 다음의 4단계를 이용하여 인증요구서를 발행하고 인증서를 수령한다.

  1. CAPI함수가 당신을 위한 Key Pair를 생성하고 인증서 창고에 저장한다.
  2. DN(Distinguished Name)을 생성한다.(?)
  3. CA로 전송을 하기위한 PKCS#10형태의 자료를 생성한다.
  4. CA에서 인증한 자료를 인증서 창고에 저장한다.
Explorer의 인증서는 "HKEY_CURRENT_USER/Software/Microsoft/Cryptography/"에 저장된다. CAPI함수는 OBJECT TAG를 이용하여 로컬디스크에 있는 DLL을 읽어들인후에 사용 할 수 있다. 다음은 CAPI를 위한 xenroll.dll을 읽어들이는 예이다. (예전에는 certenr3.dll이라는 화일에서 지원했었는데 지금은 사용되지 않고 있고, 사용했을경우에 OpenSSL에서 사인방법이 틀려진다.)


<OBJECT classid="clsid:43F8F289-7A20-11D0-8F06-00C04FC295E1"
           codebase="xenroll.dll"
           id=Enroll>
</OBJECT>

정상적으로 xenroll.dll이 불려졌으면 DN스트링을 만들고 xenroll의 createPKCS10함수를 불러서 PKCS#10형태의 인증 요구서를 만든다. DN스트링의 문자열의 구성과 createPKCS10함수콜은 다음과 같이 한다.

$szStr="CN=SeungSu KUK; C=KR; ST=KyungBook; L=Kyungsan; O=Catholic University of DAEGU; OU=Computer Center";

$result=Enroll.createPKCS10(szStr, "1.3.6.1.4.1.311.2.1.21");

생성된 $result에는 PKCS#10형태의 문자열이 들어 있고 이것을 CA로 전송한다. CA측에서는 이것에 사인하고 PKCS#7의 형태로 인증서를 돌려준다.

OpenSSL에서는 다음과 같은 방법을 이용하여 사인하고 인증서를 생성한다. 먼저 $result에서 들어오는 자료에는 "BEGIN CERTIFICATE REQUEST"라는 문자열이 없는 상태임으로 $result를 이용하여 다음과 같은 형태의 화일을 생성한다.

-----BEGIN CERTIFICATE REQUEST-----

$result에서 ^M을 삭제한 내용

-----END CERTIFICATE REQUEST-----

생성된 화일은 다음과 같이 사인하고 PKCS#7형태의 화일을 생성한다.

openssl ca -in 생성된화일 -out cert결과화일

openssl crl2pkcs7 -certfile cert결과화일 -in /path/to/crl.pem -out pkcs7화일

(crl.pem화일은 미리 생성되어 있어야 하는데 "openssl ca -gencrl"명령을 이용하여 생성한다.) pkcs7화일을 Explorer로 전송할 때에는 "BEGIN PKCS7"와 "END PKCS7"이라는 문자열(첫줄과 끝줄)을 지운상태로 전송해야 한다. (않그러면 에러가 발생한다.) 전송된 PKCS7화일(VBScript나 JavaScript의 변수로 전송)은 AcceptPKCS7함수에 의해서 import되며 다음과 같이 한다.

$szStr="전송된 PKCS7화일의 내용"

$result=Enroll.AcceptPKCS7(szStr);

3 JDK2 사용자인증

(여기는 1년전의 내용입니다..-.- 따라서 간단한 개념만 적어보겠습니다. 그리고 빠른시간내에 전제적인 내용을 정리하겠습니다.)

JDK2에서는 applet이나 javascript등을 사인하기 위해서 인증서를 사용한다. 비밀키와 공개키의 생성은 keytool을 통해서 이루어지며 keytool을 통하여 import/export기능을 수행한다. keytool을 이용한 공개키/비밀키의 생성은 다음과 같이 한다.

keytool -genkey -alias 사용자명 -keypass 해당키의비밀번호

keytool에서 "-genkey"를 이용하면 Distinguished-Name을 요구하고 시험용으로 사용하는 Self-Signed Certificate를 생성한다. 이것은 나중에 "import"에의해 CA에서 인증한 키로 대체된다. keytool에서 사용할수 있는 옵션은 다음과 같다.

  • -certreq : CSR화일을 생성한다.
  • -delete : keystore에서 해당키를 삭제한다.
  • -export : 공개키를 추출한다.
  • -genkey : keystore entry를 생성한다.
  • -import : CA에서 인증한 인증서를 import한다.
  • -list : keystore의 내용을 보여준다.
  • -keypasswd: 비밀키에 암호를 설정한다.
  • -storepasswd: (요건모지?)
인증요구서를 만들기 위해서는 "-certreq"를 사용한다. (이때 genkey에서 입력한 비밀번호를 넣어야 한다.)

keytool -certreq -keystore keystore이름 -alias 사용자명 -file CSR화일명

생성된 CSR화일은 CA에서 인증하고 "-import"를 이용해서 keystore에 저장한다.

keytool -import -alias 사용자명 -file CERT화일명 -keystore keystore명

내용을 확인하고 싶으면 keytool -printcert -file CERT화일명이렇게 입력한다.

OpenSSL에서 J2sdk에서 요구한 인증서를 처리할 때에는 다음과 같이하여 인증서를 생성하고 E-mail등을 이용하여 돌려주면 된다.

openssl ca -in certreq화일 -out 결과cert화일

AND

MIS 과제 - 공개키 암호화 방식에서 기밀성, 인증, 무결성, 부인방지가 어떻게 이루어지는가를 설명하라.

공개키 암호화 방식이란??
암호화 될 때 사용하는 키와 복호화 할 때 사용하는 키를 별도로 사용하는 방식으로
상대방에게 공개하는 공개키로 암호화한 암호문은 키를 생성한 자신이 비밀로 유지하고 있는 개인키로만 해독이 가능하고, 역으로 개인키로 암호화한 암호화한 암호문은 공개키로만 해독이 가능하도록 구현하는 것이다.

-----------------------------------------------------------------------------------------------------


공개키 암호화 방식은 기밀성을 얻을 수 있다. 암호화된 내용은 지정된 사람(개인키를 가지고 있는 사람)을 제외하고는 아무도 그 내용을 알 수 없기 때문이다.

공개키 암호화 방식을 이용한 것이 바로 전자서명 시스템이다. 전자서명에서는 암호 시스템과는 반대로 서명의 생성자는 개인키로 연산을 수행하고, 서명을 확인하고 자하는 사람은 공개키로 연산을 수행한다.
그러면 서명을 생성하는 사람은 지정된 사람(개인키를 알고 있는 사람)에 의해서만 가능하고, 서명의 확인 작업은 누구나 가능하게 된다.
이는 전자서명의 특성상, 서명은 개인의 고유한 것이므로 다른 사람에 의해 같은 서명이 생성될 수 없고(개인키가 유출되지 않았다는 전제 하에), 서명의 확인은 확인을 원하는 사람이면 누구나 쉽게 공개키를 획득하여 확인해 볼 수 있게 된다. 그러므로 인증성을 얻을 수 있다. 다시 말해, 서명이 누구에 의해 생성된 것인가를 확인할 수 있는 것이다.

AND

출처: http://www.sis.pe.kr/549

PKI 는 Public Key Infrastructure 의 약자이다. PKI는 공개키 알고리듬(비대칭형 알고리듬)을 위한 키 관리 구조라고 볼 수 있다. PKI는 공개키 알고리듬에서 요구되는 공개키 인증서를 발행하고, 취소하며, 공표하기 위한 기반 구조이다. PKI에서 제공되는 보안 서비스는 비대칭형 암호 알고리듬뿐만 아니라 대칭형 알고리듬도 이용하므로 비대칭형 암호 알고리듬으로 한정되어서는 않된다. 그러면 비대칭형 암호 알고리듬은 무엇인가? 비대칭형 암호 알고리듬은 대칭형 암호 알고리듬과 대비되는 알고리듬이다. 비대칭형 알고리듬은 송신단과 수신단에서 사용하는 암호키들이 서로 다른 암호 알고리듬을 지칭한다. 따라서 PKI는 비대칭형 암호 알고리듬에 바탕을 두고 있음을 의미한다.

그 러면 기반구조(infrastructure)란 무슨 의미인가? LAN, WAN, 인터넷을 통해 연결되는 컴퓨터 환경을 생각해보자. 컴퓨터 상의 많은 응용들이 존재하며, 서로 데이터를 교환하며, 전자 거래를 수행한다. 이 모든것들이 정상적으로 수행되기 위해서는 통일된 통신 구조를 요구한다. 그렇지 않으면, 컴퓨터들간의 통신은 불가능해진다. 비슷한 이유로, 응용간의 통신이 안전하게 수행되기 위해서는 동일한 보안 구조가 존재해야 하며, 보안은 오늘날 암호를 이용하여 달성되므로 암호 구조(cryptography structure)가 요구된다. 이 암호 구조가 PKI를 라고 할 수 있다.

PKI는 엄격하게 말하여 비대칭형 알고리듬만을 이용하지 않는다. 대칭형 암호 알고리듬과 비대칭형 알고리듬이 이용되어 전체 보안 기능을 제공한다. PKI 가 제공 가능한 보안 메카니듬은 무엇인가?

PKI는 보안 서비스를 제공하기 위한 보안 메카니듬을 포함한다. PKI가 제공하는 보안 서비스는 기밀성, 인증성, 무결성, 부인방지 서비스이다.


가. 기밀성


기 밀성은 정보의 불법적인 액세스 또는 누설로부터 데이터를 보호하는 것이다. 이 서비스는 저장 매체에 대해서는 액세스 제어로 실현되고, 데이터 전송을 위해서는 암호로 제공된다. PKI가 제공할 수 있는 것은 암호 기능이다. 실제로 액세스 제어는 특정한 주체(subject)의 신원을 확인하는 인증 기능과 특정 주체의 권한을 이용하는 인가의 조합으로 실현된다.

기밀성은 불투명한 봉투라고 볼 수 있다. 안에 있는 메시지는 밖에서는 보여지질 않는다. 일반적으로 대부분의 사람들은 봉투를 열어서, 내용을 읽을 수 있다. 암호는 봉투에서 지정된 사람인 인가된 사람 이의에 아무나 열 수 없는 믿기 힘든 강력한 봉투라고 볼 수 있다.


나. 인증성


인 증은 개인의 신원을 검증하고, 데이터 원천지를 검증하는 것이다. 다른 말로, 사람은 자기와 통신하는 사람의 신원, 데이터를 송신한 사람의 신원을 증명하고 싶어한다. 우리는 항상 사람들을 검증한다. 우리는 음성으로 전화 거는 사람의 신원을 확인한다. 노크 소리는 문 밖에 누군가가 왔다는 것을 확인한다. 항공사 직원은 사진으로 신원을 확인한다. 컴퓨터와 네트워크는 패스워드를 요청한다. ATM은 ATM카드를 넣고, PIN을 넣을 것을 요구한다.

인증은 다음과 같은 세 가지 방법으로 달성된다.


- 패스워드와 PIN과 같은 당신이 알고 있는 것.

- ATM 카드, 문 열쇠 등의 당신이 가지고 있는 것.

- 지문, 음성 패턴, 그리고 홍체 등의 생체 정보와 같은 당신인 것.


다. 무결성


무 결성은 메시지에 대한 불법적인 변경이나 대치(substitution)를 방지하기 위한 것이다. 이 메키니듬은 MAC(Message Authentication Code)나 디지털 서명이라고 불리어지는 암호학적 메카니듬으로 제공된다.

무 결성을 투명한 봉투로 대비될 수 있다. 안에 메시지는 밖에서 읽을 수 있다. 그러므로 기밀성은 없다. 그러나 무결성을 위한 봉투는 이른바 간섭 증거 특성을 제공한다. 간섭 증거 봉투는 간섭이 일어났을 때 간섭이 발생했다는 것을 증거로 남기는 봉투이다. 수신자는 봉투를 살펴서 봉투가 열리지 않았고, 찢기지 않았으며, 내용이 대치되지 않았음을 확인할 수 있다.


라. 부인방지


부 인방지는 제삼자에게 증명할 수 있는 인증성 서비스와 무결성 서비스가 결합된 서비스라고 할 수 있다. 이는 메시지 송신자가 자신으로부터 메시지가 왔음을 거부할 수 없다는 것을 제공한다. 비대칭형 암호는 오직 메시지 원천자 만이 디지털 서명문을 생성할 수 있는 디지털 서명 메카니듬을 제공한다. 그러므로 디지털 서명문을 수신한 누구도 디지털서명문의 유효성을 검증할 수 있다. 이는 법원에서 메시지가 메시지의 서명자로부터 왔다는 것을 거부할 수 없게 됨을 의미한다.

디지털 봉투는 앞에서 언급한 투명한 봉투와 동일한 특성을 갖는다. 이 메시지는 볼 수 도 있고, 서명자를 인증할 수 있으며, 검증자가 메시지가 변경되지 않았고 대치되지 않았음을 증명할 수 있다.

AND