<div dir="ltr"><div>Hello,</div><div><br></div><div>It has been a while since it was published but maybe you will find this interesting: <a href="http://www.erlang.se/publications/xjobb/0109-naeser.pdf">http://www.erlang.se/publications/xjobb/0109-naeser.pdf</a></div><div><br></div><div>Lukas</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Dec 11, 2019 at 6:07 AM Henrique Marcomini <<a href="mailto:henrique4win@gmail.com">henrique4win@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><span style="font-family:monospace">Hi,<br><br>  I've been working with erlang/elixir for the past year and I really miss<br>SECCOMP like features in the BEAM. So I started an implementation based on<br><a href="https://github.com/erlang/otp" target="_blank">https://github.com/erlang/otp</a> and I wanted to know what you people think about<br>it.<br><br>  The idea is to provide a way to blacklist/whitelist function calls on a<br>process level, so for example if I'm evaluating human input for a calculation,<br>I can guarantee that no other function except the ones that are necessary are<br>called. Going further, in a case where my erlang cookie is leaked, I know<br>that only a limited set of functions are callable using rpc or node.spawn/2.<br><br>  The way I envision it (and I'm implementing it) is adding a byte to the<br>process struct with the following meaning:<br><br>   0 1 2 3 4 5 6 7<br>  +-+-+-+-+-+-+-+-+<br>  |E|M|S|I|U|U|U|U|<br>  +-+-+-+-+-+-+-+-+<br><br>  Where:<br>    E -> Whether the mechanism is active (0:Off/1:On)<br>    M -> Operation Mode (0:Whitelist/1:Blacklist)<br>    S -> Disable Spawn (0:Can spawn new process/1:Cannot spawn new process)<br>    I -> Whether a child process will inherit the<br>    U -> Unused<br><br>  There are some implicit rule in this byte:<br>    - M,S, and I are unused whether E is set to 0<br>    - I is unused if S is set to 1<br><br>  I choosed to use a byte because bitwise operation are cheap and are the least<br>expensive way I could think, and bitmasks can be combined in a meaningful way.<br><br>  The verification of this byte would occur at the apply function, so we can<br>check the byte every time a function is called. To know which function is<br>whitelisted/blacklisted I added an Eterm to the process struct. This Eterm is a<br>NIL terminated list of tuples, each tuple contains two atoms representing the<br>module name and the function name which is whitelisted/blacklisted.<br><br>  Probably a hashmap, or a binary tree of hashs would be quicker to search.<br>But I don't know if there is any good low level way to introduce it without<br>adding a lot of code to the code base.<br><br>  To implement process inherit capabilites, I added a verification on spawn, <br>but there are some possible bypasses that would need to be treated latter on.<br><br>  For example:<br><br>-------------------------------------------------------------------------------<br><br>  If there is a process running as a dynamic supervisor (P1), some other <br>process (P2) may send a message to spawn some worker (P5) and the father <br>process would be the supervisor (P1), which may not have the mechanism active. <br><br>Diagram below:<br><br><br>             |                              |<br>             |  P1 - Dynamic Supervisor     | P2 (With active mechanism)<br>             V                              |<br>      ===============                       |<br>      | P3   | P4                           V<br>      V      V<br><br>  When P2 asks P1 to spawn a new worker, the diagram will look like the<br>following:<br><br><br>             |                              |<br>             |  P1 - Dynamic Supervisor     | P2 (With active mechanism)<br>             V                              |<br>      ===============                       |<br>      | P3   | P4   | P5                    V<br>      V      V      V<br><br>  Where P3, P4, and P5 are spawned with P1 as a parent, so it will not inherit<br>any rules from P2. At this point P5 can execute any code and send a message to<br>P2, bypassing the mechanism.<br><br>-------------------------------------------------------------------------------<br><br>  On another case a process (P1) on Node 1 which is under this mechanism may<br>spawn another process (P2) to Node 2, and then P1 spawns another process (P3)<br>on Node 1. If process generated by spawns of other nodes are less secure than<br>the process that called the spawn function, it will lead to privilege<br>escalation.<br><br>Diagram below:<br><br> +---------------+              +---------------+<br> |               |              |               | <br> |    Node 1     |              |    Node 2     | <br> |               |              |               | <br> |        P1     |   spawn/2    |               | <br> |   ------------> -------------> --------+     |<br> |       calls   |              |         |     | <br> |               |              |         | P2  | <br> |               |              |         |     | <br> |        P3     |   spawn/2    |  calls  |     | <br> |   <---------- <------------- <---------+     | <br> |               |              |               | <br> +---------------+              +---------------+<br><br>  If P3 restrictions are less strict than P1, then P1 escalated privilege.<br><br>-------------------------------------------------------------------------------<br><br>  The code that I'm working is at <a href="https://github.com/Supitto/OTP/tree/maint" target="_blank">https://github.com/Supitto/OTP/tree/maint</a><br>and it is built upon the maint branch. It still quite imature and have some<br>edges to trim (I'm still figthing with allocations and Eterms). But if this<br>idea is apreciated I will implement everything on the main branch. Also if <br>you can think of some other scenario where this mechanism is defeated, please<br>infome me :D<br><br>Thanks,<br><br>Henrique Almeida Marcomini<br><br>Telegram -> @supitto<br>IRC (freenode) -> Supitto<br><br>Ps. The code on the repo may be not working (depends on the commit), but the<br>    idea is there.<br><br>Pps. I made everything in ASCII so to see it properly use monospace fonts</span></div>
</blockquote></div></div>