最近有需求要幫系統加入新增帳號、修改帳密的流程,所以想著想著,就蹦出了一支 C 程式,透過 setuid 的方式,終於可以完成這項工作 (經高手指點,bash 無法被 setuid 使用,也就是設定完後無法達成想要的結果,可以在 script 裡打 id 指令)
相關 Unix 指令回顧:
- 一行指令新增帳號
- $ sudo adduser --quiet --gecos "" --disabled-login --no-create-home --shell "/usr/sbin/nologin" tester
- 一行指令更新密碼
- $ echo "tester:password" | chpasswd
- 檢查使用者是否存在
- $ getent passwd tester
程式碼:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#define CMD_ADDUSER "sudo adduser --quiet --gecos \"\" --disabled-login --no-create-home --shell \"/usr/sbin/nologin\" "
#define CMD_CHECK_USER_EXISTS "getent passwd"
#define MAX_BUFFER_LINE 1024
int main(int argc, char *argv[])
{
char buf[MAX_BUFFER_LINE+1], pass[MAX_BUFFER_LINE+1], *cmd;
FILE *fp;
setuid(0); // use root
//system("id");
if( argc < 3 )
{
fprintf( stderr, "Usage> %s username [ - | password]\n\t%s username -\t\t(read password from stdin)\n\t%s username password\n\n\tothers: sudo chown root %s && sudo chmod 4755 %s\n" , argv[0], argv[0], argv[0] , argv[0], argv[0] );
exit(1);
}
memset( buf, 0, MAX_BUFFER_LINE + 1);
memset( pass, 0, MAX_BUFFER_LINE + 1);
if( argv[2][0] != '-' )
{
strncpy( pass, argv[2], MAX_BUFFER_LINE );
pass[MAX_BUFFER_LINE] = '\0';
}
else if( !feof( stdin ) && fgets( pass, MAX_BUFFER_LINE, stdin ) > 0 )
{
//printf("Pass:[%s]\n",pass);
}
if( strlen(pass) < 1 )
{
fprintf( stderr, "Error @ Init: password is empty\n" );
exit(1);
}
// check account exists
cmd = buf;
snprintf( buf, MAX_BUFFER_LINE, "%s %s", CMD_CHECK_USER_EXISTS, argv[1] );
fp = popen( cmd , "r" );
memset( buf, 0, MAX_BUFFER_LINE + 1);
fgets( buf, MAX_BUFFER_LINE, fp );
pclose(fp);
if( !strlen(buf) ) // create the account if not exists
{
// add account
memset( buf, 0, MAX_BUFFER_LINE + 1);
cmd = buf;
snprintf( buf, MAX_BUFFER_LINE, "%s %s", CMD_ADDUSER, argv[1] );
pclose( popen( cmd , "r" ) );
// query the account
memset( buf, 0, MAX_BUFFER_LINE + 1);
cmd = buf;
snprintf( buf, MAX_BUFFER_LINE, "%s %s", CMD_CHECK_USER_EXISTS, argv[1] );
fp = popen( cmd , "r" );
memset( buf, 0, MAX_BUFFER_LINE + 1);
fgets( buf, MAX_BUFFER_LINE, fp );
pclose(fp);
if( !strstr( buf, argv[1] ) ) // user is not created
{
printf("Error @ create an account: user cannot be created\n");
exit(1);
}
// change password
memset( buf, 0, MAX_BUFFER_LINE + 1);
cmd = buf;
snprintf( buf, MAX_BUFFER_LINE, "echo \"%s:%s\" | chpasswd ", argv[1] , pass );
fp = popen( cmd , "r" );
memset( buf, 0, MAX_BUFFER_LINE + 1);
fgets( buf, MAX_BUFFER_LINE, fp );
pclose(fp);
if( !strlen(buf) )
printf("OK\n");
}
else if( strstr( buf, "/bin/false" ) || strstr( buf, "/nologin" ) ) // change password
{
// change password
memset( buf, 0, MAX_BUFFER_LINE + 1);
cmd = buf;
snprintf( buf, MAX_BUFFER_LINE, "echo \"%s:%s\" | chpasswd ", argv[1] , pass );
fp = popen( cmd , "r" );
memset( buf, 0, MAX_BUFFER_LINE + 1);
fgets( buf, MAX_BUFFER_LINE, fp );
pclose(fp);
if( !strlen(buf) )
printf("OK\n");
}
else
{
printf("SKIP @ cannot change the password for '%s'.\n", argv[1]);
}
return 0;
}
暫時把這隻程式定位:
- 可以新增 nologin 帳號
- 可以修改 nologin 帳號的密碼
用法:
$ gcc main.c
$ sudo chown root ./a.out && sudo chmod 4755 ./a.out
$ ./a.out new_account new_password
若要在安全一下,可以在設定 uid 範圍,以避免改到一些系統帳號。
沒有留言:
張貼留言