How to access files without the need of "sudo"?

1,671 views
Skip to first unread message

Constantine Vass

unread,
Mar 11, 2014, 4:37:31 PM3/11/14
to golan...@googlegroups.com
I am executing the following code in myApp:

err := server.ListenAndServeTLS(runPath+"/myApp.net-cert.pem", runPath+"myApp.net-key.pem")
if err != nil {
fmt.Printf("%s|%s|%s|%s|%s|%s", routine, "ListenAndServe ERROR", err, " ", " ", " ")
fmt.Println()
panic(err)
}

If I run as "> myApp" I get this error message:


main|ListenAndServe ERROR|listen tcp 0.0.0.0:443: bind: permission denied| | | 

panic: listen tcp 0.0.0.0:443: bind: permission denied


goroutine 1 [running]:

runtime.panic(0x24ca00, 0xc21008f840)

/usr/local/go/src/pkg/runtime/panic.c:266 +0xb6



If I run as "> sudo myApp" it is working.

As I see the app needs root privileges to access the .pem files. I am getting
this error trying to access other files too.

How to access files without the need of "sudo"?

Brian Hatfield

unread,
Mar 11, 2014, 4:41:28 PM3/11/14
to Constantine Vass, golan...@googlegroups.com
The error you pasted is not from an attempt to access a .pem file, it's because you're trying to bind to a port lower than 1024 without root permissions. If you'd like to run your service without root, bind to a port higher than 1024 (eg 8443). Alternatively, with sudo, use authbind to hand your process 443 and then de-escalate privileges for the actual execution.


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Constantine Vass

unread,
Mar 11, 2014, 4:46:39 PM3/11/14
to golan...@googlegroups.com, Constantine Vass
The app is running under mac mini server and have to make it work with launchd anyway.
I suppose then when it runs as a root I will not have this issue. 

But I am still trying to understand how to make it work with launchd.

Bryan Whitehead

unread,
Mar 11, 2014, 4:46:32 PM3/11/14
to Constantine Vass, golang-nuts
this is not a file read privileges error. this is don't have privilege to listen on port 443.

All ports below 1024 (possibly more) are privileged ports, your app must be run as root.

OR just run and listen to on port 6443 and add some iptables rules to DNAT request to 443->6443.

In practice I don't use ListenAndServeTLS, i just use ListenAndServe and then have nginx do the SSL and proxy to port 8080.


Rodrigo Kochenburger

unread,
Mar 11, 2014, 4:49:46 PM3/11/14
to Constantine Vass, golan...@googlegroups.com
You probably don't wnat it running as root though for security reasons, otherwise if any use successfully exploit any vulnerability they will have root superpowers... 

- RK

Constantine Vass

unread,
Mar 11, 2014, 4:58:31 PM3/11/14
to golan...@googlegroups.com, Constantine Vass
I am getting this error trying to open a file. I suppose
I need to set root permission for the directory with the file?

Constantine Vass

unread,
Mar 11, 2014, 5:15:48 PM3/11/14
to golan...@googlegroups.com, Constantine Vass
When I give Everyone:read&write permissions it is working but it is not safe.

I am wondering if I am using launchd how the 443 and file permissions need to be set?

Dave Cheney

unread,
Mar 11, 2014, 10:35:33 PM3/11/14
to golan...@googlegroups.com, Constantine Vass
Launchd has two options.

1. $USER/Library/LaunchDaemons [sic] for services run as $USER
2. /System/Library/LaunchDaemons [sic] for services run as root

It sounds like you want to place your launchd config file in the latter.

You should pay attention to others in the thread who have encouraged you NOT to do this, it sounds like you don't really understand the implications of your actions and how they affect the security of your service.

Cheers

Dave

Constantine Vass

unread,
Mar 12, 2014, 4:15:14 AM3/12/14
to golan...@googlegroups.com, Constantine Vass
Following Apple's guide I place it in Apple recommended places:

"Property list files describing daemons are installed in /Library/LaunchDaemons, and those describing agents are installed in /Library/LaunchAgents or in the LaunchAgents subdirectory of an individual user’s Library directory. (The appropriate location for executables that you launch from your job is /usr/local/libexec.)"

1) /usr/local/libexec/WebServer01
This is the Golang code for listening to port 80:
===
var listenAddr string = "0.0.0.0:80"
...
err := http.ListenAndServe(listenAddr, nil)
if err != nil {
fmt.Printf("\n%s|%s|%s|%s|%s|%s", "ListenAndServer error", err, " ", " ", " ", " ")
panic(err)
}
===

2) /Library/LaunchDaemons/com.mydomain.webServer01.plist

com.mydomain.webServer01.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.mydomain.webServer01</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/libexec/WebServer01</string>
</array>
<key>Sockets</key>
<dict>
<key>Listeners</key>
<dict>
<key>SockServiceName</key>
<string>80</string>
</dict>
</dict>
<key>RunAtLoad</key>
<false/>
</dict>
</plist>

Then:
sudo chown root:wheel com.mydomain.webServer01.plist
sudo chmod 644 com.mydomain.webServer01.plist
and copy com.mydomain.webServer01.plist to /Library/LaunchDaemons/

If I run WebServer01 from command line like:
"sudo ./WebServer01" it is working OK - the web site is served fine.
when I try to run it like:

launchctl load com.mydomain.webServer01.plist

bind(): Permission denied


with:
sudo launchctl load com.mydomain.webServer01.plist

I don't get an error message in Terminal but in Logs I see:
Mar 12 00:50:32  TTY=ttys008 ; PWD=/Library/LaunchDaemons ; USER=root ; COMMAND=/bin/launchctl load com.mydomain.webServer01.plist
Mar 12 00:50:41  kernel[0]: CODE SIGNING: cs_invalid_page(0x1000): p=45936[WebServer01] final status 0x0, allowing (remove VALID) page
Mar 12 00:50:41 com.apple.launchd[1] (com.mydomain.webServer01[45936]): Exited with code: 2

and the web page is not working. 

Are there a working code with example how to run a golang web server with launchd?

Gyepi SAM

unread,
Mar 12, 2014, 5:06:39 AM3/12/14
to Constantine Vass, golan...@googlegroups.com
On Wed, Mar 12, 2014 at 01:15:14AM -0700, Constantine Vass wrote:
> Following Apple's guide I place it in Apple recommended places:
>
> https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html#//apple_ref/doc/uid/10000172i-SW7-BCIEDDBJ
> "Property list files describing daemons are installed in /Library/
> *LaunchDaemons*, and those describing agents are installed in
> /Library/LaunchAgents or in the LaunchAgents subdirectory of an individual
> user’s Library directory. (The appropriate location for executables that
> you launch from your job is /usr/local/*libexec*.)"
> ....
> *I don't get an error message in Terminal but in Logs I see:*
> Mar 12 00:50:32 TTY=ttys008 ; PWD=/Library/LaunchDaemons ; USER=root ;
> COMMAND=/bin/launchctl load com.mydomain.webServer01.plist
> Mar 12 00:50:41 kernel[0]: CODE SIGNING: cs_invalid_page(0x1000):
> p=45936[WebServer01] final status 0x0, allowing (remove VALID) page
> Mar 12 00:50:41 com.apple.launchd[1] (com.mydomain.webServer01[45936]):
> Exited with code: 2
>
> and the web page is not working.
>
> Are there a working code with example how to run a golang web server with
> launchd?

This is not a Go specific problem.

Your code needs to be signed or at least the system needs to be configured
to run your code without signing. See spctl.

To add to previous suggestions; if your service is going to run on the public
Internet, I strongly suggest that you get someone competent and more knowledgeable to help
or at least review the results; proper security is best not learned by
stitching together bits and pieces of information gleaned from mailing lists.

-Gyepi

Constantine Vass

unread,
Mar 12, 2014, 11:49:10 AM3/12/14
to golan...@googlegroups.com, Constantine Vass, self-...@gyepi.com
All that is correct. Could you please elaborate more on 
:80 facing page security issues?

Gyepi SAM

unread,
Mar 12, 2014, 1:58:04 PM3/12/14
to Constantine Vass, golan...@googlegroups.com
On Wed, Mar 12, 2014 at 08:49:10AM -0700, Constantine Vass wrote:
> All that is correct. Could you please elaborate more on
> :80 facing page security issues?

This is what I mean. Security is not just about what service you
run on port 80. The server and the services it provides and how it does
so are all important. Just as important are what other services are available
on the system and so on. The goal is to minimize your attack exposure,
compartmentalize when possible, reduce privilege to minimal levels and track
your inputs. The concern here is based on the questions you're asking, it is
not clear you are aware of these issues.

Security is not a punch list you go through just before deployment.

-Gyepi

Constantine Vass

unread,
Mar 12, 2014, 2:47:57 PM3/12/14
to golan...@googlegroups.com, Constantine Vass, self-...@gyepi.com
A clean machine port 80 serving a static web site - what security issues?

Dan Cross

unread,
Mar 12, 2014, 3:16:01 PM3/12/14
to Constantine Vass, golang-nuts, self-...@gyepi.com
On Wed, Mar 12, 2014 at 2:47 PM, Constantine Vass <ths...@gmail.com> wrote:
A clean machine port 80 serving a static web site - what security issues?

The underlying issue dates back to the introduction of TCP/IP into Unix.

In those days, getting access to the Internet was kind of a big deal and it was thus assumed that the hosts running on the network could be trusted.  Having root access on those hosts was also kind of a big deal.  However, the Berkeley people (or maybe the BBN people) realized that they had untrusted users on the hosts (e.g., students who had access to the machine, but not root access), even if the hosts themselves were trusted.  Thus arose the need for some system to establish the trustworthiness of network services.

The hack they came up with was to unilaterally declare TCP and UDP ports below than 1024 "trusted": a program could only bind() a socket to those ports if it were being run by the superuser (aka, "root") on the host in question.  Thus, an undergraduate logging into the Berkeley CS VAX couldn't notice that, e.g., the telnet server wasn't running and start one up on port 23 (and thus harvest passwords) because (presumably) that student didn't have root access on the machine.  Most services were running on low-numbered ports, so this more or less worked to prevent untrusted users from starting up trusted services.

Incidentally, this was how the 'r' commands worked: the *client* was setuid root and bound the source port for a connection to some low-valued port number and then sent data about what user was running the command to the remote host.  That host in turn verified that the source port of the connection was less than 1024, and assumed that the data it received could be trusted.  Of course, there are any number of ways to subvert that sort of scheme, but in the early days of the TCP/IP Internet, it more or less worked.

The vestige of requiring root access to bind to low-numbered (so called "privileged") ports persists, even though everyone effectively has root access on their own machine now anyway.  But having administrative access to your own machine is different from running everything as root on your own machine; that's the issue here.  In particular, the "security issue" is that your program has to run as the root user, even though that really shouldn't be required just to serve some static files.  Security-wise, a better approach would be to define a completely unprivileged user that could read the files you wanted to serve, but not write anything (except maybe a log file or something) and run your server as that user, with the server bound to an "unprivileged" port (and perhaps a firewall rule or small proxy program to redirect traffic from port 80 to the actual serving port).  Then, IF there's a bug in the server that allows a remote attacker to e.g., run code on your machine, at least it isn't running as the superuser.  It's a way of proactively containing damage.  As Gyepi said, it's about limiting exposure and compartmentalizing.

        - Dan C.

Constantine Vass

unread,
Mar 12, 2014, 3:23:55 PM3/12/14
to golan...@googlegroups.com, Constantine Vass, self-...@gyepi.com
Thank you. From your experience - what bug in Golang's ListAndServe can allow an attacker to
run a code on the server? Do you have a practical example?

egon

unread,
Mar 12, 2014, 3:41:44 PM3/12/14
to golan...@googlegroups.com, Constantine Vass, self-...@gyepi.com


On Wednesday, March 12, 2014 9:23:55 PM UTC+2, Constantine Vass wrote:
Thank you. From your experience - what bug in Golang's ListAndServe can allow an attacker to
run a code on the server?

I think you are still missing the point... security comes from precaution and assuming every piece of code has some sort of exploit in them... and you also assume that you made a mistake setting up some part of the security.
 
Do you have a practical example?

Let's say you accidentally serve a file where some passwords are stored.

+ egon

Constantine Vass

unread,
Mar 12, 2014, 3:47:43 PM3/12/14
to golan...@googlegroups.com, Constantine Vass, self-...@gyepi.com

>Let's say you accidentally serve a file where some passwords are stored.
I see - this is common sense. We can assume these precautions are taken.

If we focus only on the coding and assume the system security considerations 
are OK let see this code":
package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":80", nil)
}

What security risk we have here and how it can be prevented? 

egon

unread,
Mar 12, 2014, 4:07:10 PM3/12/14
to golan...@googlegroups.com, Constantine Vass, self-...@gyepi.com


On Wednesday, March 12, 2014 9:47:43 PM UTC+2, Constantine Vass wrote:

>Let's say you accidentally serve a file where some passwords are stored.
I see - this is common sense. We can assume these precautions are taken.

If we focus only on the coding and assume the system security considerations 
are OK let see this code":
package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":80", nil)
}
I don't know. If I knew, I would've reported it and it probably would have been fixed by someone. 

What security risk we have here and how it can be prevented? 

Hmm... best I can come up with is... let's say you do a huge request to the server, which has little memory, the server crashes, because some driver wanted more memory, couldn't get it and took everything else down... The server may have some mode that allows temporarily remote connection at start-up, of course with a password... (but that may also have some bug in it)...

(But for some reason, I believe that "http" already has taken precaution against too large requests...)

Of course, there could be some 0-day in the runtime.

Constantine Vass

unread,
Mar 12, 2014, 4:21:32 PM3/12/14
to golan...@googlegroups.com, Constantine Vass, self-...@gyepi.com
As I suspected it is more academic. 

If we want to be more pragmatic - you never can be sure you have enough security,
we take the necessary measures but still we have the question of "trusting trust" as I see
this in the paper. 

If we are talking about trust - last week I bought mac-mini-server which I see its default settings 
are light years ahead in security compared to what there was in Ubuntu by default.

The questions I have now is because of this more tightened security in mac-mini-server - I cannot 
do things which I made before under Ubuntu - which is OK if I follow Apple's rules to make 
it work right.

Rodrigo Kochenburger

unread,
Mar 12, 2014, 4:33:15 PM3/12/14
to Constantine Vass, golan...@googlegroups.com, self-...@gyepi.com
Running your app as root in any system (Mac or Linux) is unsafe. 

No one said that OSX is insecure, only that linux is way more used for deployments and is probably more battle-tested on different scenarios which can lead to bugs being found and fixed faster.

In summary: You need root privileges to be able to bind to lower ports in most *nix systems and if you do make sure that after binding, the process gets demoted to a lower privilege user. In OSX your application needs to be signed using a key that you can generate yourself using the keychain.

- RK


Constantine Vass

unread,
Mar 12, 2014, 4:39:29 PM3/12/14
to golan...@googlegroups.com, Constantine Vass, self-...@gyepi.com
Thank you - this is correct. 


> In OSX your application needs to be signed using a key that you can generate yourself using the keychain.

I am more familiar with iOS for which I have a developer account. Do I need one for OS X to be able to 
do more and possibly these security questions to be easily solved ?

Lars Seipel

unread,
Mar 13, 2014, 6:45:35 AM3/13/14
to Bryan Whitehead, Constantine Vass, golang-nuts
On Tue, Mar 11, 2014 at 01:46:32PM -0700, Bryan Whitehead wrote:
> All ports below 1024 (possibly more) are privileged ports, your app must be
> run as root.
>
> OR just run and listen to on port 6443 and add some iptables rules to DNAT
> request to 443->6443.

There's another way(*) and AFAIK launchd supports it: the init system
(or some dedicated service supervisor program) sets up the socket for
you and passes/inherits you the file descriptor which you then just use.

Constantine, I'd suggest you look that up. Read the documentation. It's
there for a reason.

Lars

(*) in fact, lots of

Constantine Vass

unread,
Mar 13, 2014, 1:00:04 PM3/13/14
to golan...@googlegroups.com, Bryan Whitehead, Constantine Vass
In my former Ubuntu setup I used runit process supervisor. In runit
documentation there is explanation how to run it n OS X till version 10.6.
Could not make it run under OS X Mavericks. There are lot documentations
to read but some of them are not up to date.

Matt Silverlock

unread,
Mar 13, 2014, 7:37:50 PM3/13/14
to golan...@googlegroups.com, Bryan Whitehead, Constantine Vass
1. Run nginx on port 80 (launch it as root but ensure it runs under it's own user) — if you install it via Homebrew this is taken care of for you.
2. Reverse proxy to your Go application listening on an unprivileged port (i.e. 8000)
3. Use supervisord/runit/monit/etc. to start your Go application on launch and run it as a specific user (i.e. appuser) and restart it when it crashes

This avoids the need to run your application—which is arguably the biggest security risk as it directly deals with either user input via the web or your own programming errors—as root. You almost never want to do that (ever).

Take a look at this sample/excerpt from a nginx config for the reverse proxy part: https://gist.github.com/elithrar/77ee6746104b900e866c and this one for a sample supervisor.conf file: https://gist.github.com/elithrar/9539414

Dan Cross

unread,
Mar 16, 2014, 12:07:08 PM3/16/14
to Constantine Vass, golang-nuts, self-...@gyepi.com
On Wed, Mar 12, 2014 at 3:23 PM, Constantine Vass <ths...@gmail.com> wrote:
Thank you. From your experience - what bug in Golang's ListAndServe can allow an attacker to
run a code on the server? Do you have a practical example?

I don't know, and no I don't have a practical example.  In fact, I am unaware of any such bugs.  But just because I am unaware of such bugs doesn't mean that they don't exist.  And conversely, merely being aware of any that DO exist misses the point: all other things being equal, it's better to run servers that don't need root access as some user other than root.  I may not know of any bugs in Go's http server implementation, but I do have 20+ years of practical examples of unintended security consequences in widely-used programs which have led me to believe that it's best not to run services as root unless they really do need to be run as root.

On Wed, Mar 12, 2014 at 4:21 PM, Constantine Vass <ths...@gmail.com> wrote:
As I suspected it is more academic. 

Unfortunately, not really.

People figured out a long time ago that this is just good security practice, because it's the bugs that you are unaware of that are really dangerous and we try to guard against those with defense in depth strategies like limiting the privileges that services are run with: precisely what folks are telling you to do here.

People figured that out by witnessing time and again really serious security problems in real programs; things people just had not anticipated before.  Even worse, we find entire *classes* of problems that people didn't anticipate becoming security issues years after the fact, and every time that happens, there's a spat of real-world breakins and so forth that result until (most) of the issues of that class are cleaned up, then the next class comes along.

And even more unfortunately, the Internet has become a mean place.  People can, and will, attempt to exploit you and your services, just because they can.  So if you have something exposed to the public Internet, one had best follow good security practice.
 
If we want to be more pragmatic - you never can be sure you have enough security,
we take the necessary measures but still we have the question of "trusting trust" as I see
this in the paper. 

Yes, and one of those measures is not running a program as root unless it actually needs to be run as root.  :-)

If we are talking about trust - last week I bought mac-mini-server which I see its default settings 
are light years ahead in security compared to what there was in Ubuntu by default.

Correction: as far as you know.  The whole point of not running things as root is that you are anticipating the unknown.  There was a bug in SunOS 4 whereby an attacker could obtain root access by (in part) writing a FORTRAN program that divided a floating point number by zero; I'm pretty sure no one anticipated that, and as I recall, the details had to do with the relevant signal handler running in a kernel context that gave access to superuser privileges; had someone thought to Not do that, the bug could have been avoided.

The questions I have now is because of this more tightened security in mac-mini-server - I cannot 
do things which I made before under Ubuntu - which is OK if I follow Apple's rules to make 
it work right.

Here's a simple solution: OS X comes with the PF firewall.  Add the following rule to /etc/pf.conf:

match in proto tcp from any to me port 80 rdr-to 127.0.0.1 port 8080

Then modify your program  to bind to 127.0.0.1:8080.  Now, you can run it as whoever you want, and you're good to go.

        - Dan C.

Constantine Vass

unread,
Mar 17, 2014, 1:38:11 PM3/17/14
to golan...@googlegroups.com, Constantine Vass, self-...@gyepi.com
Dan,

You shared very valuable information. i've been proactive and got rid of root already.

I added Nginx at the front and use it as reverse parodying 80->8080, 433->8443.

>"match in proto tcp from any to me port 80 rdr-to 127.0.0.1 port 8080"
I tried with firewall too. Do I need that if I am using Nginx?
Message has been deleted

Constantine Vass

unread,
Mar 17, 2014, 1:52:56 PM3/17/14
to golan...@googlegroups.com, Bryan Whitehead, Constantine Vass
I am resending my post with a little corrections, was too quick to click "submit".

You guys have been very helpful. Thanks a lot.

I've been proactive and tested with PF and then Nginx.
With Nginx the setup was easy to understand and quick to implement.
What I like about Nginx after researching I see it is independent from 
the kernel and that is how it achieves this good speed. Not sure about PF - 
if it is using the kernel. If it uses it it would slow down the speed significantly.

1) 80->8080, 443->8443
2) moved the https thing to Nginx, now all Golang code is 
using http internally on higher numbered ports.
3) tried to use "runit" (I was using it in Ubuntu server and made it work then) but I am 
having issues to make it run under OS X Mavericks. Much easier is to use "launchd".
Easier to control. Any considerations against "launchd"?

This setup is working very well, I tested it already. 

Two questions:
1) I am looking for good load testing tool. What do you recommend?

2) Do I need PF to control the 80->8080, 443->8443 or leave Nginx to do it?

Thanks,
--Constantine

Dan Cross

unread,
Mar 17, 2014, 2:00:42 PM3/17/14
to Constantine Vass, golang-nuts, self-...@gyepi.com
On Mon, Mar 17, 2014 at 1:38 PM, Constantine Vass <ths...@gmail.com> wrote:
Dan,

You shared very valuable information. i've been proactive and got rid of root already.

Good to go!

I added Nginx at the front and use it as reverse parodying 80->8080, 433->8443.

A reverse proxy will do it.

>"match in proto tcp from any to me port 80 rdr-to 127.0.0.1 port 8080"
I tried with firewall too. Do I need that if I am using Nginx?

No, you don't need that if you are using nginx.  The reverse is also true: if you do the firewall thing, you don't need nginx.  Personally, I prefer this latter way as nginx is just another moving part that is (mostly) unnecessary.

I'm afraid this is drifting rather far from Go related topics.  If you need any other help, shoot me an email off-list.  Best of luck!

        - Dan C.


Reply all
Reply to author
Forward
0 new messages