堕落不振功业废,勤耕不辍日月新

su部分帐户免密码切换

Python hailen 38℃

一、需求

最近业务部分希望在几百台主机上安装python expect包(pexpect),向其了解了下需求,其需求是通过4a审计平台登陆到他们业务的任一主机后(默认是user1 用户登陆),其希望可以在user1下执行某命令后,可以向user2、user3、user4几个用户免密切换,除此之外的其他用户不能切换。了解需求后,发现可以通过如下方法实现该需求:

  1. 通过expect(包括其他语言的衍生类)通过自动匹配并输入密码实现;
  2. 通过sudo配置NOPASSWD su实现(将需要切换的用户在sudo里配死);
  3. 通过OS底层函数进行uid、gid切换(需要s权限位配置和相关权限控制)

像expect、python、java、ruby等语言实现的expect的代码是不加密或编译后弱加密的,都可以读取源码后获取其密码内容。尽管shell 类语言也可以加密,但相对于更底层的语言c、c++、golang等编译出的二进制文件相比还是太弱鸡。所以本篇就以golang和c语言为例实现下这个需求。

二、golang expect实现

github上找了几个expect相关功能的模块,发现都不成功,后来找了一个可用的模块:github.com/ThomasRooney/gexpect ,具体代码如下:

package main
import (
	"fmt"
	gexpect "github.com/ThomasRooney/gexpect"
)
func main() {
	child, err := gexpect.Spawn("su - zabbix")
	if err != nil {
		panic(err)
	}
	child.Expect("Password")
	child.SendLine("zabbixpasswd")
	child.Interact()
}

上面并没有进行用户控制,如有需要可以使用os/user模块或syscall模块实现。这部分代码是以切换zabbix用户为例,如果需要匹配多个用户,可以通过switch……case语句实现。

虽然上面的代码实现了功能,但是副作用也比较大。比如:输入的命令会重复输出,ps执行不能全屏幕,无法 tab补全等。虽然后面也尝试和其他pty和term模块进行整合,但功力不够,并没有成功。

三、c语言实现

网上找了下su命令的源码看了下,发现其内部调用了两个头文件unistd.h和pwd.h ,前都用以实现uid、gid、euid、egid等的切换和调用(需s权限位),后都用于读取/etc/passwd文件,返回结构体中相关的值。由于unistd.h的帮助信息较多,这里只截取下pwd.h的相关帮助信息,如下图:

pwd-header

这里使用的getpwnam方法,用于匹配哪一个用户可以调用该程序实现用户功能切换,同上面golang一样,这里以只切换zabbix为例,需要匹配多个用户,可以通过switch……case语句实现。代码如下:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>
int main(void)
{
    int current_uid = getuid();
    printf("My UID is: %d. My GID is: %dn", current_uid, getgid());
    system("/usr/bin/id");
    if (setuid(0))
    {
        perror("setuid");
        return 1;
    }
    struct passwd *pw;
    pw = getpwnam("kiosk");
    if(pw->pw_uid==current_uid){  //进行用户控制,只有kiosk用户可以执行切换
        system("/usr/bin/su - zabbix");
    }
    return 0;
}

可以使用如下命令进行编译和设置用户属性和s权限位:

gcc -o setuid setuid.c
chown root.root setuid
chmod u+s setuid 或chmod 4755 setuid 

pwd.h相关的用户可以参考如下两篇文章:

https://aljensencprogramming.wordpress.com/tag/etcpasswd/

https://www.adampalmer.me/iodigitalsec/2009/10/03/linux-c-setuid-setgid-tutorial/

后来查了下golang的手册,发现syscall 模块包中也包含有上面的相关方法,理论也可以实现以上功能。具体可以参考官方文档:

https://golang.org/pkg/syscall/

s权限位比较便利,但也比较危险,使用不当很容易被提权,所以系统下的很多安全工具,都会通过find 查看带有s 权限的文件。当然本篇实现的这个需求,也有一个好处,就是不论主机的其他用户的密码如何更换,都可以成功进行用户切换,这点其实和sudo实现的功能是类似的。

su部分帐户免密码切换,首发于运维之路

转载请注明:我是IT » su部分帐户免密码切换

喜欢 (0)or分享 (0)