What are the well-known UIDs? - unix

According to the useradd manpage, UIDs below 1000 are typically reserved for system accounts.
I'm developing a service that will run as its own user. I know that well-known ports can be found in /etc/services.
Is there a place where I can find out what well-known UIDs are out there? I would like to avoid crashing with someone else's UID.

getpwent(3) iterates through the password database (usually /etc/passwd, but not necessarily; for example, the system may be in a NIS domain). Any UID known to the system should be represented there.
For demonstration, the following shell fragment and C code both should print all known UIDs on the system.
$ getent passwd | cut -d: -f3
#include <pwd.h>
#include <stdio.h>
int main() {
struct passwd *pw;
while ((pw = getpwent()))
printf("%d\n", pw->pw_uid);
}
UID 0 is always root and conventionally UID 65534 is nobody, but you shouldn't count on that, nor anything else. What UIDs are in use varies by OS, distribution, and even system -- for example, many system services on Gentoo allocate UIDs as they are installed. There is no central database of UIDs in use.
Also, /etc/login.defs defines what "system UIDs" are. On my desktop, it is configured so that UIDs 100-999 are treated as system accounts, and UIDS 1000-60000 are user accounts, but this can easily be changed.
If you are writing a service, I would suggest that the package installation be scripted to allocate a UID as needed, and that your software be configurable to use any UID/username.

I know this is an old post, but since I am here in 2017, still trying to answer a similar question I thought this additional information was relevant for anyone else in the same position.
The concept of "Well known UIDs" stems back to the early days of unix, before there were multitudes of distributions and unix variants. "Well known" UIDs were considered to be those for system users like adm, daemon, lp, sync, operator, news, mail etc, and were standard across all the various systems in order to avoid uid clashes. These users are still present in modern unix-like operating systems.
Standardising uid's across an organisation is the key to avoiding these problems. As was pointed out in a comment above, these days any uid you choose is likely to be in use 'somewhere', so the best a sysadmin can aim for is to ensure that uid's are standard across all the systems that they maintain, then allocating a new uid for an application becomes simple.
To that end, for many years I have found the post linked below invaluable, and sadly there are not a lot of similar posts on the topic, and what's out there is hard to find.
UNIX/Linux: Analyzing user/group UID/GID conflicts
If you search that blog under the 'uid' tag there are other relevant posts, including a script to automate the process of standardising uid's across multiple hosts under Linux.
This User ID Definition is also an invaluable resource.
The short answer is, that it doesn't really matter which uid's you use, as long as they are unique and standard across your organisation, to avoid clashes.

I'm not sure such a list exists. How about just noting that UID's are in use through the /etc/passwd file, /etc/shadow file, and the NIS global user list, noting what ones are in use? Then use one that isn't!

In Linux, that is configured in /etc/login.defs. Sometimes, when I install a Debian-based system, I change the "uid start" option (I forget its name, I'm not on Linux now) from 1000 to 500 for consistency with the other, Red Hat-y machines.
man login.defs should give you all the info you want.

Related

Ansible - properly encrypting/decrypting and using file content (not YAML)

So I created encrypted key using ansible-vault create my.key.
Then I use it as var:
my_key: "{{ lookup('file','{{ inventory_dir }}/group_vars/my.key') }}"
And then when running my playbook, like this:
- name: Create My Private Key
ansible.builtin.copy:
content: "{{ secrets.my_key }}"
dest: "{{ secrets_key }}"
no_log: true
It does properly create key on remote host and it is then unencrypted. But I'm thinking if this is the right way to do it? Does it unencrypt at the right time and I am not exposing sensitive data where it should not be?
I thought encrypted variables must also have !vault keyword specified. But if I do this for my my_key, I get this error:
fatal: [v14-test]: FAILED! => {"msg": "input is not vault encrypted data. "}
So this got me worried, that file is unencrypted at the wrong time or maybe message is misleading or something.
Is this the right way to do it? Or I should do it differently?
Firstly, a definitive answer as to whether this approach is appropriate, is directly linked to what you want to achieve from encryption. Therefore all the answers here can do is talk about how Vault works and then you can decide if it is right for your requirements.
Fundamentally what you are doing is a 'correct' usage of Ansible Vault, although I have not previously seen it used in quite this workflow (typically I have seen create used for encrypting YAML files of vars).
Using your method, your secret is turned into ciphertext and stored in my.key (which can be confirmed by using basic text tools such as cat, less or more). You will see the first line of the file, contains a bunch of metadata that allows Ansible to understand the file contents and decrypt on demand.
At runtime, Ansible will then use the password/key for the encrypted file (accessed through a number of methods) to decrypt the file contents into plain text and then store it in the variable my_key for use during the play.
A non-exhaustive list of things to consider when determining if Ansible Vault is the right approach for you:
Ansible Vault encryption is purely designed to protect secrets at rest (i.e. when they are stored on your hard disk)
At run time, the secrets are converted into plain text and treated like any other variable/string data, however the file on disk still contains ciphertext so the plaintext is only accessible within the running Ansible process (i.e. on a multi-user system, at no point can anybody view the plaintext simply by looking inside the my.key file. However, depending on their level of access, skills and what your Ansible tasks are doing, they may be able to access the plaintext from the running process.)
Given inside the process the data is just plain text, it is vulnerable to leakage (for example by writing the contents out into a log file - checkout the Ansible no_log option)
At run time, Ansible needs some way to access the key necessary to decrypt the ciphertext. It provides a variety of methods, including prompting the user, accessing it from a file stored on disk, accessing it from an Env var, using scripts/integrations to pull it from another secrets mgmt tool. Careful thought needs to be given about which option is chosen, relative to what you are looking to achieve from the encryption (e.g. if your goal is to protect your data in the event that your laptop gets stolen, then storing the key in a file on the same system, renders the whole operation pointless). Quite often, with more sophisticated methods, you can still end up in a 'chicken and egg' situation, once more relative to what your goal from using encryption is
I might be talking complete cobblers or be a nefarious individual trying to sow disinformation, so read the docs thoroughly if the value of the secrets if significant to you :)
Unfortunately there is no getting away from generally good security is harder to achieve than the illusion of good security :|

How to configure Oracle 11g to launch sqlplus?

On a RedHat 6 server, a third party application requires to be root to run and needs access to sqlplus. I have a running database, I can run sqlplus as user 'oracle'. When logged in as user root, 'sqlplus usr/pwd#dbname' works as expected. The trouble is that this agent needs to run sqlplus with no parameters and it always returns ORA-12546: TNS:permission denied.
I've read a dozen times that enabling root to launch Oracle is a security issue but I really have no other choice.
Running Oracle 11.2.0.1.0.
Any help will be much appreciated as I've googled for 2 days with no success.
From the documentation, ORA_12546 is:
ORA-12546: TNS:permission denied
Cause: User has insufficient privileges to perform the requested operation.
Action: Acquire necessary privileges and try again.
Which isn't entirely helpful, but various forum and blog posts (way too many to link to, Googling for the error shows a lot of similar advice) mention permissions on a particular part of the installation, $ORACLE_HOME/bin/oracle, which is a crucial and central part of most of the services.
Normally the permissions on that file would be -rws-r-s--x, with the file owned by oracle:dba, and this error can occur when the word-writable flag - the final x in that pattern - is not set. Anyone in the dba group will still be able to execute it, but those outside will not.
Your listener seems to be fine as you can connect remotely, by specifying #dbname in the connect string. The listener runs as oracle (usually, could be grid with HA, RAC or ASM) so it is in the dba group and can happily hand-off connections to an instance of the oracle executable.
When you connect without going via the listener, you have to be able to execute that file yourself. It appears that root cannot execute it (or possibly some other file, but this is usually the culprit, apparently), which implies the world-writable bit is indeed not set.
As far as I can see you have three options:
set the world-writable bit, with chmod o+x $ORACLE_HOME/bin/oracle; but that opens up the permissions for everyone, and presumably they've been restricted for a reason;
add root to the dba group, via usermod or in the /etc/group; which potentially weakens security as well;
use SQL*Net even when you don't specify #dbname in the connect string, by adding export TWO_TASK=dbname to the root environment.
You said you don't have this problem on another server, and that the file permissions are the same; in which case root might be in the dba group on that box. But I think the third option seems the simplest and safest. There is a fourth option I suppose, to install a separate instant client, but you'd have to set TWO_TASK anyway and go over SQL*Net, and you've already ruled that out.
I won't dwell on whether it's a good idea to run sqlplus (or indeed the application that needs it) as root, but will just mention that you'd could potentially have a script or function called sqlplus that switches to a less privileged account via su to run the real executable, and that might be transparent to the application. Unless you switch to the oracle account though, which is also not a good idea, you'd have the same permission issue and options.

Risk if a registrant picks a username that matches a unix command?

In my app I ask users to register using a unique name. The app creates a directory for them with that name that they then can work with, saving files, etc.
I hadn't really thought about screening for other than alpha-numeric for the name. However, I ran across a thread somewhere than said to make sure not to create directory names that match a unix command name.
Is this a legitimate risk? If so, how might one programmatically screen for such an occurrence? I'm also curious how such a scenario might play out to illustrate the problem (exploit?). That last part is academic interest only, of course.
Generally, it doesn't matter(has no obvious security risk). Most softwares, for example shell, search a unix command based on some enviroment variables(like PATH). So even if your created directory matches a unix command like "cd", it can only be used as a parameter to other unix command, like cd cd.
However, if another application search the unix command based on other approaches like searching some directories, it may lead to security breaches.
The only way I can think of that being a risk is if you're going to turn around and process those user names through command-line functions. You would want to be careful to escape the user names anywhere that they could be interpreted as a command...though off the top of my head, with strictly alphanumeric user names, you'd have to go to a lot of trouble to run into such a risk.
If you decided anyway that you wanted to ensure that the username didn't match an application on the path of the creating process, you could shell out from whatever your app environment is, and evaluate the result of which $prospectiveUsername. If it returns anything other than an empty string, you know that the username is an application on the process's path.
NOTE: In the above scenario, make sure you sanitize the username before calling out to the shell command. Otherwise, you do run security risks, if e.g. the user decides to enter her username as "janedoe; rm -rf /".

A usage of setuid?

I read a Powerpoint slide recently, and can't get a clear concept about the usage of setuid.
Here is the content of the slide.
Setuid example - printing a file
Goals
Every user can queue files
Users cannot delete other users' files
Solution
Queue directory owned by user printer
Setuid queue-file program
Create queue file as user printer
Copy joe's data as user joe
Also, setuid remove-file program
Allows removal only of files you queued
User printer mediated user joe's queue access.
Here are my questions.
I don't have a clear ​understanding​ how to solve this problem by "setuid".
First, if the file is created by user printer, how does user joe copy data to a file owned by printer. Does it have some certain right to this file.
Secondly, how to identify the relationship between you and the file you queued.
Does the file's state show something, but the file is owned by printer, which can only be changed by root. Does it have something to do with the file's gid? If so, other users' gid may also be related to this file.
Does the file's context show something about who queued it?
My questions are a mess, and I really don't have a clear concept about the solution.
Let's assume that the files are to be stored in /var/spool/pq directory; the permissions on the directory printer:printgrp:2700 (owner printer, group printgrp, mode 2700 - read, write, execute for owner only, and the SGID bit set on the directory means all files created in it will belong to group printgrp).
Further, we assume that the print queuing program, pq, has permissions printer:printgrp:4511 (setuid printer, anyone can execute it, but only printer or root can look at it).
Now, suppose Joe runs pq /home/joe/file, and the permissions on the file are joe:staff:600 (only Joe can read or write to the file). Joe's umask is set to 022 (though this file has more restrictive permissions than are implied by the umask).
When the program runs, the real UID of the process is joe, but the effective UID is printer. Since there is no need for setgid operation here, both the real and effective GID are staff. Joe's auxilliary groups list does not include printgrp.
Note that it is the effective UID and GID of a process that control its access to files. On his own, Joe cannot see what jobs are in the printer queue; the directory permissions shown don't even allow him to list the files, or access the files in the directory. Note that the converse applies; on its own, the printer user (or the pq program running as that user) cannot access Joe's file.
The pq program can create files in the printer queue directory; it will probably create two files for this request. One will be a control file, the other will be a copy of the file to be printed. It will determine a job number by some mechanism (say 12345) and it might create and open two files for writing (with restrictive permissions - 0600 or even 0400):
/var/spool/pq/c.12345 - the control file
/var/spool/pq/d.12345.1 - the first (only) data file
It should then reset its effective UID to the real UID, so it is running as Joe. It can then open the file Joe asked to be printed, and copy it to the data file. It can also write whatever information it deems relevant to the control file (date, time, who submitted the request, the number of files to be printed, special printing options, etc). When it closes those files, Joe is no longer able to access them. But the program was able to copy Joe's file to its print queue.
So, that addresses questions 1 (permissions) and 2 (control information), and also 4 (control information again).
Regarding question 3, root is always a wild card on Unix-like systems because can do anything that he wants. However, as suggested by the rest of the answer, the control file contains information about the print request, including (in particular) who submitted it. You can use setgid programs instead of setuid programs; these work in analogous ways. However, under the system I postulated, the group permissions essentially didn't come into the picture. The pq program set the permissions on the control file and data file such that the group can't read it, and the directory permissions also deny group access.
We can postulate two more programs:
pqs - printer queue status
pqr - printer queue remove
These programs would also be setuid printer. The pqs program can read the control files in the directory and list pertinent information from them. The pqr program can read the control files to ensure that when Joe submitted job 12345 when he requests the removal of job 12345. If the program is satisfied, then it can delete the files.
Separately from these user-invoked programs, there would also be a daemon program (conventionally named pqd in this system) that would be kicked into action by pq if it is not already running. It would be responsible for reading the control files in the directory, and using that information to actually print the data files to the relevant printer. The details of how different printers and different data formats are handled are a problem for the daemon to deal with. The daemon too will run with printer privileges, and printer will have been given access to the printer devices (for locally attached printers) or configured to communicate over the network with a protocol such as IPP (Internet Printer Protocol). Joe probably won't be able to use the printer devices directly.
Note that the setuid programs have powers that Joe does not have. They must be written carefully to ensure that Joe cannot abuse those extra powers. Any setuid program is somewhat dangerous; a setuid root program can be lethal. In general, setgid programs are less dangerous. However, for both types of program, great care is required in the writing of such programs.

How can I pass a password to the "su" command?

I have a program that is going to take a password as input and then do a shell execute to perform a "su" (switch user) command in UNIX. However, I don't know how to pass the password variable to the UNIX su command. The language I have to use for this is pretty limited (UniBasic).
Any ideas?
Well, the best way to do that would be a setuid-root binary that ask for the password then execute whatever command is needed but it requires knowledge you say not to possess. I'd advise in looking at sudo(1) instead.
You could ssh to localhost as another user to execute whatever command you want. Or, use sudo and edit /etc/sudoers such that sudo does not ask for a password. However, there could be security implications.
EDIT: Please let me know why when you vote it down. My answer may not be perfect but at least it works. I do that myself for some licensed software that can only be run under a weird user name.
You do not want to specify the password as a command-line argument. Not so much because of #unwind's answer (scripts could be made private) but because if someone runs a list of processes, you could see the command argument and hence the password in question.
The version of su I have on my Linux server does not support such an option. I checked sudo, but it doesn't either. They want to do the prompting themselves, to ensure it's done in a safe manner and (I guess) to discourage people from putting passwords verbatim in scripts and so on.
You could also look at the 'expect' utility that was designed to script complex user inputs into a programs that weren't flexible enough to receive this input from places other than stdin.

Resources