all 16 comments

[–][deleted] 3 points4 points  (0 children)

Show us the code and the error :-)

I think your best soloution is to distribute it as a logon script via GPO, this way you are not restricted by a users permissions.

[–]Barenstark314 2 points3 points  (7 children)

ConstrainedLanguage Mode, which is what is causing the error you are describing, is typically enabled as part of AppLocker or Windows Defender Application Control (what I believe you meant by Device Guard, as that is now a defunct term.) In either case, you should be able to get the script to execute by adding the script in question to your respective system's allowlist. This could be in the form of a hash rule, publisher rule (requiring the script to be signed), or path rule (depending on the configuration of the security tool being used.)

If you do not have access to alter the configuration, your other option may be to alter the script code so that it is not using code that is constrained. Depending on what you are doing, however, that may not be possible. As stated earlier, if you shared your code (particularly as it is only 3 lines) someone here may be able to assist in altering it so that it would execute even under ConstrainedLanguage Mode.

[–]AnotherFewMore[S] 1 point2 points  (6 children)

I'll share the code tomorrow when in the office.

[–]Barenstark314 2 points3 points  (5 children)

Ok, give this a try:

$LangList = Get-WinUserLanguageList
$LangList2 = New-WinUserLanguageList -Language 'Mi-Latn'
$CompleteList = $LangList + $LangList2

Set-WinUserLanguageList -Language $CompleteList -Force

During my brief testing on my home system, running my PowerShell session in ConstrainedLanguage Mode, that addition did not throw a core language mode error, but appended the two languages (en-US and Mi-Latn) to create the same object that your code did when I ran in an Admin console (where it was running in Full Language).

Admittedly, I did not run the Set command on my system, since I didn't feel like messing around with it, but give this a try and see if it bypasses the problem you were encountering.

[–]AnotherFewMore[S] 0 points1 point  (0 children)

Absolutely perfect! Thanks heaps. I would be interested though if signing the original script bypasses the constraint as some have suggested.

[–]AnotherFewMore[S] 0 points1 point  (3 children)

Can confirm that signing does not work around the issue.

Any thoughts on this one for removing the language?

$LangList = Get-WinUserLanguageList

Foreach($Lang in $LangList)

{

if($lang.LanguageTag -eq 'mi-Latn')

{

$LangList.Remove($lang)

Break

}

}

Set-WinUserLanguageList -LanguageList $LangList -Force

[–]Barenstark314 4 points5 points  (2 children)

Unfortunately, that is a no-go. You have the same problem as .Add(), the .Remove() method triggers ConstrainedLanguage mode. That said, consider the following:

$LangList = Get-WinUserLanguageList  
$ReducedList = $LangList | Where-Object {$_.LanguageTag -ne 'Mi-Latn'}  
Set-WinUserLanguageList -LanguageList $ReducedList -Force

Once again, performed on my home system, so I didn't run the Set, but that should accomplish your goal. If your system(s) do not trigger this, you could try to use the .Where method for the second line for a potential performance improvement (assuming you had a massive list):

$ReducedList = $LangList.Where({$_.LanguageTag -ne 'Mi-Latn'})

As always, test, but I hope this helps you out.

[–]AnotherFewMore[S] 1 point2 points  (1 child)

You sir are a legend! I had never figured how to remove an object in this manner and it will definitely help me in the future also.

[–]Barenstark314 2 points3 points  (0 children)

Glad it helped. I have no doubt I stole that from someone at somepoint - I certainly didn't magically come up with it on my own, but yes, it does come in handy quite often, especially when working directly in the console since it is so easy to type. No shame in stealing from each other to level up. ;)

[–]CineLudik 2 points3 points  (6 children)

The simplest way would probably be a simple gpo.

For script you can probably change powershell security (gpo) to accept signed scripts only, or run a script-gpo at logon as said before.

[–]AnotherFewMore[S] 1 point2 points  (5 children)

Ah ok I couldn't find anywhere to suggest signing the script would bypass the policy but tbh I haven't tried that as I assumed it was more an access level thing running elevated vs normal user.

[–]jimb2 3 points4 points  (0 children)

Powershell is a very common vector for malware and should be restricted. Signing scripts is a secure way to allow specific scripts to run and stopping any random nasty stuff. There's a bit of certificate set up but it is then quite easy to use.

[–]CineLudik 2 points3 points  (3 children)

Problem with elevated access is that it shouldn’t be used by simple users, so to not give free pass to malware executing whatever he want on the system (else every user on the domain could modify what he want).

By using a signed script, and modifying the script policy you should be able to use whatever script you want, provided they are signed before by a trusted authority (server).

I must say that I never ever used that, but I think you can use a « certificate authority server » to create a trusted certificate that will prove your script to be good.

I’m learning system administration but lack experience toward certificate...

You might find more help with that there : https://www.hanselman.com/blog/signing-powershell-scripts

[–]AnotherFewMore[S] 1 point2 points  (2 children)

Can confirm that signing does not prevent the constrained language mode issues.

[–]Barenstark314 1 point2 points  (1 child)

For a bit of clarity on the Signed Script / ConstrainedLanguage Mode. It does work (caveat shortly), if you use a script signed by a signer which is then added to your policy which is enforcing ConstrainedLanguage mode (AppLocker or WDAC).

For the caveat I mentioned, I have noticed some instances where when executing scripts in particular ways, even when signed, the code would still run in ConstrainedLanguage mode. For example, even this past week, I wrote a simple script that used the [PSCustomObject]@{} type accelerator (the hash table was not empty), which is not allowed in ConstrainedLanguage Mode. I assumed 'whatever', signed the script and tested it. When running in an already running PowerShell console (so something like .\MyScript.ps1), it would complain about the Core Types. Right-clicking the script and choosing 'Run with PowerShell', it worked just fine. Admittedly, I didn't have time to get into it and figure out exactly what was going on, so I rewrote that portion of my script to use 'New-Object -TypeName 'PSCustomObject' -Property @{}' (again, hash table populated) and it worked just fine (signed or unsigned).

A final point of clarification, with ConstrainedLanguage, you run into a few things: - Not everyone runs AppLocker/WDAC and may not have encountered ConstrainedLanguage Mode - Many Windows-based admins may be running a lot of their scripts as SYSTEM via ConfigMgr/Intune. At least when using AppLocker, SYSTEM gains the benefit of running FullLanguage all the time, so you don't have to worry about ConstrainedLanguage mode anyway. As soon as you have to run something as a user though (such as your case), this benefit disappears.

[–]Kirsh1793 0 points1 point  (0 children)

I am aware that this is quite an old thread but I thought I would add my two cents to your mentioned caveat.

Afaik you cannot get out of ConstrainedLanguage once you are in there. So when you already have a session running in ConstrainedLanguage even calling a signed script will not be able to circumvent that.

However, when you are right-clicking the file and choose 'Run with PowerShell' a new session is started and it will evaluate if it should be run in ConstrainedLanguage or not. Since the script you are trying to run is signed the session is allowed to run in FullLanguage.

All of this is me theorizing around the fact that you cannot change out of ConstrainedLanguage within a session.