vlc_sandbox.md 13 KB

Design sandbox avec broker

struct broker_worker_t
{
    int id;
    int fd; // process_ipc
    ARRAY_DECL(int) acls;
};

struct broker_state_t
{
    ARRAY_DECL(const broker_worker_t *) workers;
};

struct worker_state_t
{
    int id;
    int fd; // process_ipc
};

Lorsqu'on crée le nouveau premier objet dans un nouveau processus, le broker enregistre l'id de l'objet. Lorsqu'on essaye de passer un objet non broker-boxé via un message en faisant un process_handler_t, le broker génère un nouvel id pour l'objet et le retourne à l'appelant, qui l'intègre au message.

Les messages ont la forme suivante :

struct msg
{
    // When sending from broker
    uint32_t from;
    // Common stuff
    uint32_t op;
    uint32_t target;
    uint32_t action;

    void* args;
};

Les réponses ont la forme suivante :

struct answer
{
    uint32_t op;
    uint32_t from;
    void* payload;
};

Cas particulier de la création du processus : la target est ignoré, et from renvoie l'ID du nouveau module créé dans le nouvel étage.

Windows passage de descripteur de fichiers

From https://msdn.microsoft.com/en-us/library/bb625962.aspx

Service applications using multiple processes are sometimes designed to duplicate handles to objects, such as files, between server processes. If all the processes are running under the same special service account, the default security on service processes does not introduce restrictions. The default DACL on service processes running under special service accounts does not grant PROCESS_DUP_HANDLE access, which is required for DuplicateHandle calls. Application service designers have to implement functionality to grant PROCESS_DUP_HANDLE access on the service process object to another user account used by a co-process in order to share handles between application processes that run under different user accounts. But if the service into which you want to duplicate the handle is a special service account running at a system integrity level, a co-process running at a high or medium integrity level will not be able to obtain PROCESS_DUP_HANDLE because of the mandatory label policy. Even if the DACL grants PROCESS_DUP_HANDLE access, the mandatory label policy does not allow lower-integrity callers that access. If this situation affects the service application design, the application service code will need to change so that the process that initiates DuplicateHandle is at an integrity level higher than the integrity level of the process that is the source of the handle. That is, a higher-integrity service can duplicate a handle into its own process as a target from a lower-integrity process as the handle source.

https://bugs.chromium.org/p/chromium/issues/detail?id=338538 https://chromium.googlesource.com/chromium/src.git/+/dc84fcce71f37e6faeab9dce6ae2a65f1e12a5d2%5E%21/#F0

Windows ignores DACLs on certain unnamed objects (like shared sections). So, we generate a random name when we need to enforce read-only.

Windows isolation réseau

https://msdn.microsoft.com/en-us/library/hh780593 https://msdn.microsoft.com/library/0a97956e-fda9-4791-b87b-9e03ae135382

Not possible without Hyper-V, which needs Windows 10 Pro.

Windows, Shatter attack, UIPI

http://www.coseinc.com/en/index.php?rt=download&act=publication&file=Vista_UIPI.ppt.pdf https://en.wikipedia.org/wiki/Shatter_attack http://www.hpl.hp.com/techreports/2005/HPL-2005-87.pdf

=> Since windows vista, 4 integrity levels: low, medium, high, system

Exploiting a leaked thread handle project zero

https://googleprojectzero.blogspot.com/2016/03/exploiting-leaked-thread-handle.html

other attacks:

Documents à lire

VLC-sandboxing orienté module

Windows security

  • Jobs are not aimed at providing security, they are like cgroups.
  • CreateRestrictedToken is the most powerful barrier all windows 10 has.
  • Better options are limited to Window 10 pro edition, and include virtualization or WSL.
  • Windows has unix socket in WSL too, but they don't support SCM and so file descriptor transfer between processes.

CreateRestrictedToken

When trying to access a resource, Windows will check the user SID and group SID, and then will check the restricted token. Thus, restricted token can be used as a way to limit one process's available resources, by attaching a restricted token to it.

As the user and group is checked, this token can only be used to limit existing right and can't add new ones.

It is worth noticing that it doesn't limit resources access from the outside to the restricted process.

A restricted token can be a primary or impersonation access token.

From the documentation, it allows three ways of restricting a token:

https://docs.microsoft.com/en-us/windows/desktop/secauthz/restricted-tokens

  • Remove privileges from the token.
  • Apply the deny-only attribute to SIDs in the token so that they cannot be used to access secured objects. For more information about the deny-only attribute, see SID Attributes in an Access Token.
  • Specify a list of restricting SIDs, which can limit access to securable objects.

To create a process with a restricted primary token, CreateProcessAsUser must be used, with the caller process having the SE_ASSIGNPRIMARYTOKEN_NAME privilege if it doesn't specify a restricted version of the caller's primary token.

It is possible to activate a restricted token later by using the token with the ImpersonateLoggedOnUser function.

Security note:

Applications that use restricted tokens should run the restricted application on desktops other than the default desktop. This is necessary to prevent an attack by a restricted application, using SendMessage or PostMessage, to unrestricted applications on the default desktop. If necessary, switch between desktops for your application purposes.

It is possible to transfer a token from one process to another thanks to DuplicateHandle, as explained in the following forum posts:

https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/9bd4bce0-033a-431b-abb8-2c10438e6283/how-can-i-pass-security-token-from-one-process-to-another-?forum=windowssecurity https://stackoverflow.com/questions/2331363/is-passing-a-windows-security-token-between-processes-permitted

ImpersonateNamedPipeClient: https://stackoverflow.com/a/2339129

Windows IPC

Todolist

[x] vlc_ipc_SendIpc must write the size of the message, then write each part of the message.

[x] vlc_ipc_RecvMsg must read the size of the message, then read the whole message.

[x] vlc_msg_append_block must put the name of the shared memory.

[x] vlc_msg_recv_block must open the shared memory and map it.

[ ] zygote calls createprocess with --sandbox-worker=%file_descriptor_read option.

[ ] zygote sends write file descriptor to new worker and then close it.

[ ] vlc_sandbox_start should start the worker eventloop if --sandbox-worker option is present in the command line.

[ ] vlc_sandbox_start should start the zygote if --sandbox-zygote=%fd is present in the command line.

[ ] block_alloc should create a file mapping using createfilemapping and map it in memory using mapviewoffile.

[ ] block_filemapping_init should use OpenFileMapping and MapViewOfFile.

[ ] IPC in the Windows sandbox must be named pipes instead of anonymous pipes because anonymous ones don't have support neither for duplex communication nor overlapped IO operations. It means that a proper planning of SID must be made to restrict other low integrity level sandboxed process.

[ ] msg_poller should use io completion port => might work, try out => take care socket deletion

[ ] vlc_ipc_close should close the handle, and might need to manage the allocated memory (for overlapped structure for example)

[ ] replace close(ipc.fd) by vlc_ipc_close(ipc)

[ ] try removing the zygote process from the windows model, only inherit the handle for IPC when creating a new process.

IOCP

https://www.codeproject.com/Articles/10330/A-simple-IOCP-Server-Client-Class http://www.drdobbs.com/cpp/multithreaded-asynchronous-io-io-comple/201202921?pgno=3

completion vs readiness https://softwareengineering.stackexchange.com/questions/293908/readiness-vs-completion-async-io-memory-usage https://stackoverflow.com/questions/2794535/linux-and-i-o-completion-ports

The readiness model notify that a file descriptor is ready for action, whether it is reading or writing to it. The user then can perform the kernel-to-user action without waiting. In particular, it means that you can use one buffer for the whole set of file descriptor when reading.

The completion model notify that the operation planned on a file descriptor has been satisfied. The user has to start the operation and let the operating system do it on its own, whether or not the file descriptor was ready. In particular, it means that you need one buffer for each file descriptor as you can't know in which order the operation will be satisfied.

The workflow for IOCP on Windows to emulate the msg_poller is to create an IoCompletionPort with the following call.

HANDLE iocp =
    CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, nThreads );

Then associate a HANDLE handle to the port, with key being a registration key used as identifier or pointer, given back in the notification of this handle.

CreateIoCompletionPort( handle, iocp, key, 0 );

The port is ready so start read requests, giving an OVERLAPPED object and a new buffer to each read request when no request is pending.

FOREACH( struct iocp_buffer*, iohandle, iohandles )
{
    if( !iohandle->pending )
        ReadFile( iohandle->handle, iohandle->buffer,
                  length, NULL, iohandle->overlapped );
}
ENDFOR()

And finally wait for on the request to be satisfied by the operating system. The argument overlapped is required to be passed as a LPOVERLAPPED struct, but the example in the documentation uses a OVERLAPPED** instead.

DWORD length = 0;
ULONG_PTR key = 0;
OVERLAPPED *overlapped = NULL;

GetQueuedCompletionStatus( iopc, &length, &key, &overlapped, INFINITE );

Finally, overlapped contains the information about the handle and the buffer, while key contains an additional information to recognize the operation.

We can proceed to the next operations on the data and release the overlapped structure.

TODO: removing HANDLE from the IO port.

ReadFileEx provide another kind of writing asynchronous IO, but still built upon this concept of completion. One can register an user-defined callback which will be casted at the end of the IO operation.

This callback will get the ownership of the OVERLAPPED object and will be responsible for processing and releasing it.

a lire https://opensource.googleblog.com/2010/01/libevent-20x-like-libevent-14x-only.html => easier to write a notify-to-completion than completion-to-notify wrapper.

design issues when using IOCP in a winsock server https://support.microsoft.com/en-us/help/192800/info-design-issues-when-using-iocp-in-a-winsock-server

fast portable non blocking network programming with libevent http://www.wangafu.net/~nickm/libevent-book/

closing a file handle with IO completion https://stackoverflow.com/questions/6573218/removing-a-handle-from-a-i-o-completion-port-and-other-questions-about-iocp

Sandbox todolist

[ ] Create process by zones, all video decoders in the same process, all audio in the same other process and vout/aout in the same process as their respective counterpart

[ ] Process creation policy should be in the broker process and configured at vlc_sandbox_Init by the application caller.

[ ] Special process creation order should be possible, for example when having multiple video outputs.

[ ] Release object correctly, proxy objects should have a special released handler associated to them and be released as soon as the other endpoint is released.

[ ] Handle cross-process errors and report them to the other process correctly

[ ] Handle other process life cycle, health and failure

[ ] Play with SID on Windows to understand how it works.