Code Monkey home page Code Monkey logo

sandboxamples's Introduction

Sandbox Examples

Goals

  1. Kernel- and user-space process based sandboxing examples for common hosted runtimes (Windows, Linux, MacOS, BSDs).
  2. Each hosted runtime must contain assumptions and tests.
  3. Portable abstractions are defered, but planned for later for a CI library with CI as use case.
  4. Make code simple to cross-compile and natively compile.
  5. Eventual goal is compare with (realtime) OS security model design to estimate how far off current OS implementations are and have some more structured designs to use for sel4 based OSes including drivers.
  6. Tooling, good design and scalability: Library approach.

Status

Windows

Linux

  • landlock (access control on kernel objects)
  • seccomp-bpf (syscall filtering)
  • parallel process spawn handle leak problem with workarounds
    • mutex or only standard handles
    • list of to be closed handles does not work, because order of handles which are inherited is not guaranteed to be stable and may vary during process lifetime
  • file system sandboxing by user account (chown, chmod, Linux permission system)
  • setreuid, setregid (bounded waiting, fixing libstd child_process errors)
  • cgroups (semantic mismatch, more powerful than job object),
  • network sandboxing, seccomp-bpf
  • what other persistent state may be accessible? - look into namespaces https://lwn.net/Articles/531114/
  • minimal system setup, solution?
  • tight system supervision setup, solution?
  • security shutdown, lockdown?
  • more advanced: race-free signaling

MacOS

  • sandbox-exec, look into firefox and chromium sandboxing code stackoverflow question some overview
  • how to wait for process group
    • kevent NOTE_TRACK needed
    • orphaned processes still not cleaned up
    • fork bomb unmitigated (applying posix limits needed)
    • workaround jobs not finishing in deadline: kill all processes with uid
  • what other persistent state may be accessible?
  • minimal system setup, solution?
  • tight system supervision setup, solution?
  • security shutdown, solution?

Other BSDs and Unixes

  • Kernel API sandboxing works likely very similar to other solutions
  • process API with identical problems
  • network parts unclear
  • other parts are highly configuration dependent

Tests and implementation

Tests are to be found in test/.

General procedure:

    1. Find reasonable short example code
    1. Add testfile.c to test\win\ and build.zig
    1. zig translate-c test\win\testfile.c > test\win\testfile.zig, add it to build.zig
    1. simplify test\win\testfile.zig, implementation, error abstractions

Deviation:

  • Follow different example code, ideally with sufficient explanations
  • Opaque pointers (Windows) hard to debug/check for correctness of operations
  • More than 3 parameter with optional pointer or weird problems
  • Standalone C and Zig files as libs, main calls C version and vice versa
    • bare bone C pointers in Zig
    • identical logic for Zig and C version
    • combinations to figure out what went wrong
    • view assembly diffs
    • record program and inspect fn args structures
  • TODO setup Kernel debugging to get logic
  • TODO program + procederes to extract underlying in-Kernel structures/code collection instead of opaque pointers (ntdll trace, ghidra?)
  • TODO trace fn args structures => debugger plugin

References

sandboxamples's People

Contributors

matu3ba avatar

Watchers

 avatar  avatar

sandboxamples's Issues

Tracking Issue idealized formal model for permissions, process tracking and IPC (signaling etc)

Gotta got formal to be eventually picked up by sel4 instead of not good (underspecified and insufficiently complete) POSIX model.

Why
Posix/Linux too with complex API, unspecified and forces solving handle leak problem by user with high performance cost (mutex + 2 calls to set and unset CLEXEC on all intended to be seperataly inherited handlers xor not doing parallel process spawning at all).


existing process has ressources
  handle1(secret)
  handle2(non-secret)

      userspace          │    kernelspace    │   userspace
      ───────────────────┼───────────────────┼───────────────────── 
      thread1 calls fork │                   │   thread2 calls fork
      (or clone)                                 (or clone)
      spawned process 1◄────               ─────►spawned process 2
      high trust         |   does not ensure |   low trust
                         |   handles do not  |   (might not close secret handle1)
                         |   cross trust     |
      intend             |   boundaries      |   intend 
      gets only handle1  |=> no in-memory    |   gets only handle2
                         |   single process  |
                         |   trust storage   |
                         |   possible        |
                         |   (must use other |
                         |    process)       |

Solution uses similar semantics as Windows explicit list of inherited handles, although Windows ones are worse with file handles needing to stay opened or spawning fails. See https://github.com/mikdusan/child-process/issues/1 for the possible Posix fix.

Further, the Linux solution is complex, see http://catern.com/process.html and https://github.com/catern/supervise.

Windows has too comples API and requires even more meta objects with selecting multiple ways of doing the same, but slightly differently. System call filtering is only partially supported (kernel32 + ntdll API with ~400 calls still accessible) with kernel32 being "security by obscurity" as "kernel lib on top of kernel hidden from user".
See matu3ba/win32k-mitigation#3, for ntdll and kernel32 restriction https://github.com/matu3ba/win32k-mitigation/tree/master/test/standalone/child_process_ntdll_only, for explicit file handle inheritance (good thing, if there would not be 5 ways of doing it with multiple combinations and its behavior not specified https://github.com/matu3ba/win32k-mitigation/tree/master/test/standalone/child_process_explicit_handles).

Also, async with list would mandate solving the same problem.

Main semantic questions for static scheduling

  • minimal base system requirements
  • sel4 model
  • declarative Kernel API generation? versioning? querying?
  • performance, synchronization, memory footprint, meta-data extraction and reasoning
  • kernel as a lib like kernel32 solution with well-specified semantics?

Main semantic questions for dynamic prefdefined scheduling

  • unclear, probably the same as static + attaching solver?

Main semantic questions for dynamic prefdefined scheduling

  • unclear, probably the same as static + attaching solver + providing proof for OS selection?

static kernel API call filtering (seccomp and alternatives on other OSes)

unclear: can kernel32 or ntdll calls be patched, ie as admin or system user by providing empty stubs? idea would be to spawn suspended, patch out stubs with debug API and do the same subsequently for spawned child processes.

  • requires stubs patching being possisble
  • requires watching for subset of ntdll calls possible
  • requires debug API be able to follow child processes

windows design flaw: no reliable notification about process tree termination

See https://stackoverflow.com/questions/28025869/reliable-waiting-for-process-tree-completion and https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_associate_completion_port?redirectedfrom=MSDN

Note that, except for limits set with the JobObjectNotificationLimitInformation information class, 
messages are intended only as notifications and their delivery to the completion port is 
not guaranteed. The failure of a message to arrive at the completion port does not necessarily 
mean that the event did not occur.

So it looks like there is no really reliable way to get process tree completion notifications in Windows.
One has to use polling, for example via https://learn.microsoft.com/de-de/windows/win32/api/jobapi2/nf-jobapi2-queryinformationjobobject JOBOBJECT_BASIC_ACCOUNTING_INFORMATION.

With admin privileges and ETW, see for example https://stackoverflow.com/questions/28882178/how-can-i-capture-process-names-using-the-traceevent-library suggesting to use process id, one can write an own task manager to track process relations (examples in https://www.nuget.org/packages/Microsoft.Diagnostics.Tracing.TraceEvent.Samples/).
But that is pretty much overkill.

A workaround with known process names is to wait for them to terminate, but there might be identically named processes spawned in other job units we are waiting for leading to potential deadlocks, if both wait for another on the same system.

file system permission checks and restrictions

TODO

general improvements

  • restrict ETW output of specific program to create sandboxing rules enforced by CI for running as impersonated lower privileged user
  • ci tests: create another user and use it for checking file permissions

windows: add method to wait for process group termination

See CI, which can be locally reproduced with a few attempts and/or under heavy system load:

test
+- run main_job_api failure
hasProcessPrefix err: error.PartialCopy
error: ProcessHasUnwantedPrefix
D:\a\sandboxamples\sandboxamples\test\win\main_job_api.zig:151:21: 0xcf1b34 in behavior (main_job_api.exe.obj)
    if (has_prefix) return error.ProcessHasUnwantedPrefix;
                    ^
D:\a\sandboxamples\sandboxamples\test\win\main_job_api.zig:37:5: 0xcf327a in main (main_job_api.exe.obj)
    try behavior(gpa);
    ^
error: the following command exited with code 1 (expected exited with code 0):
D:\a\sandboxamples\sandboxamples\zig-out\bin\main_job_api.exe D:\a\sandboxamples\sandboxamples\zig-out\bin\evildescendent_child_job_api.exe 
test
+- run main_acl stderr
sec_info: sec.os.win.SecurityInfo{ .sid_owner = ?*sec.os.win.PSID__opaque_4421@1fc558c2374, .sid_group = null, .dacl = null, .sacl = null, .sec_descr = ?*anyopaque@1fc558c2360 }
Build Summary: 24/26 steps succeeded; 1 failed
test transitive failure
+- run main_min success 10ms MaxRSS:4M
|  +- zig build-exe main_min Debug native success 2s MaxRSS:154M
|  +- zig build-exe child_min Debug native success 1s MaxRSS:134M
+- run main_explicit_handle_inheritance success 93ms MaxRSS:5M
|  +- zig build-exe main_explicit_handle_inheritance Debug native success 41s MaxRSS:164M
|  +- zig build-exe child_explicit_handle_inheritance Debug native success 2s MaxRSS:134M
|  +- install success
|     +- install child_explicit_handle_inheritance success
|     |  +- zig build-exe child_explicit_handle_inheritance Debug native (reused)
|     +- install main_explicit_handle_inheritance success
|     |  +- zig build-exe main_explicit_handle_inheritance Debug native (reused)
|     +- install child_win32k_mitigation success
|     |  +- zig build-exe child_win32k_mitigation Debug native success 2s MaxRSS:136M
|     +- install main_win32k_mitigation success
|     |  +- zig build-exe main_win32k_mitigation Debug native success 41s MaxRSS:153M
|     +- install evildescendent_child_job_api success
|     |  +- zig build-exe evildescendent_child_job_api Debug native success 41s MaxRSS:143M
|     +- install main_job_api success
|     |  +- zig build-exe main_job_api Debug native success 2s MaxRSS:155M
|     +- install main_getsecurityinfo_c success
|     |  +- zig build-exe main_getsecurityinfo_c Debug native success 41s MaxRSS:129M
|     +- install main_acl success
|        +- zig build-exe main_acl Debug native success 2s MaxRSS:151M
+- run main_win32k_mitigation success 62ms MaxRSS:4M
|  +- zig build-exe main_win32k_mitigation Debug native (reused)
|  +- zig build-exe child_win32k_mitigation Debug native (reused)
|  +- install (+8 more reused dependencies)
+- run main_job_api failure
|  +- zig build-exe main_job_api Debug native (reused)
|  +- zig build-exe evildescendent_child_job_api Debug native (reused)
|  +- install (+8 more reused dependencies)
+- run main_getsecurityinfo_c success 43ms MaxRSS:4M
|  +- zig build-exe main_getsecurityinfo_c Debug native (reused)
|  +- install (+8 more reused dependencies)
+- run main_acl success 25ms MaxRSS:5M
   +- zig build-exe main_acl Debug native (reused)
   +- install (+8 more reused dependencies)
error: the following build command failed with exit code 1:
D:\a\sandboxamples\sandboxamples\zig-cache\o\ef63a89db80e75a4dd49f5ce93c545b0\build.exe C:\hostedtoolcache\windows\zig\master\x64\zig.exe D:\a\sandboxamples\sandboxamples D:\a\sandboxamples\sandboxamples\zig-cache C:\Users\runneradmin\AppData\Local\zig --seed 0x615abec9 -Z016111adb887a881 test --summary all
Error: Process completed with exit code 1.

Probably Windows has a dedicated method to wait for process group termination.

windows token based stuff

Main motivation https://wiki.sei.cmu.edu/confluence/display/c/WIN02-C.+Restrict+privileges+when+spawning+child+processes

https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createprocesswithtokenw
https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessasusera
https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/privilege-escalation-abusing-tokens
https://github.com/hatRiot/token-priv
https://securitytimes.medium.com/understanding-and-abusing-process-tokens-part-i-ee51671f2cfa
https://learn.microsoft.com/en-us/windows-server/security/windows-authentication/credentials-processes-in-windows-authentication

Because security must be complex for security products?
https://learn.microsoft.com/en-us/windows/win32/secauthz/securable-objects
https://learn.microsoft.com/en-us/windows/win32/secauthz/access-rights-and-access-masks
https://learn.microsoft.com/en-us/windows/win32/secauthz/access-tokens

Also briefly mention antipattern of cleartext user password logins regarding information persistence
and/or how to work around that with deleting and creating new user with random password.

And briefly antipatterns/pick your poison regarding https://www.tevora.com/threat-blog/about-windows-process-thread-tokens-and-pass-the-hash/. Must understand if there is no better way or simply not mentioned here.

TODOs

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.