Requirements Analysis:
First of all, this is not the QT series of articles, but about the web, the reason to write this, because the previous web-related development, often involved with the Linux underlying commands, such as creating a directory, delete a directory, or execute a custom script. about how PHP calls and executes Linux's underlying commands, which have been studied before, basically implement the functions that they need, but some places have not been figured out. Today, I came across it, taking advantage of this opportunity to describe to you how the step-by-step should be achieved, and finally attach the relevant C code.
Principle Realization:
First of all, the general Web site is the use of Apache or nginx, so when using PHP to execute the Linux command, on the Linux side of the identity of Apache or Nginx users to execute. Usually based on security considerations, Apache or Nginx on the Linux side of the default user is not very high permissions, such as delete, create, etc., so we must be a way to give it certain permissions. In my previous articles, I used a method, will be Apache or nginx Default user modified, to that user has given a very high authority, although achieved my goal, but it is the biggest hidden trouble, that is, the Web server default user rights set too large, Very vulnerable to attacks from outside, and even without the outside world, I myself in the PHP side to execute a command to remove my entire site, and on the Linux side of this basically no defense. Based on this, we propose a way for the Linux side not to modify the Web server default user permissions, but when the command is executed by us to control what the command should have the user's execution permissions, or root user, or the ordinary user is completely passed by our parameters determined.
Secondly, based on the above description, the basic realization of the idea is: Accept the PHP passed username and passwd parameters, a new process on the Linux side, and then impersonate the process as a user identity, that is, set the process of the user actual, valid user ID and user group ID, Then execute a command, at which point the process of executing the command is as if the username user itself executes that command. Username can execute a valid command only within its own purview, such as: If the username is a normal user, it cannot be executed by the command to delete other users or root user files. In this way, to a certain extent, the control of security is achieved.
Finally, setuid () and setgid () are required to change the actual, valid user ID and user group ID of a process as proposed above, and there is a need to be aware of the two functions here, if it is a privileged user, root, it can arbitrarily set its own UID and GID , which can impersonate any user, and if it is executed by a normal user, it can only set its own UID and GID, and cannot be set to another user, that is, cannot impersonate another user. In order to solve this problem, it is necessary to use some features of Linux, that is, to set the user tag bit of the file: s, so that the file will be executed with the owner's permission. This way, the Apache or nginx Default user executes this file as if the owner of the file is executing it, and we use the root user to create the file, which is equivalent to the root user executing the file, at which time setuid and Setgid can impersonate the process to any user's identity.
Implementation code:
[CPP]View Plaincopy
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <pwd.h>
- #include <math.h>
- #include <time.h>
- Usage:exefile Command work_directory username password
- int main (int argc, char *argv[])
- {
- char *username = NULL;
- char *password = NULL;
- char *command = NULL;
- char *workdir = NULL;
- struct passwd *stpasswd = NULL;
- if (argc = = 5)
- {
- command = argv[1];
- Workdir = argv[2]; //work Directory
- Username = argv[3];
- Password = argv[4];
- }
- Else
- {
- return 1;
- }
- //printf ("username =%s\n", username);
- //printf ("Password =%s\n", password);
- //printf ("Workdir =%s\n", workdir);
- //printf ("command =%s\n", command);
- int result = 0; //auth (Username,password); Ensure the user is a Legel user in the system
- if (result = = 0) //auth successfully
- {
- int kidstatus, deadpid;
- //! Fork () clones an identical process out; it duplicates all the variables of the current process, as if one process clones the other .
- The return value of the//! fork () function has three cases: = 0 represents the cloned process >0 on behalf of the "parent" process <0 execution error
- //! This situation is usually fork out the new process, "Optional: Identity switch", then use it to execute EXECLP (), execute the relevant command
- pid_t kidpid = fork ();
- if (kidpid = =-1)
- {
- printf ("fork Error");
- return 1;
- }
- if (kidpid = = 0)
- {
- //! Getpwnam (): Get information about a user's login
- //! header file: #include <pwd.h> #include <sys/types.h>
- STPASSWD = Getpwnam (username);
- //! setgid (): Set the actual user group ID and valid user group ID
- //! setuid (): Set the actual user ID and valid user ID
- //! chdir (): Modifying the current directory
- //! Note: If it is a non-privileged user, then it executes Setgid and setuid can only be set to its own GID and UID, and cannot set any other value
- //! If you are a privileged user (that is, you have root privileges), you can use Setgid and setuid to set any number, which is why the final
- //! compiled file to pass: chmod u+s set Privilege bit
- Setgid ((int) (stpasswd->pw_gid)); //set current UserGroup
- Setuid ((int) (STPASSWD->PW_UID)); //set Current User
- ChDir (Workdir); //change Work Directory
- //! int EXECLP (const char *file, const char *arg, ..., (char *) 0);
- //! EXECLP () looks up the file name of the PATH environment variable in the directory that matches the parameter, executes the file after it is found, and then
- //! The parameter after the second argument as the file's argv[0], argv[1] ..., the last argument must end with a null pointer (NULL)
- //! The following command is:/bin/bash-c command execution
- int rv = EXECLP ("/bin/bash", "/bin/bash", "-C", command, NULL);
- Fflush (stdout);
- return RV;
- }
- //! We only get here if we ' re the parent process.
- //! waitpid () Blocking wait child process end
- //! function Prototypes:
- Deadpid = Waitpid (kidpid, &kidstatus, 0);
- if (deadpid = =-1)
- {
- printf ("error to fork a process!");
- return 1;
- }
- Else
- {
- return 0;
- }
- }
- Else
- {
- printf ("Authenticate failed\n");
- return 1;
- }
- }
Finally, use GCC to compile the file: gcc test_exec.c-o test_exec; give it permission after the compilation is complete: chmod 777 test_exec; Then set the user tag bit: s, chmod u+s test_exec
To perform the test:
1. Use the root user to create a del_test file, and then switch to the normal user, the test can be deleted, and then use our command to simulate the root user to see if you can delete
2. Use the root user to create a del_test file, switch to the Zhangsan user, use the command to simulate the Lisi user, see the ability to delete
Through the above, we can see that the use of this command we can impersonate any user's identity, the equivalent of any permissions are controlled by you, to a certain extent, to ensure security.
Summarize:
The knowledge point of indefinitely must understand its principle, otherwise always do not know how to do. Come on! This period of time the development of the Web disk does not involve too many challenging things, look forward to the research of the UDT.
Reference: http://blog.csdn.net/houqd2012/article/details/34165381
Universal scripting helps the Web execute underlying linux commands