1

I have a binary that is SUID which I can currently use a buffer overflow exploit to obtain an elevated EUID shell.

However I haven't worked much with changing IDs through shellcode, and the file I need to access requires me to have a GID equal to the EUID I have obtained. However, after obtaining my shell, my GID stays the same as previously.

My question: What system calls or shellcode do I need to execute to elevate my GID to be equal to my EUID when the shell is spawned?

Also: So far I have tried setregid and setegid system calls in shellcode before spawning the shell, however both return "-1" when using a GID that is not already my unprivileged GID.

Thank you.

3
  • Is it suid root? Commented Apr 22, 2018 at 23:59
  • 1
    No, it is suid another non-privileged user. I did some more research and I'm not sure it's even possible to change GID without a root account.. Commented Apr 23, 2018 at 0:47
  • That is correct. I posted an answer to that effect. Commented Apr 23, 2018 at 1:02

1 Answer 1

0

According to setgid(2), the syscall will fail unless the calling process is privileged:

   EPERM  The calling process is not privileged (does not have the
          CAP_SETGID capability), and gid does not match the real group
          ID or saved set-group-ID of the calling process.

Unless you are running with the correct capabilities (specifically CAP_SETGID, provided by root), you cannot change your GID to a value which is not your real or saved GID. This limitation applies to any syscall that changes the GID. The manual page on credentials(7) is extremely helpful.

You can actually see where this is done in the kernel:

SYSCALL_DEFINE1(setgid, gid_t, gid)
{
    struct user_namespace *ns = current_user_ns();
    const struct cred *old;
    struct cred *new;
    int retval;
    kgid_t kgid;

    kgid = make_kgid(ns, gid);
    if (!gid_valid(kgid))
        return -EINVAL;

    new = prepare_creds();
    if (!new)
        return -ENOMEM;
    old = current_cred();

    retval = -EPERM;
    if (ns_capable(old->user_ns, CAP_SETGID))
        new->gid = new->egid = new->sgid = new->fsgid = kgid;
    else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid))
        new->egid = new->fsgid = kgid;
    else
        goto error;

    return commit_creds(new);

error:
    abort_creds(new);
    return retval;
}

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.