{"id":12188,"date":"2025-10-14T02:00:00","date_gmt":"2025-10-14T06:00:00","guid":{"rendered":"https:\/\/www.both.org\/?p=12188"},"modified":"2025-10-11T20:35:12","modified_gmt":"2025-10-12T00:35:12","slug":"a-caution-about-using-sudo","status":"publish","type":"post","link":"https:\/\/www.both.org\/?p=12188","title":{"rendered":"A caution about using sudo"},"content":{"rendered":"<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"javascript:void(0)\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"\" data-post-id=\"12188\" data-trigger-type=\"like\" data-restriction=\"cookie\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">    <\/span>\r\n<\/div><\/div>\n<p>The <strong>sudo<\/strong> program is an excellent way to extend &#8220;administrator&#8221;-like access to users who are not otherwise system administrators. In fact, modern Linux desktop distributions assume that at least one user should have an &#8220;administrator&#8221;-like role. When using a Linux system this way, a user can run certain &#8220;system&#8221; level commands as root, using their normal user account.<\/p>\n\n\n\n<p>For example, on my Fedora Linux desktop system, I am this &#8220;administrator&#8221;-like person. I can run <em>any<\/em> command as root, simply by using the <strong>sudo<\/strong> command. I use this rarely, but it sometimes comes in handy. For example, while I can use a desktop package manager to install new programs and applications, I&#8217;m familiar enough with the Linux command line that I prefer to do it &#8220;by hand.&#8221; To install the <strong>pngcrush<\/strong> package, which can optimize a PNG graphic file for size, I just type this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo dnf install pngcrush<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"using-sudo-on-a-server\">Using sudo on a server<\/h2>\n\n\n\n<p>On a server where you need to provide other non-&#8220;administrators&#8221; with the ability to run certain commands as root, you can edit the <code>\/etc\/sudoers<\/code> file to specify <em>who can run which commands<\/em>. You can even limit the <em>options<\/em> that these users can give to these commands, such as only allowing certain users to mount the CD-ROM drive, as though they were root. The <code>sudoers<\/code> file contains examples of how to limit these kinds of commands.<\/p>\n\n\n\n<p>But you need to be <em>very careful<\/em> about how you grant this access, and what commands they have access to run. Here&#8217;s an example that demonstrates what I mean:<\/p>\n\n\n\n<p>A friend of mine used to work for a large company, as an <em>applications administrator<\/em>. Like many organizations, this company split up roles on the server: the systems administrators supported the hardware and operating system, the database administrators maintained the databases, and the application administrators ran the applications. The applications needed to be launched as root, so the systems administration team set up <strong>sudo<\/strong> commands for them.<\/p>\n\n\n\n<p>For this example, let&#8217;s say the application was installed in <code>\/opt\/___<\/code>, which was &#8220;owned&#8221; by the application administrator team. Like good Linux users, the applications administrators set up scripts to automate tasks for them. For example, they had a script that acted like a &#8220;system&#8221; script, so they could start the application by running a command like <code>\/opt\/___\/bin\/app<\/code> with an option like <strong>start<\/strong> or <strong>stop<\/strong> or <strong>restart<\/strong>. You can imagine a script that looked like this: (I&#8217;ve replaced any actual commands with an <strong>echo<\/strong> command, because I&#8217;m only demonstrating it)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\n# run this with 'sudo app start' or 'sudo app stop'\n\ncase \"$1\" in\nstart)\n  echo 'starting app server..'\n  ;;\nstop)\n  echo 'stopping app server..'\n  ;;\nrestart)\n  \"$0\" stop &amp;&amp; \"$0\" start\n  ;;\n*)\n  echo \"usage: $(basename $0) start|stop|restart\"\n  ;;\nesac<\/code><\/pre>\n\n\n\n<p>The system administrators set up an <code>\/etc\/sudoers<\/code> rule that allowed the application administrators to only run this script with <strong>start<\/strong> or <strong>stop<\/strong> or <strong>restart<\/strong>, with a rule that looked like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>%apps ALL=\/opt\/___\/bin\/app start, \/opt\/___\/bin\/app stop, \/opt\/___\/bin\/app restart<\/code><\/pre>\n\n\n\n<p>With this rule, any member of the <code>apps<\/code> group (the application administrators) could start the application by typing this command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo \/opt\/___\/bin\/app start\nstarting app server..<\/code><\/pre>\n\n\n\n<p>..or stop the application with this command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo \/opt\/___\/bin\/app stop\nstopping app server..<\/code><\/pre>\n\n\n\n<p>..or restart the application (such as when the application needs to be &#8220;refreshed&#8221;) by typing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo \/opt\/___\/bin\/app restart\nstopping app server..\nstarting app server..<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"a-security-issue\">A security issue<\/h2>\n\n\n\n<p>Using <strong>sudo<\/strong> made it easy to &#8220;draw a line&#8221; between the systems administrator and the application administrator roles. The applications team could manage the application without involving the systems team, especially because the applications team &#8220;owned&#8221; the <code>\/opt\/___<\/code> directory on the server.<\/p>\n\n\n\n<p>But do you see the security gap in this script? Here&#8217;s what happened:<\/p>\n\n\n\n<p>One night, the application crashed hard. My friend was the application administrator on-call person, so he was paged by the automatic monitoring system. I don&#8217;t recall exactly what the problem was that night (it was years ago) but let&#8217;s say the issue was that the <code>\/opt<\/code> filesystem had filled up. Through some investigation, my friend found that the &#8220;temporary&#8221; area in an unrelated <code>\/opt\/temp<\/code> directory was full. This directory was well known to only contain &#8220;interim&#8221; files, and deleting the files in this &#8220;temporary&#8221; area (especially file names starting with &#8220;tmp&#8221;) was safe to do.<\/p>\n\n\n\n<p>But the system administrator on-call person wasn&#8217;t responding to calls. No one with the access to clean up the <code>\/opt\/temp<\/code> directory was available to do this quick task.<\/p>\n\n\n\n<p>My friend realized <em>they could run the script as root<\/em> using <strong>sudo<\/strong>, and <em>they could edit the script<\/em>. So they made a quick edit to the <code>\/opt\/___\/bin\/app<\/code> script to clean up the <code>\/opt\/temp<\/code> directory. The edit might have looked like this: (again, I&#8217;ll use the <strong>echo<\/strong> command instead, because I&#8217;m only demonstrating it)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\n# run this with 'sudo app start' or 'sudo app stop'\n\necho 'cd \/opt\/temp ; rm tmp.*'\nexit\n\ncase \"$1\" in\nstart)\n  echo 'starting app server..'\n  ;;\nstop)\n  echo 'stopping app server..'\n  ;;\nrestart)\n  \"$0\" stop &amp;&amp; \"$0\" start\n  ;;\n*)\n  echo \"usage: $(basename $0) start|stop|restart\"\n  ;;\nesac<\/code><\/pre>\n\n\n\n<p>This modification to the script adds a command to delete temporary files in the <code>\/opt\/temp<\/code> directory, then immediately exit the script. With this edit, my friend ran the script with one of the options allowed in the <code>\/etc\/sudoers<\/code> rule file, such as <strong>stop<\/strong>, and the system cheerfully deleted the other temporary files:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo \/opt\/___\/bin\/app stop\ncd \/opt\/temp ; rm tmp.*<\/code><\/pre>\n\n\n\n<p>After running this command, my friend removed the two extra lines from the script, returning things to normal.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"security-and-sudo\">Security and sudo<\/h2>\n\n\n\n<p>This demonstrates why it&#8217;s important to be careful about what commands you allow users to run with <strong>sudo<\/strong>. My friend was able to edit the script, so was effectively able to <em>run any arbitrary command as root<\/em>. Fortunately, this was a benign &#8220;abuse&#8221; of <strong>sudo<\/strong>, but imagine if a bad actor had been able to login as an application administrator and made a different change to the script&#8211;such as an edit that transferred system access to an outside agent. That would be a disaster.<\/p>\n\n\n\n<p>This is not a <strong>sudo<\/strong> problem, but a user management issue. In fact, this issue is also noted in the <strong>sudo<\/strong> documentation, such as this note in the <em>sudo<\/em>(8) &#8220;man&#8221; page:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>There is no easy way to prevent a user from gaining a root shell if that user is allowed to run arbitrary commands via <strong>sudo<\/strong>.<\/p>\n\n\n\n<p>\u2026 Running shell scripts via <strong>sudo<\/strong> can expose the same kernel bugs that make set-user-ID shell scripts unsafe on some operating systems.<\/p>\n<\/blockquote>\n\n\n\n<p>One way to avoid the problem I described is <em>do not allow general users to edit the script<\/em>. If the <code>\/opt\/___\/bin\/app<\/code> script were &#8220;owned&#8221; by root and mode <code>500<\/code> (that is, read+execute only by root) then the script could still be executable using <strong>sudo<\/strong>.<\/p>\n\n\n\n<p>The <strong>sudo<\/strong> command is great for controlling access, but take this example as a general caveat about using <strong>sudo<\/strong>: you <em>cannot<\/em> let people edit any script that <strong>sudo<\/strong> lets them run.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This example shows why it is important that users should not be able to edit scripts that they can run with sudo.<\/p>\n","protected":false},"author":33,"featured_media":2700,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":""},"categories":[5,75,89],"tags":[91,261,97],"class_list":["post-12188","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-linux","category-security","category-system-administration","tag-linux","tag-security","tag-sysadmin"],"modified_by":"Jim Hall","_links":{"self":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/12188","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/users\/33"}],"replies":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=12188"}],"version-history":[{"count":5,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/12188\/revisions"}],"predecessor-version":[{"id":12194,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/12188\/revisions\/12194"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/media\/2700"}],"wp:attachment":[{"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=12188"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=12188"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=12188"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}