Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CVE-2014-3537: Insufficient checking leads to privilege escalation #4450

Closed
michaelrsweet opened this issue Jul 3, 2014 · 11 comments
Closed
Milestone

Comments

@michaelrsweet
Copy link
Collaborator

Version: 1.7.3
CUPS.org User: twaugh.redhat

An HTTP GET request on resources beginning "/rss/" will serve the corresponding file from /var/cache/cups/rss/. This directory has group lp write permission.

The cupsd service runs as root, and follows symlinks when serving files.

A user in the "lp" group is able to create a symlink in /var/cache/cups/rss/ pointing to a local target file which they are not able to read, and can gain read access by fetching the corresponding "/rss/" resource.

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: mike

This is not exploitable out-of-the-box as we disable the web interface by default.

Once enabled, someone with "_lp" group membership could create a symlink pointing to a sensitive file, and then retrieve the contents of that file using a HTTP GET request to the local cupsd.

The fix will be to lstat the file to be served and then disallow any symlinks (404 response - not found).

(I'm not going to get fancy with this and allow symlinking to world-readable files, we just won't allow it...)?

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: mike

Proposed patch is attached. Basically, if a file is a symlink or does not have world read permissions, don't try to serve it up.

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: twaugh.redhat

Thanks for the patch.

It's actually not just information disclosure, as a group lp user can symlink to /var/run/cups/certs/0 and use that to gain '@System' group privilege with cupsd. I've updated the bug title.

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: mike

OK, so you're good with the patch? I'd like to release 1.7.4 next week (say, July 10th) if you have no objection.

I'm not sure if any OS's put any user other than "lp" in the "lp" group; I know on OS X the only way you'd be able to take advantage of this is to escalate to root first, making this bug less of an issue (why bother if you have root, right?)

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: twaugh.redhat

Yes, the patch looks good to me.

I don't know whether there are generally any other users in the lp group, but of course if there is any code execution exploit in a filter, that code would run in group lp.

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: twaugh.redhat

I'm checking whether there are objections with releasing this on July 10th...

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: twaugh.redhat

I've heard no objections to July 10th.

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: twaugh.redhat

Acknowledgment:
This issue was discovered by Francisco Alonso of the Red Hat Security Response Team.

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: mike

OK, July 10th it is.

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: mike

Fixed in Subversion repository.

@michaelrsweet
Copy link
Collaborator Author

"str4450.patch":

Index: scheduler/client.c

--- scheduler/client.c (revision 11982)
+++ scheduler/client.c (working copy)
@@ -2961,7 +2961,7 @@
if ((ptr = strchr(filename, '?')) != NULL)
*ptr = '\0';

  • if ((status = stat(filename, filestats)) != 0)

  • if ((status = lstat(filename, filestats)) != 0)
    {
    /*

  • Drop the language prefix and try the root directory...
    @@ -2973,14 +2973,35 @@
    if ((ptr = strchr(filename, '?')) != NULL)
    *ptr = '\0';

  •  status = stat(filename, filestats);
    
  •  status = lstat(filename, filestats);
    

    }
    }

    /*

  • * If we're found a directory, get the index.html file instead...

    • If we've found a symlink, 404 the sucker to avoid disclosing information.
      */
  • if (!status && S_ISLNK(filestats->st_mode))

  • {

  • cupsdLogClient(con, CUPSD_LOG_INFO, "Symlinks such as "%s" are not allowed.", filename);

  • return (NULL);

  • }

  • /*
  • * Similarly, if the file/directory does not have world read permissions, do
  • * not allow access...
  • */
  • if (!status && !(filestats->st_mode & S_IROTH))
  • {
  • cupsdLogClient(con, CUPSD_LOG_INFO, "Files/directories such as "%s" must be world-readable.", filename);
  • return (NULL);
  • }
  • /*
  • * If we've found a directory, get the index.html file instead...
  • _/

if (!status && S_ISDIR(filestats->st_mode))
{
/_

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant