UNIX security programming and library function description

xiaoxiao2021-03-06  84

UNIX security programming and library function description

UNIX systems provide a number of subroutines for programmers, which can access various security properties. Some information subroutines, return file properties, actual and valid UID, GID, etc. Some subroutions can change file properties Some of .uid, GID, etc. have some handleave files and group files, and some completion of encryption and decryption.

This article mainly discusses the security of system programs, standard C library subroutines, how to write secure C procedures and introduce program design from root (subroutines that can only be called by root).

System subscriber

(1) I / O subroutine

* Creat (): Create a new file or rewrite a temporary file.

Two parameters are required: file names and access license values ​​(8 envelopes). Such as:

Creat ("/ usr / pat / read_write", 0666) / * Establish a file with 0666 to establish a license method * /

Calling this subroutine must have the write and execution of the written directory of the created file, and the licensing method set to Creat () will be modified by the files set by the Umask () setting, the owner of the new file, The panel is determined by the effective UID and GID.

The return value is a file descriptor for the new file.

* fstat (): See Stat ().

* Open (): Opens the file inside the C program.

There are two parameters: file path name and open mode (i, o, i & o).

If the process that calls this subroutine does not have the correct access to the file to be opened (including search license of all directory components on the file path), it will cause failed execution.

If this subroutine is called to open the unssembling file unless the O_CREAT flag is set, the call will be unsuccessful. At this point, the access license of the new file is used as the third parameter (can be modified by the user's umask).

When the file is turned on, then change the file or the access license where the file is located, it does not affect the I / O operation of the file.

* Read (): Read information from the file that has been opened and used by Open ().

It doesn't care about the access license of the file. Once the file is opened as an input, you can read information from this file.

* Write (): Output information is in a file that has been opened and used as an output. Like read (), it does not care about the access license of the file.

(2) Process control

* EXEC (): including Execl (), Execv (), Execle (), Execve (), Execlp () and Execvp ()

You can copy an executable model to the storage space occupied by the calling process. The program that is being called the process will not be longer, and the new program replaces its location.

This is the only way to perform a program in the UNIX system: cover the original program with the program that will execute.

Safety Precautions:

The actual and effective UID and GID passed to programs that do not have SUID and SGID licenses by Exec ().

If the programs that are tested by Exec () include SUID and SGID licenses, the valid UID and GID will set the owner or group of the program.

The file establishment shield value will be passed to the new program.

All open files are passed to the new program except for the except for the exec () shutdown flag.

Use the FCNTL () subroutine to set the shutdown flag of Exec ().

* for (): It is used to build a new process. The sub-process established is the process of calling fork () (parent process)

Exactly the same copy (except for processes)

Safety Precautions:

The child process will inherit the actual and effective UID and GID of the Parent process.

The sub-process inherits the file to establish a shield value.

All open files pass to the child process.

* Signal (): Allows an accident and interrupt that the process can occur.

Two parameters are required: the subroutines to be called when the signal number and the signal occur.

The signal number is defined in Signal.h.

The subroutine to be called when the signal occurs, can be written by the user, or the value given by the system, such as SIG_IGN, the signal will be ignored, the SIG_DFL signal will be processed by the default method of the system.

As many of the security-related programs prohibit end-to-end interrupt information (Break and Delete) to avoid running by the user terminal.

Some signals cause the core dump of the process of generating the UNIX system (the contents of the process in which the process receives the signal, sometimes important information), which can be used to disable the core dump.

(3) File properties

* Access (): Detect whether the accessibility of the specified file meets the specified access type.

Two parameters are required: the file name and the access type (integer) to be detected.

The access type is defined as follows:

0: Check if the file exists

1: Check if the executive (search)

2: Check if you can write

3: Check if you can write and execute

4: Check if you read

5: Check if readable and executed 6: Check if readable can be writable

The meaning of these numbers is the same meaning as the number of licensing methods in the chmod command.

This subroutine uses the actual UID and GID detection file access capabilities (generally valid UID and GID to check file access capabilities).

Return Value: 0: License - 1: No license.

* chmod (): Change the access method of the specified file or directory to a new license method.

Two parameters are required: file names and new access licensing methods.

* chown (): Change the UID and GID of the owner and group of the specified file at the same time. (Difty from the chown command).

Since this subroutine changes the owner and group of the file, you must cancel the SUID and SGID license of the file to prevent the user from establishing the SUID and SGID programs, then run Chown () to get the permissions of others.

* Stat (): Returns the status of the file (attribute).

Two parameters are required: the file path name and a structural pointer point to the location of the status information.

The structure is defined as follows:

ST_MODE: File Type and Access Licensing Method

ST_INO: i node number

ST_DEV: ID of the device where the file is located

ST_RDEV: ID of special file

ST_nLink: File Link Number

ST_UID: File owner's UID

ST_GID: GID of the file group

ST_SIZE: File size by byte count

ST_AATIME: Last Access Time (Reading)

ST_MTIME: The final modification time (write) and the final state change

ST_CTIME: The final state modification time

Return value: 0: Success 1: Failure

* umask (): Sets the file creation of the file and its sub-process to the specified access license.

Need a parameter: new file sets the screen value.

(4) UID and GID processing

* getuid (): Returns the actual UID of the process.

* getGID (): Returns the actual GID of the process.

The above two subroutines can be used to determine who is running the process.

* getEuid (): Returns the effective UID of the process.

* getGID (): Returns the effective GID of the process.

The above two subprograms can be used in a program to determine if it is useful when running a user rather than a SUID program that runs its user, you can adjust them to check that this program is indeed running with the user's SUID.

* SetUID (): Used to change the effective UID.

For a general user, this subroutine is only useful to the SUID program to be converted between valid and actual UIDs (from the original UID to actual UID) to protect the process is not safe hazard. In fact, the process is no longer SUID mode is running.

* setgid (): Used to change the effective GID.

2. Standard C library

(1) Standard I / O

* FOPEN (): Open a file for reading or writing, security considerations are the same as Open ().

* Fread (), getc (), fgetc (), gets (), scanf () and fscanf (): From fopen ()

Read information in the file read. They don't care about the file access license. This is the same as read ().

* FWRITE (), PUT (), FPUTC (), PUTS, FPUTS (), Printf (), FPRINTF (): Write information to files over a file that have been opened by FOPEN (). They don't care about the files. license.

With Write ().

* getpass (): Reads from the terminal to 8 characters long passwords, and does not return the characters entered by the user.

Need a parameter: prompt information.

The subroutine displays the prompt information on the terminal, disables the character backup function, read the password from / dev / tty, and then restore the character backup function, return the pointer to the password that just knocked into the password.

* POPEN (): Introduction will be described in (5).

(2) / etc / passwd processing

There is a set of subroutines to make it easy access to the / etc / passwd file, and can read the file or write new entry items or updates.

* getPWUID (): Get the entry item of the specified UID from the / etc / passwd file.

* getPwnam (): For the specified login name, retrieve entry items in the / etc / passwd file.

The above two subroutines returns a pointer to the Passwd structure, which is defined in /usr/include/pwd.h, defined as follows:

Struct passwd {

Char * pw_name; / * login name * /

Char * pw_passwd; / * Encrypted password * /

UID_T PW_UID; / * UID * /

GID_T PW_GID; / * GID * /

Char * pw_age; / * proxy information * /

Char * pw_comment; / * Note * /

Char * pw_gecos;

Char * pw_dir; / ​​* Main directory * /

CHAR * PW_SHELL; / * Used shell * /

}

* getPwent (), setpwent (), endpwent (): Subsequent processing for password files.

Call getPwent (), open / etc / passwd and return to the pointer to the first entry item in the file, keep the files on the files on the open state of the file.

Then call the getPwent () to return to the entry items in the password file.

Call setPWent () Re-set the pointer of the password file as the beginning of the file.

Turn off the password file after using the full port file.

* Putpwent (): Modify or add the entry item in the / etc / passwd file.

This subroutine writes the entry entry into a specified file, which is generally a temporary file, and the direct write password file is very dangerous. It is best to do file sealing before execution, so that the two programs cannot write a file at the same time. Algorithm is as follows :

Establish an independent temporary file, ie / etc / passnnn, NNN is the PID number.

Establish a new temporary document and standard temporary file / etc / PTMP chain, if the chain failed,

Then someone is using / etc / ptmp, waiting until / etc / ptmp available or exit.

Copy / etc / passwd to / etc / ptmp, you can make any modifications to this file.

Move / etc / passwd to backup file / etc / opasswd.

Establish / etc / ptmp and / etc / passwd chain.

Disconnect / etc / passnnn and / etc / ptmp chain.

Note: The temporary file should be built in the / etc directory, to ensure that the file is in the same file system, the chain can be successful, and the temporary file will not be unsafe. In addition, if the new file already exists, even if it is built

The chain is the root user, which will also fail, thereby ensuring that no one can insert an interference once the temporary file is successfully constructed. Of course, the program with temporary files should ensure that all temporary files are cleared, and the signal is correctly captured.

(3) / etc / group processing

There is a set of information similar to the previous subroutine processing / etc / group, you must use the INCLUDE/grp.h file to join the /usr/include/grp.h file to your own program when using the file. This file defines the GROUP structure. getGRGID (), getGrent () Returns the Group structure pointer.

* getGRNAM (): Search for the specified group name in the / etc / group file, then return the pointer to the group entry item.

* getgrgid (): Similar to the previous subroutine, the difference is to search the specified GID.

* getGrent (): Returns the next entry item in the Group file.

* setGrent (): Restore the file pointer of the group file to the starting point of the file.

* endgrent (): After using it, turn off the group file.

* getUid (): Returns the actual UID of the calling process.

* getPruid (): Determines the login name corresponding to the actual UID as the actual UID, or specifies a UID as a parameter.

* getLogin (): Returns the pointer of the user logged in on the terminal.

The system checks STDIN, STDOUT, and STDERR are associated with the terminal, and the standard input associated with the terminal is used to determine the terminal name, the terminal name is used to find the user in the / etc / utmp file, which is maintained by login, by The WHO program is used to confirm the user.

* CUSERID (): First call getLogin (), if getLogin () returns a Null pointer, then call GetPWUID (GetUID ()).

* The following is the command:

* logname: List the username of the login to the terminal.

* WHO AM i: Shows the login name of the user running this command.

* ID: Display the actual UID and GID (if effective UID and GID and actual different simultaneous display valid UID and GID) and corresponding login names.

(4) Encryption subroutine

In January 1977, NBS announced a standard encryption method for networks for the US federal government ADP system: Data encryption standards, DES, DES, for non-confident applications. Des handle 64BITS block, 56-bit encryption keys.

* setKey (), encrypt (): Provides users' access to DES. This two subroutine takes a 64bits long character array. Each element in the array represents a bit, 0 or 1.SetKey () settings will be pressed. The encryption key of the DES processing ignores a 56-bit encryption key .Encrypt () then encrypts or decrypts a given 64BITS long, encrypted or decrypts the second change of the subroutine, 0 : Encryption 1: Decryption.

* crypt (): It is a password encryption program in the UNIX system, and is also called by the / usr / lib / makeKekey command.

The Crypt () subroutine is independ command, it takes 8 keywords with / usr / lib / makekey, 2 SALT characters. Keywords give to setKey (), SALT characters for mixing encrypt () DES algorithm, eventually call Encrypt () repeated 25 encrypted a string.

Returns the encrypted string pointer.

(5) Run the shell

* system (): Run / bin / SH executes the command specified by its parameter, returns when the specified command is completed.

* POPEN (): Similar to system (), different is the command runtime, its standard input or output is coupled to the file pointer returned by POPEN ().

Both call fork (), exec (), and POPEN () also calls PIPE (), completes their work, so that Fork () and Exec () security consideration begin to work.

3. Write a secure C program

Generally there are two security issues, you must consider when writing:

(1) Make sure that any temporary files you create do not contain confidential data. If there is a confidential data, set the temporary file only to yourself / write itself. Ensure that the directory for establishing a temporary file is only writable.

(2) Make sure any commands you have to run (via system (), popen (), execlp (), execv () running commands that you want to run, instead of anything else

Be careful when, especially your own procedures are licensed for SUID or SGID.

The first aspect is relatively simple, call Umask (077) before the program begins. To make the file readable to others, call CHMOD () can also be used to establish a "invisible" temporary file.

Creat ("/ TMP / XXX", 0);

FILE = Open ("/ TMP / XXX", O_RDWR);

Unlink ("/ tmp / xxx");

After the file / TMP / XXX is created, open, then disconnected, but the memory assigned to the file is not deleted until the file channel that ultimately points to the file is turned off. Open the file and any The child process can access this temporary file, while other processes cannot access the file because it has been deleted by UNLINK () in / TMP.

The second aspect is more complicated and subtle. Due to system (), POPEN (), Execlp (), execvp () is executed, if the full path of the execution command is not given, it can "lie" the user's program to perform different commands. Since the system subscriber is based on the PATH variable which directory search for the specified life

Order, this is called a Suid trap. The safest way is to change the effective UID to the actual UID before calling system (), and another better method is to use the full path name command as the parameter .execl (), Execv ( ), Execle (), execve () requires full path name as a parameter. Another way to set the SUID trap is set in the program, because System () and POPEN () are started, so shell syntax can be used. Such as:

System ("path = / bin: / usr / bin cd");

This allows the user to run system commands without having to know which directory to be executed, but this method cannot be used in Execlp (), Execvp () because they cannot start the SHELL execution call sequence passing command string.

There are two other problems: two other issues: 2 other questions about the command line of the shell explanation to system () and POPEN ():

* Shell uses the characters in the IFS shell variable to break the command line into a word (usually this shell variable is space, Tab, wrap), such as the IFS is /, string / bin / ED is explained into a word bin, next It is a word ED, thereby causing the misinterpretation of the command line.

Again again: Before running another program through his own procedure, the effective UID should change the actual UID. After another program exits, change the effective UID back to the original effective UID.SUID / SGID program Guidance criterion

(1) Do not write a SUID / SGID program, there is no such thing in most.

(2) Set up the SGID license, do not set up a SUID license. You should establish a new group alone.

(3) Do not perform any programs with EXEC (). Remember that EXEC () is also called by System () and POPEN ().

To call EXEC () (or system (), POPEN ()), you should use setgid in advance (getGID ()) to set the actual GID.

If you cannot use setgid (), you should set IFS when you call System () or POPEN ():

POPEN ("IFS = / T / N; Export IFS; / BIN / LS", "R");

. Use the full path name of the command to be executed.

If you cannot use a full path name, you should set PATH: POPEN before command ("IFS = / t / n; export import; path = / bin: / usr / bin; / bin / ls", "r") ;

Do not pass the parameters specified by the user to System () or POPEN (); if you cannot avoid it, you should check if there is a special shell character in the paragraph string.

If the user has a large program, call EXEC () to perform many other programs, do not set the large program to SGID license. You can write one (or more) smaller, the simpler SGID program must have SGID. Licensed tasks and then execute these small SGID programs by large programs.

(4) If the user must use the SUID instead of SGID, remember (2), (3) content in the same order, and adjust it accordingly. Do not set the ROOT SUID license. Select another household.

(5) If the user wants to give other people to perform their own shell programs, do not want them to read the program, set the program to only permit only, and can only run through their own shell programs.

Compile, press the following method when installing the SUID / SGID program

(1) Make sure that all SuID (SGID) programs are unwritable for groups and other users, the restrictions of access rights are less than 4755 (2755) will bring trouble. Can only be more stringent. 4111 (2111) will make Others can't find security vulnerabilities in the program.

(2) Be wary of external coding and make / install methods. Some Make / Install methods do not select the SUID / SGID program.

Check the SUID / SGID license of the above guidelines.

Check commands that may establish a Suid / SGID file in the Makefile file.

4.Root program design

There are several subrouties to call from the process of effective UID 0. Many previous subroutines,

When calling from the root process, it will be completed and the original processing. It is mainly to ignore the check permission.

The procedure running by the root user is of course a root process (except for SUID), because the valid UID is used to determine the access permission of the file, the process of calling fork () generated from the process of root, is also the root process.

(1) SetUID (): When calling SetUID () from the root process, setUID () will set the valid and actual UID as the specified value. This value can be any integer. For non-root processes, you can only call setUID () with the actual UID or the original UID of this process.

(2) Setgid (): When calling setgid () in the system process, the actual and valid GID changes to the value specified by its parameter with the setUID () in the system process.

* When calling the above two subprograms, you should pay attention to the following:

Call once setuid () (setgid ()) will set the valid and actual UID (GID), independently set effective or actual UID (GID) is very good, but you can't do this.

. SetUID () (setgid ()) sets the valid and actual UID (GID) to any integer, and its value does not have to be associated with the / etc / passwd (/ etc / group).

Once the program is setuid () in a user's UID (), the program will no longer be run as root, or it is impossible to get ROOT privileges.

(3) Chown (): When the root process runs chown (), chown () will not delete the SUID and / or SGID license of the file, but when the non-root process runs chown (), Chown () will cancel the SUID of the file and / Or SGID license. (4) Chroot (): Change the process to the concept of root directory, after calling Chroot (), the process cannot change the current work directory to any directory above the new root directory, all started Path search starts from the new root directory.

(5) mknod (): Used to establish a file, similar to Creat (), difference is MKNOD () does not return the file descriptor of the open file, and can establish any type of file (ordinary file, special file, directory file If the MKNOD () will be invoked from a non-root process, only the FIFO special file (a famous pipe file) is created, mknod () must be called from the root process (). Because creat () can only establish ordinary File, mknod () is the only way to establish a directory file, so only

There is root to create a directory, which is why the mkdir command has a SUID license and belongs all.

MkNod () is generally not called from the program. Usually use the / etc / mknod command to create special device files and these files can generally not build and delete when using the use, and the mkdir command is used to establish a directory. When using mknod () to establish special files It should be noted that you are not allowed to access memory, disks, terminals, and other devices.

(6) unlink (): Used to delete files. The parameter is to delete the path name pointer to the file. When the directory is specified, unlink () must be called from the root process, which is a unique condition that the unlink () must be called from the root process. This is why the rmdir command has a root SGID license.

(7) Mount (), umount (): This is called by the root process, which is used to install and disassemble the file system. These two subroutions are also called by the mount and umount commands, and their parameters are basically the same as the parameters of the command. Call mount () Need to give a special file and a directory pointer, the file system on the special file will be installed in this directory, and a logo option is given when calling, specifying the installed file system to be read / written (0 ) Or read only (1) .umount () is a pointer to a special file to be disassembled.

转载请注明原文地址:https://www.9cbs.com/read-95339.html

New Post(0)