@lightless
2017-04-07T17:25:33.000000Z
字数 3239
阅读 1283
未分类
上篇文章中提出了一个基于docker的蜜罐系统设计,仅仅是将攻击者的流量引入到蜜罐中,但这是不够的,我们要发起反击,将攻击的流量打回去!为什么想这么做呢?记得很久以前参加某个安全沙龙的时候,某个安全专家提出了一个十分猥琐的思路,大意是,如果你发现有一个IP在持续的对你的SSH(以SSH为例,其他服务类似)进行爆破,有一种可能是这个IP被别人种马并自动进行对其他主机的爆破,以便传播自己,在这种情况下,爆破所用的字典很大可能上是固定的,也就是说,你用这个IP爆破过来的流量反爆破回去,很有可能爆破成功XD,于是很自然的就想将这个思路用到蜜罐上了。
以前也尝试过写通过某些很挫的方法记录用户SSH登录的账号密码,但是奈何太菜了,只能记录正确的账号密码,那些爆破失败的密码是没有办法记录的。最近知道了PAM这个东西,工作中也在使用,于是学习了一番。
PAM的全称是Pluggable Authentication Modules for Linux,大概就是一个插件化的认证模块,每个程序可以通过配置文件调用不同的认证模块,以便于达到认证的目的。先排出两个参考资料,已经讲的十分详细了:
The Linux-PAM Guides
Using Pluggable Authentication Modules (PAM)
PAM的配置文件一般放在/etc/pam.d/文件夹中,例如login程序的PAM配置文件为/etc/pam.d/login。
PAM配置文件有固定的格式,一般如下:
module_interface control_flag module_name module_arguments
module_interface代表的是认证过程中不同的阶段,目前总共有四种:
每个PAM的模块都可以提供多种interface,例如pam_unix.so就可以提供上面四种所有的interface。
例如下面这个配置,则是将pam_unix.so配置到auth interface。
auth required pam_unix.so
模块的interface指令是可以被堆叠的(原文: stacked),例如reboot的配置:
[root@VM-UBUNTU ~]# cat /etc/pam.d/reboot#%PAM-1.0# pam_rootok用于检查当前用户是否为root,检查的方法是查看UID是否为0。如果检查成功,则直接返回成功,不会进行其他的检查。auth sufficient pam_rootok.so# pam_console.so模块用于认证用户,如果用户登录到console中了,会检查/etc/security/console.app/这个文件夹中有没有一个`reboot`文件,如果检查通过,则继续向下检查。auth required pam_console.so#auth include system-auth# pam_permit.so允许root或任何登录到console中的用户执行reboot操作。account required pam_permit.so
每个模块被执行后都只会有两种返回值:成功或失败。ControlFlag则为了说明当PAM返回了某个结果的时候,应当如何继续认证。换句话说,当堆叠了很多模块的时候,ControlFlag则决定了这次认证中返回值的重要程度。
常见的总共有五种ControlFlag:
因为我们要记录用户的账户与密码,所以需要一个在auth interface阶段的PAM,根据文档我们也可以看出,需要实现两个方法:
#define PAM_SM_AUTH#include <security/pam_modules.h>PAM_EXTERN int pam_sm_authenticate( pamh,flags,argc,argv);PAM_EXTERN int pam_sm_setcred( pamh,flags,argc,argv);
第二个pam_sm_setcred方法我们并不关心,所以在代码中简单的返回PAM_SUCCESS就可以了。
/** Auth阶段的其他的PAM Interface,不用关心* */PAM_EXTERN intpam_sm_setcred(pam_handle_t *pam_handle, int flags, int argc, const char **argv) {(void)pam_handle;(void)flags;(void)argc;(void)argv;return (PAM_SUCCESS);}
然后就要实现pam_sm_authenticate方法了,我们在这个方法里要做的事情其实很简单,获取用户名,获取密码,然后记录到文件中。
获取用户名可以通过pam_get_user实现,而密码可以通过pam_get_authtok实现,实在是太简单了。代码大概长这个样子:
PAM_EXTERN intpam_sm_authenticate(pam_handle_t *pam_handle, int flags, int argc, const char **argv) {const char *username = NULL;const char *password = NULL;// get usernameint pam_err = pam_get_user(pam_handle, &username, NULL);if (pam_err != PAM_SUCCESS) {return pam_err;}syslog(LOG_ERR, "Get username: %s", username);// get passwordpam_err = pam_get_authtok(pam_handle, PAM_AUTHTOK, &password, NULL);if (pam_err != PAM_SUCCESS) {return PAM_SYSTEM_ERR;}syslog(LOG_ERR, "password: %s", password);write_file(username, password);return PAM_SUCCESS;}
其中write_file函数是把username和password拼接起来并写入到文件中。完整的代码已经放到github上了,有兴趣的同学可以去玩一玩,地址:https://github.com/LiGhT1EsS/pam_my_unix