c - C 中 SSHD 的自定义 PAM
问题描述
我试图通过创建 SSH 后门来了解 PAM 的工作原理。按照这个示例https://github.com/beatgammit/simple-pam我已经知道如何制作功能性 PAM 模块,但我想从 CIN 中读取硬编码令牌。我尝试了以下方法:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <security/pam_appl.h>
#include <security/pam_modules.h>
/* expected hook */
PAM_EXTERN int pam_sm_setcred( pam_handle_t *pamh, int flags, int argc, const char **argv ) {
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) {
printf("Acct mgmt\n");
return PAM_SUCCESS;
}
/* expected hook, this is where custom stuff happens */
PAM_EXTERN int pam_sm_authenticate( pam_handle_t *pamh, int flags,int argc, const char **argv ) {
int retval;
const char* pUsername;
retval = pam_get_user(pamh, &pUsername, "Username: ");
printf("Welcome %s\n", pUsername);
if (retval != PAM_SUCCESS) {
return retval;
}
if (strcmp(pUsername, "luciannitescu") != 0) {
return PAM_AUTH_ERR;
}
char securetoken[8] = "aaaaaaa";
char password[8];
printf("Enter your secure token:\n");
scanf(password);
if (strcmp(password, securetoken) != 0)
{
return PAM_AUTH_ERR;
}
return PAM_SUCCESS;
}
执行 ssh 身份验证时,我收到权限被拒绝消息,如果我删除以下代码行,一切正常:
char securetoken[8] = "aaaaaaa";
char password[8];
printf("Enter your secure token:\n");
scanf(password);
if (strcmp(password, securetoken) != 0)
{
return PAM_AUTH_ERR;
}
认证失败:
ssh luciannitescu@127.0.0.1 -v
OpenSSH_7.6p1 Ubuntu-4, OpenSSL 1.0.2n 7 Dec 2017
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug1: Connecting to 127.0.0.1 [127.0.0.1] port 22.
debug1: Connection established.
debug1: identity file /home/lucian/.ssh/id_rsa type 0
debug1: key_load_public: No such file or directory
debug1: identity file /home/lucian/.ssh/id_rsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/lucian/.ssh/id_dsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/lucian/.ssh/id_dsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/lucian/.ssh/id_ecdsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/lucian/.ssh/id_ecdsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/lucian/.ssh/id_ed25519 type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/lucian/.ssh/id_ed25519-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_7.6p1 Ubuntu-4
debug1: Remote protocol version 2.0, remote software version OpenSSH_7.2p2 Ubuntu-4ubuntu2.4
debug1: match: OpenSSH_7.2p2 Ubuntu-4ubuntu2.4 pat OpenSSH* compat 0x04000000
debug1: Authenticating to 127.0.0.1:22 as 'luciannitescu'
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: curve25519-sha256@libssh.org
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ecdsa-sha2-nistp256 SHA256:...
debug1: Host '127.0.0.1' is known and matches the ECDSA host key.
debug1: Found key in /home/lucian/.ssh/known_hosts:22
debug1: rekey after 134217728 blocks
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: rekey after 134217728 blocks
debug1: SSH2_MSG_EXT_INFO received
debug1: kex_input_ext_info: server-sig-algs=<rsa-sha2-256,rsa-sha2-512>
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
debug1: Offering public key: RSA SHA256:... /home/lucian/.ssh/id_rsa
debug1: Authentications that can continue: publickey,password
debug1: Trying private key: /home/lucian/.ssh/id_dsa
debug1: Trying private key: /home/lucian/.ssh/id_ecdsa
debug1: Trying private key: /home/lucian/.ssh/id_ed25519
debug1: Next authentication method: password
luciannitescu@127.0.0.1's password:
debug1: Authentications that can continue: publickey,password
Permission denied, please try again.
luciannitescu@127.0.0.1's password:
debug1: Authentications that can continue: publickey,password
Permission denied, please try again.
luciannitescu@127.0.0.1's password:
debug1: Authentications that can continue: publickey,password
debug1: No more authentication methods to try.
luciannitescu@127.0.0.1: Permission denied (publickey,password).
后期编辑:
使用以下代码更改代码后:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <security/pam_appl.h>
#include <security/pam_modules.h>
/* expected hook */
PAM_EXTERN int pam_sm_setcred( pam_handle_t *pamh, int flags, int argc, const char **argv ) {
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) {
printf("Acct mgmt\n");
return PAM_SUCCESS;
}
/* expected hook, this is where custom stuff happens */
PAM_EXTERN int pam_sm_authenticate( pam_handle_t *pamh, int flags,int argc, const char **argv ) {
struct pam_message msg[1];
struct pam_response *resp = NULL;
struct pam_conv *conv;
pam_get_item (pamh, PAM_CONV, (const void **) &conv);
msg[0].msg = "Enter your secret token: ";
msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
conv->conv(1, &msg, &resp, conv->appdata_ptr);
// Token is now in resp->resp;
int retval;
const char* pUsername;
retval = pam_get_user(pamh, &pUsername, "Username: ");
printf("Welcome %s\n", pUsername);
if (retval != PAM_SUCCESS) {
return retval;
}
if (strcmp(pUsername, "luciannitescu") != 0) {
return PAM_AUTH_ERR;
}
return PAM_SUCCESS;
}
我无法建立 SSH 连接:
lucian@local:~$ ssh luciannitescu@127.0.0.1
luciannitescu@127.0.0.1's password:
Connection closed by 127.0.0.1 port 22
服务器调试:
debug3: mm_request_send entering: type 23
debug2: userauth_pubkey: authenticated 0 pkalg rsa-sha2-512 [preauth]
debug3: userauth_finish: failure partial=0 next methods="publickey,password" [preauth]
debug3: send packet: type 51 [preauth]
debug3: receive packet: type 50 [preauth]
debug1: userauth-request for user luciannitescu service ssh-connection method password [preauth]
debug1: attempt 2 failures 1 [preauth]
debug2: input_userauth_request: try method password [preauth]
debug3: mm_auth_password entering [preauth]
debug3: mm_request_send entering: type 12 [preauth]
debug3: mm_auth_password: waiting for MONITOR_ANS_AUTHPASSWORD [preauth]
debug3: mm_request_receive_expect entering: type 13 [preauth]
debug3: mm_request_receive entering [preauth]
debug3: mm_request_receive entering
debug3: monitor_read: checking request 12
debug3: PAM: sshpam_passwd_conv called with 1 messages
mm_log_handler: write: Broken pipe
debug1: do_cleanup
debug3: PAM: sshpam_thread_cleanup entering
Segmentation fault (core dumped)
解决方案
您不能使用scanf()
从用户读取值,因为标准输入未传递给用户。您必须使用具有适当功能的 ssh 键盘交互式身份验证。这由pam_conv(PAM 对话)函数支持。
手册页_man 3 pam_conv_ 描述了接口。它的工作原理基本上是这样的:
PAM_EXTERN int
pam_sm_authenticate (pam_handle_t * pamh,
int flags, int argc, const char **argv)
{
struct pam_message msg[1];
struct pam_response *resp = NULL;
struct pam_conv *conv;
pam_get_item (pamh, PAM_CONV, (const void **) &conv);
msg[0].msg = "Enter your secret token: ";
msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
conv->conv(1, &msg, &resp, conv->appdata_ptr);
// Token is now in resp->resp;
....
}
您可以将此作为自定义身份验证功能的开始。
推荐阅读
- python - 运行任意代码作为函数参数(类似于 lambda)
- reinforcement-learning - 车杆问题强化学习的奖励
- java - 如何在 Java GUI 中进行多项选择
- user-interface - 如果将 Unicode 用于 UI 符号,是否有比 U+2261(≡,“相同”)更好的汉堡菜单选择?
- python - 如何使用 Mosquitto MQTT 订阅不同网络中的 Raspberry Pi Broker?
- json - ACF 中的 JSON 嵌套对象值名称
- excel - 如何提高此 FOR NEXT 循环的速度
- android - 使用自定义适配器在视图中仅显示列表的某些元素
- macos - 如何授予对 Mac 上文件和文件夹的网页访问权限
- php - Magento 2 将扩展属性添加到 Magento\Sales\Api\Data\ShipmentTrackInterface