2010-03-11 3 views
14

CreateProcessAsUser()를 사용하여 스크립트 및 실행 파일을 실행하여 자동화 작업을 처리하는 Thrid Party Windows 서비스를 사용하고 있습니다. Windows Server 2008에서 UAC 및 LUA 권한 상승이 API를 통해 처리되는 방식으로 인해 문제가 발생합니다.비대화 형 서비스 (win32/.net/powershell)에서 UAC 승격 된 프로세스 시작

서비스가 LocalSystem으로 실행되며 "데스크톱과 상호 작용"을 사용할 수 없습니다. 프로세스는 Administrators 그룹의 사용자로 실행되지만 관리자 계정은 실행되지 않습니다 (이는 많은 UAC 제한에서 제외됩니다). 모든 UAC 기본 설정이 그대로 유지됩니다.

서비스에 임의의 명령이나 powershell 코드를 전달할 수는 있지만 서비스에 의해 시작되는 비 상승, 비 대화식 프로세스의 '탈주'가 불가능합니다.

상승 된 프로세스를 시작하기위한 유일한 (공개) API 옵션이 'runas'동사가 포함 된 ShellExecute()이지만 그 호출이 불가능하다는 것을 알 수있는 것 같습니다. 비 대화식 서비스이거나 "이 작업에는 대화식 창 스테이션이 필요합니다"와 같은 오류가 발생합니다.

내가 찾은 유일한 해결 방법은 여기에 언급되어 http://www.eggheadcafe.com/software/aspnet/29620442/how-to-proper-use-sendinp.aspx

비스타에서 공식이 과정을 높일 수있는 방법 에만 쉘 API에서 ShellExecute (예)를 사용하고 문서화 (하지 CreateProcess를 또는 CreateProcessAsUser). 따라서 응용 프로그램에서 ShellExecute (Ex)를 호출하여 도우미 을 시작하여 SendInput을 호출해야합니다. 은 또한, 세션 0 분리 인해 서비스 만 대화 형 데스크톱을 지정 ( 에서 ShellExecute (예)를 사용할 수 없습니다) 에 CreateProcessAsUser 또는 CreateProcessWithLogonW를 사용할 수 있습니다.

.. Windows 서비스에서 상승 된 프로세스를 생성 할 수있는 직접적인 방법이 없다고 생각합니다. 먼저 CreateProcessAsUser 또는 CreateProcessWithLogonW를 사용하여 승격되지 않은 프로세스를 사용자 세션 (대화 형 데스크톱)에 생성 할 수 있습니다. 그런 다음 승격되지 않은 프로세스 에서 ShellExecute (Ex)를 사용하여 실제 작업에 대해 상승 된 프로세스를 생성 할 수 있습니다. 내가/약간의 정교한 P를해야이없는 닷넷 System.Diagnostics.ProcessStartInfo 이후에 CreateProcessAsUser 또는 CreateProcessWithLogonW를 호출하는 물건을 호출 것 같은

는 .NET/PowerShell을 코드에서이 작업을 수행하려면, 그것은 본다 "winsta0 \ default"로 설정할 수있는 lpDesktop과 동일합니다. LocalSystem에 CreateProcessAsUser 또는 CreateProcessWithLogonW를 호출 할 권한이 있는지 여부는 확실하지 않습니다.

은 또한, 나는이 작업을 수행하는 간단한 방법이 없다 결론에 도달하고있어 모든 것을 바탕으로 http://blogs.msdn.com/alejacma/archive/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net.aspxProcess.Start with different credentials with UAC on

바라 보았다. 내가 놓친 게 있니? 이것은 정말 열심히해야하는 것처럼 보이지 않습니다. UAC는 비대화 형 사용 사례를 처리하도록 설계된 적이 없었던 것처럼 느껴집니다.

그리고 Microsoft 사람들이이 문서를 읽게되면 ShellExecute가 내부적으로 권한 상승을 처리하는 방법이 응용 프로그램 정보 서비스 (AIS)를 호출하는 것임을 알았습니다. 일부 Win32 또는 .NET API를 통해 AIS에 동일한 호출을 사용할 수없는 이유는 무엇입니까? http://msdn.microsoft.com/en-us/library/bb756945.aspx

죄송합니다. 어떤 아이디어 주셔서 감사합니다.

+0

대신 서버 코어가 UAC를 지원하지 않는다고 말합니다. 내 평가를 확인하는 것 같아. http://blogs.technet.com/server_core/archive/2009/01/19/user-account-control-uac-and-server-core.aspx –

+0

여기에 내 게시물을 참조하십시오. 특히 LinkedToken을 살펴 봅니다. 섹션 : http://brianbondy.com/blog/id/100/understanding-windows-at-a-deeper-level-sessions-window-stations-and-desktops –

답변

16

세션 제로 분리를 중단하는 "공식적인"방법은 터미널 서비스 API와 CreateProcessAsUser()의 조합을 사용하여 사용자 세션 내에서 프로세스를 시작하는 것입니다. 이전 작업에서 우리는 다운로드 한 업데이트를 설치하기 전에 서비스에서 사용자에게 대화 상자를 표시해야하므로 작업을 완료했습니다. WinXP, Win2K3, Vista 및 Win7에서 작동하지만 적어도 승리 2K8이 너무 다를 것이라고 기대하지 마십시오. 다음과 같이 기본적으로, 프로세스가 진행됩니다

  1. 전화 WTSGetActiveConsoleSessionId() 활성 콘솔 세션 ID를 얻기 위해 (매우 중요, 대화 형 세션도 클라이언트 시스템에 하지 항상 세션 1 참조). 이 API는 대화 형 세션에 로그인 한 활성 사용자가 없으면 (즉, RDP를 사용하지 않고 실제 컴퓨터에 로컬로 로그인 한 경우) -1을 반환합니다.
  2. 이전 API 호출의 세션 ID를 WTSQueryUserToken()으로 전달하면 콘솔에 로그인 한 사용자를 reprents하는 열린 토큰을 얻을 수 있습니다.
  3. DuplicateTokenEx()으로 전화하여 가장 토큰 (WTSQueryUserToken)을 기본 토큰으로 변환하십시오.
  4. 프로세스의 새 환경을 만들려면 CreateEnvironmentBlock()으로 전화하십시오 (선택 사항이지만 선택하지 않으면 프로세스에 해당되지 않습니다).
  5. 실행 파일의 명령 줄과 함께 # 3 단계의 기본 토큰을 CreateProccessAsUser()에 전달합니다. 4 단계에서 환경 블록을 만든 경우 CREATE_UNICODE_ENVIRONMENT 플래그도 전달해야합니다 (항상). 어리석은 것처럼 보일지 모르지만 API를 사용하지 않으면 API가 끔찍하게 실패합니다 (ERROR_INVALID_PARAMTER).
  6. 환경 블록을 만든 경우 DestroyEnvironmentBlock을 호출해야합니다. 그렇지 않으면 메모리 누수가 발생합니다. 프로세스가 시작될 때 환경 블록의 별도 복사본이 제공되므로 로컬 데이터 만 파괴됩니다.

그리고! Windows는 내부 마법을 수행하며 응용 프로그램을 시작합니다. 그러나 이것이 서비스에서 시작되고 대화식 프로세스가 시작될지라도 UAC를 우회 할 것인지 확신 할 수는 없습니다 (그러나 그 말은 인용하지 마십시오). 즉, 레지스트리 또는 내부 매니페스트가 그렇게하지 않는 한 승격 된 프로세스로 실행되지 않을 수도 있습니다. 그렇더라도 UAC 프롬프트가 표시 될 수 있습니다. 3 단계에서 얻은 토큰이 제한된 토큰 인 경우 AdjustTokenPrivileges()을 사용하여 상승 된 (전체) 토큰을 복원 할 수 있지만 그 중 하나를 인용하지는 않습니다. 그러나 MSDN 문서에 명시된 바와 같이 아직 가지고 있지 않은 토큰에 대한 권한을 "추가"할 수 없음을 유의하십시오 (예 : AdjustTokenPrivileges을 사용하여 제한된 사용자 토큰을 관리자로 설정할 수 없음, 기본 사용자는 함께 시작하는 관리자 여야합니다).

Win2K에서 모든 것을 기술적으로 수행 할 수 있습니다. Win2K는 WTSGetActiveConsoleSessionId()WTSQueryUserToken() API가없고 (Win2K Pro의 경우 WTSEnumerateProcesses()과 함께) WinXP로 시작하는 것이 실제로 가능합니다. 당신은 0을 세션 ID로 하드 코딩 할 수 있습니다. (Win2K에서는 항상 그렇기 때문에) 실행중인 프로세스를 열거하고 토큰 중 하나를 복제하여 사용자 토큰을 얻을 수 있다고 가정합니다. 대화 형 SID가 있음).관계없이 서비스 설정에서 "데스크탑과 상호 작용"을 선택하지 않은 경우에도 CreateProcessAsUser()은 대화 형 사용자 토큰이 전달 될 때와 동일한 방식으로 작동합니다. 프로세스가 경건한 LocalSystem 액세스 토큰을 상속하지 않으므로 어쨌든 서비스에서 직접 실행하는 것보다 안전합니다.

이제 타사 앱이 스크립트/프로세스를 실행할 때이 작업을 수행하는지는 모르겠지만 서비스에서 수행하려는 경우 (Vista 및 Win7에서는 세션 0 격리를 극복하는 유일한 방법).

+3

'DuplicateTokenEx'를 호출 할 필요가 없습니다. 'CreateProcessAsUser'는'WTSQueryUserToken'에서 얻은 토큰으로 프로세스를 실행합니다. 귀하의 답변은 매우 자세하지만 "서비스로부터 프로세스 향상 방법 (UAC 사용 가능)"이라고 대답하지 않습니다. – Ajay

+1

실제로 그렇지 않습니다. 이렇게하면 제한된 토큰이 남게됩니다. – Joshua

+0

참고 사항 : 1) @Ajay는 'WTSQueryUserToken'이 이미 기본 토큰을 반환하기 때문에 3 단계를 건너 뛸 수 있습니다. 2) UAC를 사용하면 실제로 2 단계 후에 연결된 토큰을 가져와야합니다. 이것은'TokenLinkedToken' 정보 클래스를 사용하여'GetTokenInformation'을 호출하여 수행합니다. 그러나'TokenElevationType '을 쿼리하면 고도가 제한된다고합니다. 3) 환경 블록을 만들지 않으면 새로운 프로세스는 생성 프로세스의 환경을 갖게됩니다. 이것은 여러분의 서비스입니다 –

1

사용 사례에 따라, 내가 할 수있는 일을 할 수 있습니다. 나는 활성 세션에 대한 winlogon 프로세스를 추적하여 토큰을 훔칩니다. 활성 세션이 없으면 (API는 -1을 리턴 함) WINVER> = 6 인 경우 1을, 그렇지 않은 경우 0을 사용하십시오.이 경우 활성 세션에서 SYSTEM이됩니다.

관련 문제