[HN Gopher] Named Pipes in .NET 6 with Tray Icon and Service
___________________________________________________________________
Named Pipes in .NET 6 with Tray Icon and Service
Author : entrep
Score : 126 points
Date : 2021-11-23 14:06 UTC (8 hours ago)
(HTM) web link (erikengberg.com)
(TXT) w3m dump (erikengberg.com)
| bloblaw wrote:
| Good article, but I wish the author would've addressed securing
| these named pipes.
|
| Consider that if a user-mode application can send messages to a
| privileged process (like a Windows service).
|
| What prevents _any_ user-mode application from doing that? And if
| your Windows service is running as "NT_AUTHORITY/SYSTEM" and
| even executes privileged commands, well you might find you've got
| a simple privilege escalation vuln.
|
| Remember, secure your named pipes...especially when the named
| pipe server runs as SYSTEM.
|
| - https://stackoverflow.com/a/59983266
|
| - https://versprite.com/blog/security-research/vulnerable-name...
| program9 wrote:
| I've worked on apps like this, and I didn't know or care which
| user was going to use the features requiring elevation. So I
| couldn't manage permissions per user. My approach to security
| was to simply limit the input (method parameters usually) from
| the unprivileged process. For example, not letting the client
| send arbitrary commands to execute, use filesystem path
| whitelists, only elevate when required, etc. If the privileged
| code uses a resource, and that resource can be changed/replaced
| by an unprivileged user, then the privileged code can be
| manipulated. Like a Registry key in HKCU for example, or a file
| in a user's AppData folder. Using enums as method parameters
| for privileged code helped me avoid some obvious vulns I
| might've otherwise created. I've definitely done it the wrong
| way before. It can be tough.
| bloblaw wrote:
| This is generally how I've approached this problem as well. I
| like using the `ServiceController.ExecuteCommand` method and
| just send some integer value from the client -> server...and
| the server maps the integer value to a pre-determined
| command.
|
| https://docs.microsoft.com/en-
| us/dotnet/api/system.servicepr...
|
| You've definitely outlined the risk clearly of allowing a
| client to specify anything arbitrarily.
|
| I once wrote a sudo implementation for Windows Vista /
| Windows 7 and first attempt used named pipes communicating to
| a windows service that did some token manipulation to execute
| things _as_ the user (but with elevated token attached as
| well). There be (security) dragons.
|
| I like using named pipes and they are a great IPC mechanism
| for communicating amongst processes of the same privilege
| level. I would not use them for message passing between
| processes of different privilege levels.
| merb wrote:
| I think the package he used, also has some kind of pipe
| authorization access control.
| entrep wrote:
| That is correct.
| entrep wrote:
| Thanks! That's very valid feedback. Could be my next write up.
| bloblaw wrote:
| You're welcome. An alternative I've used to named pipes among
| processes of different privilege levels is to build the
| service to listen for custom commands sent to it. These are
| just integers, and the service maps those to pre-defined
| commands.
|
| Then the only thing the user-mode application can send are
| just flags (integers) that the service has already pre-
| determined what it will do in response.
|
| Here's an article:
| https://www.codeproject.com/Articles/24434/How-to-Write-
| Wind...
|
| And here's a succinct example:
| https://stackoverflow.com/a/5805700
| entrep wrote:
| Interesting. Didn't know about it.
| ww520 wrote:
| Good to address the security aspects of named pipe. However
| none of those describes how to secure the server.
|
| The server needs to call ImpersonateNamedPipeClient() on the
| incoming client connection to assume the client's security
| token, that would lower the server's privilege to the level of
| the client. That's it!
|
| A guest level client can connect to the server. The server's
| privilege becomes guest, and cannot access any resources that
| guest has no permission to access.
|
| [1] https://docs.microsoft.com/en-
| us/windows/win32/api/namedpipe...
| munchler wrote:
| FWIW, the project in the article is explicitly intended to
| allow privilege elevation: "You have an application which
| runs in user context, without any administrative rights, and
| you need to perform some tasks which requires higher
| privileges."
| ww520 wrote:
| The server can do whatever it needs to do in its higher
| privilege. Just when it interacts with the client
| connection, it lowers its privilege to the client's level.
| It gets the incoming data, sanitizes it, and reverts back
| to higher privilege to do the work. This minimizes the
| attack surface to the area dealing with client interaction,
| not the whole server. The server might link in a 3rd party
| XML library to sanitizes the incoming data and you don't
| know what the library can do. Running that in the client
| privilege level ensures that whatever it does only under
| the client's privilege.
| monocasa wrote:
| That thread still has higher privilege write access to
| it's process's state, including the stacks of other
| threads that haven't impersonated that client.
| ImpersonateNamedPipeClient is a very leaky security
| barrier, and far from the only thing you need to know
| about when it comes to named pipe security.
| [deleted]
| k8sToGo wrote:
| I don't know why I expected something more technical for the tray
| icon part. I mean using a third party library is not really
| anything .NET 6 specific.
| entrep wrote:
| I'll guess that will be a separate post.
| comeonseriously wrote:
| Seems to me, the focus of the article was more on named pipes
| than the tray icon, so maybe that's why?
| ape4 wrote:
| Named pipes have been in Windows for many years
| https://docs.microsoft.com/en-us/windows/win32/api/winbase/n...
| hobs wrote:
| First thing I do with SQL Server setups - turn off named pipes
| :)
| giancarlostoro wrote:
| Is there a reason you do this? Curious, I havent had to setup
| SQL Server myself in a while so I don't know what a
| reasonable reason would be.
| tyingq wrote:
| Named pipes are fast when the database is on the same box,
| but slower than a normal tcp connection when the database
| is remote. Something to do with PeekNamedPipe calls having
| to prepend reads.
| hobs wrote:
| Yeah one of my favorite SE posters talks a little more
| about it, generally the benefits are only there if you
| have app/db/sql server all on the same box.
|
| https://dba.stackexchange.com/a/24176/15642
| zwieback wrote:
| Been using them since 1992 but at this point I would naturally
| turn to sockets, even on the same machine. I can't even really
| say why though. Named pipes are nice because they are really
| more like a file but at this point sockets feel more natural
| because they exist and are supported everywhere.
| ziml77 wrote:
| You can apply permissions to named pipes and, well, they're
| named which is useful since you can use a unique and
| deterministic enough name that you don't need an extra band
| of communication for the client to know what port the server
| ended up starting on.
| zwieback wrote:
| Yeah, good point, as opposed to anonymous pipes, which also
| still exist.
| ww520 wrote:
| TCP server cannot assume the security context of the client,
| thus privilege elevation attack can easily happen.
| monocasa wrote:
| More importantly in a lot of cases, you can ask the kernel
| for the client's SID as the server, and make decisions
| knowing that the client couldn't forge it.
| [deleted]
| resoluteteeth wrote:
| This uses the package H.Pipes which seems to use
| System.Runtime.Serialization.BinaryFormatter by default; isn't
| this insecure?
| tonyedgecombe wrote:
| Why is BinaryFormatter insecure?
|
| Edit: Never mind, see https://docs.microsoft.com/en-
| us/dotnet/standard/serializati...
| entrep wrote:
| It's possible to use different formatters for H.Pipes. I will
| probably update the post to not mislead.
| thrower123 wrote:
| I think this is the first NamedPipes tutorial in C# that I've
| ever seen that doesn't do things completely wrong by using a
| StreamWriter or StreamReader. Of course, that's because it uses
| another library that wraps all the tricky bits of NamedPipes that
| everybody always does wrong -> https://github.com/HavenDV/H.Pipes
|
| NamedPipes are sweet for doing same-machine IPC on Windows, that
| is for sure, but the built-in API is full of footguns.
| jborean93 wrote:
| Can you elaborate what's wrong with using StreamReader or
| StreamWriter with a np? I've used them before so wondering what
| I'm potentially doing wrong here and what's the alternative.
| thrower123 wrote:
| It becomes an issue if the data you're reading or writing is
| larger than 1024 bytes and you are in
| PipeTransmissionMode.Message, because of some implementation
| details with buffers and how StreamReader/Writer handle
| Read/Write calls on the underlying
| NamedPipe(Client/Server)Stream
|
| See https://stackoverflow.com/questions/31936100/namedpipeser
| ver...
| jborean93 wrote:
| Thanks for the info, I personally avoid the message mode
| and just operate on bytes so that could be why I haven't
| had problems with it.
| thefz wrote:
| Amazing read and insanely helpful. Thanks a ton both to the
| author and to who posted it, if different people.
| entrep wrote:
| We're the same person. Thanks.
| krisrm wrote:
| Just to clarify something at the start of the article... If you
| are using full Visual Studio to develop with .NET 6, you will
| need 2022. If not, (eg. VS Code), will work with the command line
| sdk.
| philliphaydon wrote:
| Pretty sure there isn't anything you can't do in Jetbrains
| Rider EAP.
|
| Edit: would like to know why I'm being downvoted.
| achandlerwhite wrote:
| Hot reload in Rider only works in debug mode on Windows (to
| be clear it also works in nondebug sessions on Windows). On
| Mac trying to use Hot Reload with Rider on a nondebug session
| errors out, so it's not 100% yet.
| philliphaydon wrote:
| But the article doesn't require hot reload to achieve the
| goal right?
| pjmlp wrote:
| - Debugging across .NET and C++ on the same solution.
|
| - Create a architecture diagram out of .NET and native
| compiled code.
|
| - Integration with SharePoint and Dynamix SDKs
|
| - SQL Server and Azure SDKs
|
| - Using the Fakes mocking framework for MSIL rewriting
|
| - Debugging the GPU shaders
|
| Just a couple of examples, I can take plenty more out of VS
| enterprise.
|
| I really don't get how people can think JetBrains does better
| than platform owners.
|
| They will ever play catch-up with platform capabilities and
| only offer a subset of the package.
| philliphaydon wrote:
| So, the parent comment I replied to was in relation to
| needing VS 2022 for .NET 6, to which I replied that you
| could use Jetbrains Rider EAP, obviously for .NET 6, to
| accomplish the task in the linked post.
|
| > They will ever play catch-up with platform capabilities
| and only offer a subset of the package.
|
| Obviously, they are competing with a 20+yo product.
|
| But atleast I can get all my .NET work done on Linux
| without needing slow bloated VS with a ton of useless
| features like 'unit testing for poor code choices or legacy
| codebases', or 'integration with the 2nd worst
| collaborative tool after Jira'.
| pjmlp wrote:
| Sure when it all boils down to the tiny .NET Core subset
| of ASP.NET MVC applications, instead of those 20 years of
| history.
|
| Looking forward to see how they deal with MAUI and Blazor
| integration.
|
| What others call bloat I call productivity features.
| sebazzz wrote:
| An alternative that comes with built-in dependency injection is
| using the .NET hosted process model. Much easier to test too.
___________________________________________________________________
(page generated 2021-11-23 23:01 UTC)