diff --git a/powershell/ql/src/experimental/ConvertToSecureStringAsPlainText.qhelp b/powershell/ql/src/experimental/ConvertToSecureStringAsPlainText.qhelp new file mode 100644 index 000000000000..97aba07bf4c2 --- /dev/null +++ b/powershell/ql/src/experimental/ConvertToSecureStringAsPlainText.qhelp @@ -0,0 +1,22 @@ + + + +

The use of the AsPlainText parameter with the ConvertTo-SecureString command can expose secure information.

+ +
+ +

+If you do need an ability to retrieve the password from somewhere without prompting the user, consider using the SecretStore module from the PowerShell Gallery. +

+
+ + +
  • +PSScriptAnalyzer: +AvoidUsingConvertToSecureStringWithPlainText. +
  • + +
    +
    diff --git a/powershell/ql/src/experimental/ConvertToSecureStringAsPlainText.ql b/powershell/ql/src/experimental/ConvertToSecureStringAsPlainText.ql new file mode 100644 index 000000000000..f01abb69a8ba --- /dev/null +++ b/powershell/ql/src/experimental/ConvertToSecureStringAsPlainText.ql @@ -0,0 +1,19 @@ +/** + * @name Use of the AsPlainText parameter in ConvertTo-SecureString + * @description Do not use the AsPlainText parameter in ConvertTo-SecureString + * @kind problem + * @problem.severity error + * @security-severity 7.0 + * @precision high + * @id powershell/microsoft/public/convert-to-securestring-as-plaintext + * @tags correctness + * security + */ + + import powershell + + from CmdCall c + where + c.getName() = "ConvertTo-SecureString" and + c.hasNamedArgument("asplaintext") + select c, "Use of AsPlainText parameter in ConvertTo-SecureString call" \ No newline at end of file diff --git a/powershell/ql/src/experimental/HardcodedComputerName.qhelp b/powershell/ql/src/experimental/HardcodedComputerName.qhelp new file mode 100644 index 000000000000..86432d1f5127 --- /dev/null +++ b/powershell/ql/src/experimental/HardcodedComputerName.qhelp @@ -0,0 +1,25 @@ + + + +

    The names of computers should never be hard coded as this will expose sensitive information. The ComputerName parameter should never have a hard coded value. +

    + +
    + + +

    Remove hardcoded computer names.

    + +
    + + +
  • +PSScriptAnalyzer: +AvoidUsingComputerNameHardcoded. +
  • + + +
    +
    diff --git a/powershell/ql/src/experimental/HardcodedComputerName.ql b/powershell/ql/src/experimental/HardcodedComputerName.ql new file mode 100644 index 000000000000..860205acb93f --- /dev/null +++ b/powershell/ql/src/experimental/HardcodedComputerName.ql @@ -0,0 +1,17 @@ +/** + * @name Hardcoded Computer Name + * @description Do not hardcode computer names + * @kind problem + * @problem.severity error + * @security-severity 7.0 + * @precision high + * @id powershell/microsoft/public/hardcoded-computer-name + * @tags correctness + * security + */ + +import powershell + +from Argument a +where a.getName() = "computername" and exists(a.getValue()) +select a, "ComputerName argument is hardcoded to" + a.getValue() diff --git a/powershell/ql/src/experimental/UseOfReservedCmdletChar.qhelp b/powershell/ql/src/experimental/UseOfReservedCmdletChar.qhelp new file mode 100644 index 000000000000..86cabe758176 --- /dev/null +++ b/powershell/ql/src/experimental/UseOfReservedCmdletChar.qhelp @@ -0,0 +1,26 @@ + + + +

    +You cannot use following reserved characters in a function or cmdlet name as these can cause parsing or runtime errors. + +Reserved Characters include: #,(){}[]&/\\$^;:\"'<>|?@`*%+=~ +

    + +
    + + +

    Remove reserved characters from names.

    + +
    + + +
  • +PSScriptAnalyzer: +ReservedCmdletChar. +
  • + +
    +
    diff --git a/powershell/ql/src/experimental/UseOfReservedCmdletChar.ql b/powershell/ql/src/experimental/UseOfReservedCmdletChar.ql new file mode 100644 index 000000000000..7d610f5cdf47 --- /dev/null +++ b/powershell/ql/src/experimental/UseOfReservedCmdletChar.ql @@ -0,0 +1,30 @@ +/** + * @name Reserved Characters in Function Name + * @description Do not use reserved characters in function names + * @kind problem + * @problem.severity error + * @security-severity 7.0 + * @precision high + * @id powershell/microsoft/public/reserved-characters-in-function-name + * @tags correctness + * security + */ + + import powershell + +class ReservedCharacter extends string { + ReservedCharacter() { + this = [ + "!", "@", "#", "$", + "&", "*", "(", ")", + "+", "=", "{", "^", + "}", "[", "]", "|", + ";", ":", "'", "\"", + "<", ">", ",", "?", + "/", "~"] + } +} + +from Function f, ReservedCharacter r +where f.getName().matches("%"+ r + "%") +select f, "Function name contains a reserved character: " + r \ No newline at end of file diff --git a/powershell/ql/src/experimental/UsernameOrPasswordParameter.qhelp b/powershell/ql/src/experimental/UsernameOrPasswordParameter.qhelp new file mode 100644 index 000000000000..56d36dfbe9c3 --- /dev/null +++ b/powershell/ql/src/experimental/UsernameOrPasswordParameter.qhelp @@ -0,0 +1,24 @@ + + + +

    To standardize command parameters, credentials should be accepted as objects of type PSCredential. Functions should not make use of username or password parameters. +

    + +
    + + +

    Change the parameter to type PSCredential.

    + +
    + + + +
  • +PSScriptAnalyzer: +AvoidUsingUsernameAndPasswordParams. +
  • + +
    +
    diff --git a/powershell/ql/src/experimental/UsernameOrPasswordParameter.ql b/powershell/ql/src/experimental/UsernameOrPasswordParameter.ql new file mode 100644 index 000000000000..d86b74a24624 --- /dev/null +++ b/powershell/ql/src/experimental/UsernameOrPasswordParameter.ql @@ -0,0 +1,17 @@ +/** + * @name Use of Username or Password parameter + * @description Do not use username or password parameters + * @kind problem + * @problem.severity error + * @security-severity 7.0 + * @precision high + * @id powershell/microsoft/public/username-or-password-parameter + * @tags correctness + * security + */ + + import powershell + +from Parameter p +where p.getName().toLowerCase() = ["username", "password"] +select p, "Do not use username or password parameters." diff --git a/powershell/ql/test/query-tests/security/ConvertToSecureStringAsPlainText/ConvertToSecureStringAsPlainText.expected b/powershell/ql/test/query-tests/security/ConvertToSecureStringAsPlainText/ConvertToSecureStringAsPlainText.expected new file mode 100644 index 000000000000..b4c57fada788 --- /dev/null +++ b/powershell/ql/test/query-tests/security/ConvertToSecureStringAsPlainText/ConvertToSecureStringAsPlainText.expected @@ -0,0 +1 @@ +| test.ps1:2:19:2:79 | Call to ConvertTo-SecureString | Use of AsPlainText parameter in ConvertTo-SecureString call | diff --git a/powershell/ql/test/query-tests/security/ConvertToSecureStringAsPlainText/ConvertToSecureStringAsPlainText.qlref b/powershell/ql/test/query-tests/security/ConvertToSecureStringAsPlainText/ConvertToSecureStringAsPlainText.qlref new file mode 100644 index 000000000000..1b720d5d77b1 --- /dev/null +++ b/powershell/ql/test/query-tests/security/ConvertToSecureStringAsPlainText/ConvertToSecureStringAsPlainText.qlref @@ -0,0 +1 @@ +experimental/ConvertToSecureStringAsPlainText.ql \ No newline at end of file diff --git a/powershell/ql/test/query-tests/security/ConvertToSecureStringAsPlainText/test.ps1 b/powershell/ql/test/query-tests/security/ConvertToSecureStringAsPlainText/test.ps1 new file mode 100644 index 000000000000..dfc4c457dd48 --- /dev/null +++ b/powershell/ql/test/query-tests/security/ConvertToSecureStringAsPlainText/test.ps1 @@ -0,0 +1,4 @@ +$UserInput = Read-Host 'Please enter your secure code' +$EncryptedInput = ConvertTo-SecureString -String $UserInput -AsPlainText -Force + +$SecureUserInput = Read-Host 'Please enter your secure code' -AsSecureString \ No newline at end of file diff --git a/powershell/ql/test/query-tests/security/HardcodedComputerName/HardcodedComputerName.expected b/powershell/ql/test/query-tests/security/HardcodedComputerName/HardcodedComputerName.expected new file mode 100644 index 000000000000..8cf0efb0ee43 --- /dev/null +++ b/powershell/ql/test/query-tests/security/HardcodedComputerName/HardcodedComputerName.expected @@ -0,0 +1,2 @@ +| test.ps1:3:44:3:65 | hardcoderemotehostname | ComputerName argument is hardcoded tohardcoderemotehostname | +| test.ps1:13:44:13:64 | hardcodelocalhostname | ComputerName argument is hardcoded tohardcodelocalhostname | diff --git a/powershell/ql/test/query-tests/security/HardcodedComputerName/HardcodedComputerName.qlref b/powershell/ql/test/query-tests/security/HardcodedComputerName/HardcodedComputerName.qlref new file mode 100644 index 000000000000..8e4160a9463d --- /dev/null +++ b/powershell/ql/test/query-tests/security/HardcodedComputerName/HardcodedComputerName.qlref @@ -0,0 +1 @@ +experimental/HardcodedComputerName.ql \ No newline at end of file diff --git a/powershell/ql/test/query-tests/security/HardcodedComputerName/test.ps1 b/powershell/ql/test/query-tests/security/HardcodedComputerName/test.ps1 new file mode 100644 index 000000000000..8a31f46d0f4e --- /dev/null +++ b/powershell/ql/test/query-tests/security/HardcodedComputerName/test.ps1 @@ -0,0 +1,19 @@ +Function Invoke-MyRemoteCommand () +{ + Invoke-Command -Port 343 -ComputerName hardcoderemotehostname +} + +Function Invoke-MyCommand ($ComputerName) +{ + Invoke-Command -Port 343 -ComputerName $ComputerName +} + +Function Invoke-MyLocalCommand () +{ + Invoke-Command -Port 343 -ComputerName hardcodelocalhostname +} + +Function Invoke-MyLocalCommand () +{ + Invoke-Command -Port 343 -ComputerName $env:COMPUTERNAME +} \ No newline at end of file diff --git a/powershell/ql/test/query-tests/security/UseOfReservedCmdletChar/UseOfReservedCmdletChar.expected b/powershell/ql/test/query-tests/security/UseOfReservedCmdletChar/UseOfReservedCmdletChar.expected new file mode 100644 index 000000000000..a78da0144e44 --- /dev/null +++ b/powershell/ql/test/query-tests/security/UseOfReservedCmdletChar/UseOfReservedCmdletChar.expected @@ -0,0 +1,2 @@ +| test.ps1:1:1:2:5 | MyFunction[1] | Function name contains a reserved character: [ | +| test.ps1:1:1:2:5 | MyFunction[1] | Function name contains a reserved character: ] | diff --git a/powershell/ql/test/query-tests/security/UseOfReservedCmdletChar/UseOfReservedCmdletChar.qlref b/powershell/ql/test/query-tests/security/UseOfReservedCmdletChar/UseOfReservedCmdletChar.qlref new file mode 100644 index 000000000000..70451a74a560 --- /dev/null +++ b/powershell/ql/test/query-tests/security/UseOfReservedCmdletChar/UseOfReservedCmdletChar.qlref @@ -0,0 +1 @@ +experimental/UseOfReservedCmdletChar.ql \ No newline at end of file diff --git a/powershell/ql/test/query-tests/security/UseOfReservedCmdletChar/test.ps1 b/powershell/ql/test/query-tests/security/UseOfReservedCmdletChar/test.ps1 new file mode 100644 index 000000000000..79eefefc67e3 --- /dev/null +++ b/powershell/ql/test/query-tests/security/UseOfReservedCmdletChar/test.ps1 @@ -0,0 +1,2 @@ +function MyFunction[1] +{...} \ No newline at end of file diff --git a/powershell/ql/test/query-tests/security/UsernameOrPasswordParameter/UsernameOrPasswordParameter.expected b/powershell/ql/test/query-tests/security/UsernameOrPasswordParameter/UsernameOrPasswordParameter.expected new file mode 100644 index 000000000000..4f7b31c151d2 --- /dev/null +++ b/powershell/ql/test/query-tests/security/UsernameOrPasswordParameter/UsernameOrPasswordParameter.expected @@ -0,0 +1,2 @@ +| test.ps1:6:9:7:17 | Username | Do not use username or password parameters. | +| test.ps1:8:9:9:17 | Password | Do not use username or password parameters. | diff --git a/powershell/ql/test/query-tests/security/UsernameOrPasswordParameter/UsernameOrPasswordParameter.qlref b/powershell/ql/test/query-tests/security/UsernameOrPasswordParameter/UsernameOrPasswordParameter.qlref new file mode 100644 index 000000000000..8207783cd526 --- /dev/null +++ b/powershell/ql/test/query-tests/security/UsernameOrPasswordParameter/UsernameOrPasswordParameter.qlref @@ -0,0 +1 @@ +experimental/UsernameOrPasswordParameter.ql \ No newline at end of file diff --git a/powershell/ql/test/query-tests/security/UsernameOrPasswordParameter/test.ps1 b/powershell/ql/test/query-tests/security/UsernameOrPasswordParameter/test.ps1 new file mode 100644 index 000000000000..bf313dd416e9 --- /dev/null +++ b/powershell/ql/test/query-tests/security/UsernameOrPasswordParameter/test.ps1 @@ -0,0 +1,11 @@ +function Test-Script +{ + [CmdletBinding()] + Param + ( + [String] + $Username, + [SecureString] + $Password + ) +} \ No newline at end of file