[关闭]
@lightless 2017-04-07T17:25:33.000000Z 字数 3239 阅读 1142

Kokkuri的复仇

未分类


上篇文章中提出了一个基于docker的蜜罐系统设计,仅仅是将攻击者的流量引入到蜜罐中,但这是不够的,我们要发起反击,将攻击的流量打回去!为什么想这么做呢?记得很久以前参加某个安全沙龙的时候,某个安全专家提出了一个十分猥琐的思路,大意是,如果你发现有一个IP在持续的对你的SSH(以SSH为例,其他服务类似)进行爆破,有一种可能是这个IP被别人种马并自动进行对其他主机的爆破,以便传播自己,在这种情况下,爆破所用的字典很大可能上是固定的,也就是说,你用这个IP爆破过来的流量反爆破回去,很有可能爆破成功XD,于是很自然的就想将这个思路用到蜜罐上了。

0x00 初识PAM

以前也尝试过写通过某些很挫的方法记录用户SSH登录的账号密码,但是奈何太菜了,只能记录正确的账号密码,那些爆破失败的密码是没有办法记录的。最近知道了PAM这个东西,工作中也在使用,于是学习了一番。

PAM的全称是Pluggable Authentication Modules for Linux,大概就是一个插件化的认证模块,每个程序可以通过配置文件调用不同的认证模块,以便于达到认证的目的。先排出两个参考资料,已经讲的十分详细了:
The Linux-PAM Guides
Using Pluggable Authentication Modules (PAM)

0x01 PAM配置文件

PAM的配置文件一般放在/etc/pam.d/文件夹中,例如login程序的PAM配置文件为/etc/pam.d/login
PAM配置文件有固定的格式,一般如下:

  1. module_interface control_flag module_name module_arguments

module_interface代表的是认证过程中不同的阶段,目前总共有四种:

每个PAM的模块都可以提供多种interface,例如pam_unix.so就可以提供上面四种所有的interface。
例如下面这个配置,则是将pam_unix.so配置到auth interface。

  1. auth required pam_unix.so

模块的interface指令是可以被堆叠的(原文: stacked),例如reboot的配置:

  1. [root@VM-UBUNTU ~]# cat /etc/pam.d/reboot
  2. #%PAM-1.0
  3. # pam_rootok用于检查当前用户是否为root,检查的方法是查看UID是否为0。如果检查成功,则直接返回成功,不会进行其他的检查。
  4. auth sufficient pam_rootok.so
  5. # pam_console.so模块用于认证用户,如果用户登录到console中了,会检查/etc/security/console.app/这个文件夹中有没有一个`reboot`文件,如果检查通过,则继续向下检查。
  6. auth required pam_console.so
  7. #auth include system-auth
  8. # pam_permit.so允许root或任何登录到console中的用户执行reboot操作。
  9. account required pam_permit.so

每个模块被执行后都只会有两种返回值:成功或失败。ControlFlag则为了说明当PAM返回了某个结果的时候,应当如何继续认证。换句话说,当堆叠了很多模块的时候,ControlFlag则决定了这次认证中返回值的重要程度。
常见的总共有五种ControlFlag

0x02 编写PAM

因为我们要记录用户的账户与密码,所以需要一个在auth interface阶段的PAM,根据文档我们也可以看出,需要实现两个方法:

  1. #define PAM_SM_AUTH
  2. #include <security/pam_modules.h>
  3. PAM_EXTERN int pam_sm_authenticate( pamh,
  4. flags,
  5. argc,
  6. argv);
  7. PAM_EXTERN int pam_sm_setcred( pamh,
  8. flags,
  9. argc,
  10. argv);

第二个pam_sm_setcred方法我们并不关心,所以在代码中简单的返回PAM_SUCCESS就可以了。

  1. /*
  2. * Auth阶段的其他的PAM Interface,不用关心
  3. * */
  4. PAM_EXTERN int
  5. pam_sm_setcred(pam_handle_t *pam_handle, int flags, int argc, const char **argv) {
  6. (void)pam_handle;
  7. (void)flags;
  8. (void)argc;
  9. (void)argv;
  10. return (PAM_SUCCESS);
  11. }

然后就要实现pam_sm_authenticate方法了,我们在这个方法里要做的事情其实很简单,获取用户名,获取密码,然后记录到文件中。

获取用户名可以通过pam_get_user实现,而密码可以通过pam_get_authtok实现,实在是太简单了。代码大概长这个样子:

  1. PAM_EXTERN int
  2. pam_sm_authenticate(pam_handle_t *pam_handle, int flags, int argc, const char **argv) {
  3. const char *username = NULL;
  4. const char *password = NULL;
  5. // get username
  6. int pam_err = pam_get_user(pam_handle, &username, NULL);
  7. if (pam_err != PAM_SUCCESS) {
  8. return pam_err;
  9. }
  10. syslog(LOG_ERR, "Get username: %s", username);
  11. // get password
  12. pam_err = pam_get_authtok(pam_handle, PAM_AUTHTOK, &password, NULL);
  13. if (pam_err != PAM_SUCCESS) {
  14. return PAM_SYSTEM_ERR;
  15. }
  16. syslog(LOG_ERR, "password: %s", password);
  17. write_file(username, password);
  18. return PAM_SUCCESS;
  19. }

其中write_file函数是把username和password拼接起来并写入到文件中。完整的代码已经放到github上了,有兴趣的同学可以去玩一玩,地址:https://github.com/LiGhT1EsS/pam_my_unix

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注