Skip to content

Security: PoshWeb/OP

Security

security.md

OP Security

Many packages are zip files in a trenchcoat, and files can be dangerous.

OP lets you work with all sorts of packages. This can be helpful, and can be dangerous.

Lets think of things we can do with a package in terms of levels of risk:

Low Risk

Reading Packages

It is generally safe to read files.

OP helps you with this: you can make anything into a package, and see what's inside.

OP provides an Open Platform for reading files and many ways to see what is inside and check the contents.

It also provides ways to inspect any code inside of the package (see mitigations):

Showing Packages

Because Open Packages have both file data and content types, we can easily serve them up and show them in a browser.

IF the server does does now allow any other verb than -Get, and is run locally, this is fairly safe.

It is more safe if not running as root or admin, and only interacting with well-known content types.

Medium Risk

Editing Packages

Things start to get tricky when you can change a package.

We want to enable package editing, but do so as safely as we can.

OP can let you change packages with simple local PUT/POST/DELETE operations.

But only if you -Allow it. If we are running a local web server, we might -Allow it.

If we were running a remote web server with this flag on, we might be very foolish.

To start a local server that can edit a package, we can run:

$package | 
    Start-OpenPackage -Allow GET, HEAD, POST, PUT, DELETE

High Risk

Invoking Packages

Packages can contain code, and code can be run.

As Open Packages can be an Open Platform for applications, we can invoke from packages.

We would be very foolish if we did this with packages we do not trust.

Mitigations

In order to mitigate risks, Open Package provides several mitigations.

Package Metadata

Open Packages contain metadata that most archives lack.

Each Open Package has a .PackageProperties collection.

This collection contains some useful information, such as the Identifier and Version.

Package Content Hashes

It is trivial to get all of the hashes of files within a package.

If these hashes deviate, the package has been changed.

For example, if we wanted all of the hashes of a PowerShell gallery module, we can use:

$turtlePackage = Get-OpenPackage https://powershellgallery.com/Packages/Turtle
$turtlePackage.FileHash

Package Data Inspection

In addition to reading hashes, we can also read any file within the package.

This allows us to scan packages.

Select-OpenPackage can be quite handy.

It allows us to select parts of a package by name, and allows us to search within package parts using:

  • Regular Expressions
  • XPath
  • PowerShell AST Conditions

Additionally, each package has several properties to assist inspection.

For example, .package.json will return any package.json files in the package.

To assist in inspecting PowerShell packages, we can also look for specific Abstract Syntax Tree types:

  • .GetPowerShellCommandAst gets all commands referenced in a package
  • .GetPowerShellParameterAst gets all parameters referenced in a package
  • .GetPowerShellTypeAst gets all types referenced in a package

To see every property an OpenPackage provides, use Get-Member:

$openPackage = Import-Module OP -PassThru | OP  
$openPackage | Get-Member

Locking Packages

In order to prevent package alteration, we can Lock-OpenPackage to get a read-only version of the package.

This will prevent alteration of the package, even if we choose the -Allow other http verbs in Start-OpenPackage

Eventing

In order to prevent the loading of unwelcome packages or starting of unwelcome servers, many commands broadcast an event.

For example:

  • Get-OpenPackage will be sent every time a package might be opened.
  • Start-OpenPackage will be sent every time a package might be run as a server.

These events can be used for logging of activity.

We can also use them to prevent some execution

Preventing Execution

Each event has a .MessageData dictionary.

To prevent a command from executing, just say no.

For example, we want to prevent Start-OpenPackage from launching any server, we can use:

Register-EngineEvent -SourceIdentifier Start-OpenPackage -Action {
    Write-Host "Won't Start"

    $event.MessageData['No'] = 'way'
}

Adding any number of keys to an event's message will reject the event.

Those properties are:

  • No
  • Deny
  • Reject
  • Rejected

If any of these properties are found, the command should stop processing.

There aren’t any published security advisories