{"id":17884,"date":"2008-09-30T13:03:56","date_gmt":"2008-09-30T21:03:56","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/powershell\/?p=17884"},"modified":"2019-06-07T13:05:11","modified_gmt":"2019-06-07T21:05:11","slug":"powershells-security-guiding-principles","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/powershells-security-guiding-principles\/","title":{"rendered":"PowerShell\u2019s Security Guiding Principles"},"content":{"rendered":"<p>One of most common issues we face with PowerShell comes from users or ISVs misunderstanding PowerShell\u2019s security guiding principles. At a high-level, it seems to all make sense \u2013 execution policies help ensure that you only run scripts that you trust on your system. These protections are driven by PowerShell\u2019s <a href=\"http:\/\/www.leeholmes.com\/blog\/DemonstrationOfMonadsSecurityFeatures.aspx\">three main security features<\/a>. For people that will never use PowerShell, that trust decision is made for you by way of PowerShell\u2019s default \u201cRestricted\u201d execution policy. Others may want to use a verifiable identity chain as their important guiding factor, in which case the Authenticode signing certificates (and associated identity) enforced by the \u201cAllSigned\u201d mode is ideal. Advanced scripters are typically very selective in the source of their scripts (and either deeply trust the source, or have reviewed the script itself) and select a RemoteSigned or Unrestricted execution policy.<\/p>\n<p>These features are the core defenses in PowerShell\u2019s security threat model.<\/p>\n<p>The threat model of an application identifies:<\/p>\n<ul>\n<li>What you are trying to protect. In PowerShell\u2019s case, this is almost entirely &quot;code execution.\u201d <\/li>\n<li>Sources of data, and how that data flows. In PowerShell\u2019s case, these are scripts sent to you through email, scripts downloaded from the internet, your profile, user input, and other similar sources. From there, this data flows through many PowerShell features \u2013 the parser, cmdlet invocation, formatting and output, etc. <\/li>\n<li>Boundaries between untrusted data and trusted data.      \n<ul>\n<li>PowerShell doesn\u2019t trust scripts that you download from the internet. <\/li>\n<li>PowerShell doesn\u2019t trust a random script or executable lying in the current location of your hard drive. <\/li>\n<li>PowerShell does trust user input. <\/li>\n<li>PowerShell does trust the administrator of the machine. <\/li>\n<li>PowerShell does trust a running script. <\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Security features come into play any time information crosses a trust boundary. PowerShell doesn\u2019t trust scripts that you\u2019ve downloaded from the internet, so the Execution Policy gives you a way to usher the script across that trust boundary. Once you trust it, PowerShell trusts it, and runs it faithfully.<\/p>\n<blockquote>\n<p><em>Example: A malicious script uses the .NET Reflection APIs to modify internal engine data structures. It creates the ability to send all of your output to a secret server somewhere in the bowels of the internet. Is this a security bug?<\/em><\/p>\n<p><em>Answer: No. PowerShell didn\u2019t trust the script when you got it, but your choice of execution policy declared it as safe. That means it is now trusted and should operate with full functionality. After all, what kind of programming language would PowerShell be without support for <\/em><a href=\"http:\/\/www.leeholmes.com\/blog\/ScriptingNetworkTCPConnectionsInPowerShell.aspx\"><em>TCP scripting<\/em><\/a><em>?<\/em><\/p>\n<\/blockquote>\n<p>PowerShell trusts user input, and runs it as-is. PowerShell\u2019s formatting and output system trusts the objects that arrive to it, and format them however is requested.<\/p>\n<p>Now, this is where things tend to get confused. People easily understand the power of an execution policy to prevent scripts from running, but often forget to consider <em>from whom<\/em>. They might think of enforcing an \u201cAllSigned\u201d policy as a way to prevent the <u>user<\/u> from running non-approved applications, when it is designed as a way to prevent the <u>attacker<\/u> from running scripts that the <u>user<\/u> doesn\u2019t approve. This misconception is often wrongly reinforced by the location of V1\u2019s ExecutionPolicy configuration key \u2013 in a registry location that only machine administrators have access to. <\/p>\n<p>System-wide PowerShell Execution Policies have never been a way to prevent the <u>user<\/u> from doing something they want to do. That job is left to the Windows Account Model, which is a <a href=\"http:\/\/blogs.technet.com\/markrussinovich\/archive\/2007\/02\/12\/638372.aspx\">security boundary<\/a>. It controls what a user can do: what files they can access, what registry keys they can access, etc. PowerShell is a user-mode application, and is therefore (by the Windows security model) completely under the user\u2019s control.<\/p>\n<p>Execution Policies are user feature. Like seatbelts. It\u2019s best to keep them on, but you always have the option to take them off. PowerShell\u2019s installer sets the execution policy to \u201cRestricted\u201d as a safe default for the vast majority of users that will never run a PowerShell script in their life. A system administrator might set the execution policy to AllSigned because they want to define it as a best practice, or let non-technical users run a subset of safe scripts. At any time, the user can decide otherwise:<\/p>\n<ul>\n<li>Type the commands by hand <\/li>\n<li>Paste the script into their PowerShell prompt <\/li>\n<li>Call Invoke-Expression (Get-Content &lt;script&gt;) <\/li>\n<li>Call PowerShell \u2013Command (Get-Content &lt;script&gt;) <\/li>\n<li>Use our PowerShell hosting APIs to host PowerShell with a different Authorization Manager <\/li>\n<li>Write their own minishell that has a \u201cSay Yes To Everything\u201d Authorization Manager <\/li>\n<li>Launch PowerShell in a debugger, and skip the statements that verify the Execution Policy <\/li>\n<li>Type PowerShell commands that use private reflection to switch the Authorization Manager <\/li>\n<li>Decompile System.Management.Automation, hack out the Authorization Manager code, and recompile it <\/li>\n<li>Use a resource editing tool to modify the LUA manifest, and let Vista do <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/aa965884.aspx\">registry virtualization into HKCU<\/a> <\/li>\n<li>Launch PowerShell in a 3<sup>rd<\/sup>-party registry or application virtualization program such as <a href=\"https:\/\/www.microsoft.com\/systemcenter\/softgrid\/default.mspx\">SoftGrid<\/a> or&#160; <a href=\"http:\/\/www.thinstall.com\/products\/virtualization_suite.php\">ThInstall<\/a> <\/li>\n<li>Use the Application Compatibility toolkit to write your own <a href=\"http:\/\/blogs.msdn.com\/cjacks\/archive\/2007\/07\/05\/windows-vista-shim-internals-basics-how-shims-work-to-address-compatibility-issues-and-what-are-the-ramifications.aspx\">shim<\/a> <\/li>\n<li>Inject API hooks into PowerShell.exe (<a href=\"http:\/\/www.internals.com\/articles\/apispy\/apispy.htm\">Overview<\/a>, <a href=\"http:\/\/jacquelin.potier.free.fr\/winapioverride32\/\">Tool<\/a>, <a href=\"http:\/\/www.hook-api.com\/\">SDK<\/a>) <\/li>\n<li>(etc) <\/li>\n<\/ul>\n<p>These are all direct results of Windows\u2019 core security tenet: you have complete control over any process you are running.<\/p>\n<p>PowerShell V2 makes this reality much more transparent through a concept called \u201cExecution Policy Scopes.\u201d In V1, the scopes are as follows. Items on top, if defined, override items below them:<\/p>\n<ol>\n<li>Machine-Wide Group Policy <\/li>\n<li>Current-User Group Policy <\/li>\n<li>Machine-Wide ExecutionPolicy (stored in HKLM) <\/li>\n<\/ol>\n<p>In V2, the scopes are as follows, with \u201cProcess\u201c, \u201dCurrentUser\u201d, and \u201cLocalMachine\u201d now surfaced as the \u2013Scope parameter to Set-ExecutionPolicy<\/p>\n<ol>\n<li>Machine-Wide Group Policy <\/li>\n<li>Current-User Group Policy <\/li>\n<li>ExecutionPolicy parameter to PowerShell.exe <\/li>\n<li>PSExecutionContext environment variable <\/li>\n<li>Current-User ExecutionPolicy (stored in HKCU) <\/li>\n<li>Machine-Wide ExecutionPolicy (stored in HKLM) <\/li>\n<\/ol>\n<p>At its core, this refinement lets administrators and users tailor their safety harness. Jane might be fluent and technical (and opt for a RemoteSigned execution policy,) while Bob (another user of the same machine with different security preferences) can still get the benefits of an AllSigned default execution policy. In addition, agents or automation tools can invoke PowerShell commands without having to modify the permanent state of the system.<\/p>\n<p>A similar misunderstanding is that PowerShell\u2019s authorization policies somehow protect you from malware <a href=\"http:\/\/blog.sapien.com\/index.php\/2008\/09\/16\/powershell-hurdles\/\">already running on your machine<\/a>. Another core Windows security tenet is that any program you run has the same capabilities as you do.&#160; This includes Vista\u2019s UAC. <a href=\"http:\/\/windowsvistablog.com\/blogs\/windowsvista\/archive\/2007\/01\/23\/security-features-vs-convenience.aspx\">It is not a security boundary<\/a>.<\/p>\n<p>Now, why is<\/p>\n<blockquote>\n<p>PowerShell.exe \u2013ExecutionPolicy Bypass \u2013File c:\\temp\\bad-script.ps1<\/p>\n<\/blockquote>\n<p>not a security bug? Ultimately, if bad code has the ability to run this code, it already has control of the machine.<\/p>\n<p>&#8212;    <br \/>Lee Holmes [MSFT]     <br \/>Windows PowerShell Development     <br \/>Microsoft Corporation     <br \/>This posting is provided \u201cAS IS\u201d with no warranties, and confers no rights.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of most common issues we face with PowerShell comes from users or ISVs misunderstanding PowerShell\u2019s security guiding principles. At a high-level, it seems to all make sense \u2013 execution policies help ensure that you only run scripts that you trust on your system. These protections are driven by PowerShell\u2019s three main security features. For [&hellip;]<\/p>\n","protected":false},"author":600,"featured_media":13641,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-17884","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell"],"acf":[],"blog_post_summary":"<p>One of most common issues we face with PowerShell comes from users or ISVs misunderstanding PowerShell\u2019s security guiding principles. At a high-level, it seems to all make sense \u2013 execution policies help ensure that you only run scripts that you trust on your system. These protections are driven by PowerShell\u2019s three main security features. For [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/17884","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/users\/600"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/comments?post=17884"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/17884\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media\/13641"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media?parent=17884"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=17884"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=17884"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}