Linux System Account SSH Weak Password Detection Automatic By System API
catalog
1. Linux弱口令攻擊向量 2. Linux登錄驗證步驟 3. PAM 4. 弱口令風險基線檢查?
1. Linux弱口令攻擊向量
0x1: SSH密碼暴力破解
hydra -l root -P /root/passwdCracker/password.lst -t 16 -vV -e ns 112.124.51.10 ssh對于Linux系統來說,從外部破解系統密碼的途徑只有SSH這一條路,攻擊者必須借助網絡進行密碼猜解嘗試
0x2: Linux SSH空口令帳號
1. 通過Bash指令: cut -d: -f1 /etc/passwd,獲取當前賬戶列表 2. 遍歷列表,調用getpwnam、getgrgid獲取每個賬戶的pw_name、pw_shell,過濾出是shell為/bin/bash或/bin/sh(非/sbin/nologin)的賬戶 3. 將過濾出的帳號在/etc/shadow中逐行查找,判斷當前帳號是否為空口令(第二段為空)但是需要注意的是,用戶賬號剛創建時沒有口令,但是被系統鎖定,無法使用,必須為其指定口令后才可以使用,即使是指定空口令
0x2: /etc/shadow本地暴力破解(john and ripper)
tar zxvf john-1.ll cd john-1.8.0/src make make clean generic cd ../run ./unshadow /etc/passwd /etc/shadow > mypasswd ./john ./mypasswdRelevant Link:
http://www.openwall.com/john/ http://www.openwall.com/john/doc/EXAMPLES.shtml http://www.douban.com/note/326215912/ http://darren.blog.51cto.com/1081720/634241 http://linuxconfig.org/password-cracking-with-john-the-ripper-on-linux http://4506912.blog.51cto.com/4496912/999577 http://www.kafan.cn/edu/42559051.html?
2. Linux登錄驗證步驟
1. 根據用戶名從/etc/passwd提取uid,gid以及家目錄和shell配置 2. /etc/shadow根據uid核對密碼 3. 進入shell控制階段 //此時并不意味著登錄成功,若用戶對應的shell為/sbin/nologin,則禁止該用戶登錄系統,但可以進行其他工作,譬如操作郵件,注: /etc/nologin.txt可以顯示用戶不能登錄的原因 4. 進行PAM驗證,讀取/etc/pam.d/login,必須通過驗證才能最終登錄,該文件內容通常如下 auth required pam_securetty.so //pam_securetty.so讀取/etc/securrety,設定root用戶可以登陸的終端,一般只設置tty而沒有pts/0,telnet使用該模塊故無法使用root用戶登錄,而sshd沒有使用到該模塊故不受限制 auth required pam_stack.so service=system-auth auth required pam_nologin.so //pam_nologin.so 模塊始終允許root用戶可以登陸,其他用戶只有在/etc/nologin文件不存在時可以登陸, 若/etc/nologin文件存在,則在輸入正確用戶名及任意密碼后將該文件內容顯示給用戶 account required pam_stack.so service=system-auth password required pam_stack.so service=system-auth session required pam_stack.so service=system-auth session optional pam_console.so +----------------+| application: X |+----------------+ / +----------+ +================+| authentication-[---->--\--] Linux- |--<--| PAM config file|| + [----<--/--] PAM | |================||[conversation()][--+ \ | | | X auth .. a.so |+----------------+ | / +-n--n-----+ | X auth .. b.so || | | __| | | _____/| service user | A | | |____,-----'| | | V A+----------------+ +------|-----|---------+ -----+------++---u-----u----+ | | || auth.... |--[ a ]--[ b ]--[ c ]+--------------+| acct.... |--[ b ]--[ d ]+--------------+| password |--[ b ]--[ c ]+--------------+| session |--[ e ]--[ c ]+--------------+0x1: 密碼驗證模塊驗證流程
1. 執行/usr/bin/passwd,并輸入密碼 2. passwd調用PAM模塊,讀取/etc/pam.d/passwd配置文件并加載相應.so文件,對輸入的密碼進行驗證 3. 將驗證結果傳回passwd程序 //注: passwd修改密碼時,除了參考/etc/login.defs,還要滿足/etc/pam.d/passwd模塊的驗證Relevant Link:
http://blog.itpub.net/15480802/viewspace-1406088?
3. PAM
PAM的英文全稱是Pluggable Authentication Module系統,即此程序是有關執行用戶鑒別和帳號維護的服務。鑒別部分通常通過: (合法性)質詢-回應的交互來完成的。使用PAM,管理員可以通過不重編輯鑒定程序來定制一些使用方法,PAM有四部分組成
1. libpam: 實現PAM API的庫 2. PAM配置文件: /etc/pam.conf 3. 一套動態可裝載二進制對象組成,常常用來調用一些處理實際鑒別(authentication)工作的服務模塊 4. 使用PAM API的系統命令組成,如login、us、ftp、telnet、etc..0x1: LIBPAM
PAM API的認證(authentication)常規程序有三個主要函數組成
1. pam_start( const char *service_name, const char *username, const struct pam_conv *conv, pam_handle_t **pamh_p ); /* pam_start()和pam_end()函數是開始和結束一個PAM會話,傳遞給pam_start() 函數的參數如下所示: + service_name: 一定義在pam.conf中的特殊服務 + username: 需要鑒權的用戶登錄名。 + conv: 一指向pam_conf結構的指針 + pamh_p: 一雙精度指向pam_handle_t結構的指針。PAM構架會分配或不分配內存給這個結構,并且一應用程序不能直接訪問它。它基本上是用來通過PAM構架(framework)來處理多個并發的PAM會話 pam_conv結構如下所示: struct pam_conv {int (*conv)(int num_msg, const struct pam_message **msg,struct pam_response **resp, void *appdata_ptr);void *appdata_ptr; }*conv是指向PAM對話函數的指針,appdata_ptr指針指向特殊應用程序數據,它并不常用 */2. pam_end( pam_handle_t *pamh, int exit_status ); /* pam_end()函數的參數由在pam_start()函數中填充的pam_handle_t*組成,并且返回的是exit狀態。exit狀態正常情況下是PAM_SUCCESS。pam_edn()會收回與pam_handle_t*相關聯的內存,并且任何企圖重用這個句柄將返回一個seg fault錯誤 */3. pam_authenticate( pam_handle_t *pamh, int flags ); /* pam_authenticate()函數也再一次由通過pam_start()填充的pam_handle_t*組成,并且可選的標志(flags)可以傳遞給結構(framework) */另外一些可以應用于應用程序的PAM API函數如下所示
+ pam_set_item() - 為PAM會話寫狀態信息 + pam_get_item() - 為PAM獲得狀態信息 + pam_acct_mgmt() - 檢查當前用戶帳號是否合法 + pam_open_session() - 開始一個新的會話 + pam_close_session() - 關閉當前會話進程 + pam_setcred() -管理用戶信任資格(credentials) + pam_chauthtok() - 改變用戶的鑒權(authentication)token牌 + pam_strerror() - 返回錯誤字符串,類似與perror()函數0x2: PAM.CONF
PAM配置文件通常位于/etc/pam.conf,它可以分為四個部分
1. 鑒權(authentication) 2. 帳號管理 3. 會話管理 4. 密碼管理一個標準的一行配置如下所示:
login auth required /usr/lib/security/pam_unix.so.1 try_first_pass1) 第一欄是服務名,這是參照在pam_start()函數中的第一個參數。如果通過pam_start()的服務請求不列在pam.conf,則將使用默認的"other"服務。"other"服務名字可以是"su"和"rlogin",如果服務名不止一次說明,模塊將會提示"stacked",并且framework將會通過第三欄的值來決定2) 第二欄指示這特定的服務將執行何種類型的行為,合法的值是: "auth"為鑒權行為、"account"為帳號管理、"session"為會話管理、"password"為密碼管理。不是所有的應用程序需要使用每一個行為,如,su僅僅需要使用"auth"鑒權行為,"passwd"只需要來使用"password"管理行為 3) 第三欄作為一個控制類型的一欄。如果用戶在鑒定行為中失敗,它指示PAM 架構(framework)行為。此欄正確的值為:"requisite","required", "sufficient", "optional":3.1) + "requisite"意思指如果用戶在鑒定(quthentication)時失敗,PAM framework會立即返回一失敗信息,其中沒有其他模塊調用。3.2) + "required"指示如果一個用戶鑒定(quthentication)時失敗,PAM framework只在調用其他所有模塊后在返回失敗信息。這樣做的話用戶會不知道哪個模塊鑒權被拒絕,如果一個用戶成功被鑒別,所有"required"模塊必須返回成功3.3) + "optional"意思是用戶將被允許訪問即使鑒權失敗,失敗的結果是下一個在堆棧中的模塊將被處理3.4) + "sufficient"指的是如果用戶傳遞一這特定模塊,PAM framework會立即返回成功,即使隨后的模塊有"requisite"或者"required"控制值,類似于"optional" 、"sufficient"回允許訪問即使鑒全步驟失敗4) pam.conf第四欄中是認證模塊的路徑,各個系統路徑不同,如在Linux-PAM系統中PAM模塊在/usr/lib目錄下,而Solaris在/usr/lib/security中維護模塊 5) 第五欄是一個空格分開的module-dependent選項列表,是傳遞給認證模塊調用0x3: 模塊 MODULES
每一個PAM模塊本質上是一個必須輸出特定函數的庫,這些函數可以被PAM framework調用(面向接口編程),通過庫輸出的函數有如下列表
+ pam_sm_authenticate() + pam_sm_setcred() + pam_sm_acct_mgmt() + pam_sm_open_session() + pam_sm_close_session() + pam_sm_chauthtok()如果實現者不決定在一模塊內支持特定的操作,模塊會為此操作返回PAM_SUCCESS,例如:如果一個模塊設計成為不支持帳號管理(account management),pam_sm_acct_mgmt()函數會簡單的返回PAM_SUCCESS
pam_sm_authenticate()是按下面的方式聲明的
一個簡單的pam_unix 模塊中的pam_sm_authenticate()函數應該如下所示
#include <security/pam_modules.h> #include <...>extern int pam_sm_authenticate( pam_handle_t *pamh, int flgs, int c, char **v ) {char *user;char *passwd;struct passwd *pwd;int ret;/* ignore flags and optional arguments */if ( (ret = pam_get_user( ..., &user )) != PAM_SUCCESS )return ret;if ( (ret = pam_get_pass( ..., &passwd )) != PAM_SUCCESS )return ret;if ( (pwd = getpwnam(user)) != NULL ) {if ( !strcmp(pwd->pw_passwd, crypt(passwd)) )return PAM_SUCCESS;elsereturn PAM_AUTH_ERR;}return PAM_AUTH_ERR; }0x4: 應用程序 APPLICATION
一個應用程序處理PAM部分必須由pam_start()和pam_end()組成和一PAM對話函數。比較幸運的是,user-space PAM API定義的比較成熟和穩定所以對話函數是比較模板型的代碼。一個簡單的su PAM實現所下所示
#include <security/pam_appl.h> #include <...>int su_conv(int, const struct pam_message **,struct pam_response **, void *);static struct pam_conv pam_conv = { su_conv, NULL };int main( int argc, char **argv ) {pam_handle_t *pamh;int ret;struct passwd *pwd;/* assume arguments are correct and argv[1] is the username */ret = pam_start("su", argv[1], &pam_conv, &pamh);if ( ret == PAM_SUCCESS )ret = pam_authenticate(pamh, 0);if ( ret == PAM_SUCCESS )ret = pam_acct_mgmt(pamh, 0);if ( ret == PAM_SUCCESS ) {if ( (pwd = getpwnam(argv[1])) != NULL )setuid(pwd->pw_uid);else {pam_end(pamh, PAM_AUTH_ERR);exit(1);}}pam_end(pamh, PAM_SUCCESS);/* return 0 on success, !0 on failure */return ( ret == PAM_SUCCESS ? 0 : 1 ); }int su_conv(int num_msg, const struct pam_message **msg,struct pam_response **resp, void *appdata) {struct pam_message *m = *msg;struct pam_message *r = *resp;while ( num_msg-- ){switch(m->msg_style) {case PAM_PROMPT_ECHO_ON:fprintf(stdout, "%s", m->msg);r->resp = (char *)malloc(PAM_MAX_RESP_SIZE);fgets(r->resp, PAM_MAX_RESP_SIZE-1, stdin);m++; r++;break;case PAM_PROMPT_ECHO_OFF:r->resp = getpass(m->msg);m++; r++;break;case PAM_ERROR_MSG:fprintf(stderr, "%s\n", m->msg);m++; r++;break;case PAM_TEXT_MSG:fprintf(stdout, "%s\n", m->msg);m++; r++;break;default:break;}}return PAM_SUCCESS; }Relevant Link:
http://www.xfocus.net/articles/200006/45.html http://www.helplib.net/s/linux.die/65_1666/man-3-pam-start.shtml?
3. 弱口令風險基線檢查
0x1: 檢測方案
1. 通過Bash指令: cut -d: -f1 /etc/passwd,獲取當前賬戶列表 2. 遍歷列表,調用getpwnam、getgrgid獲取每個賬戶的pw_name、pw_shell,過濾出是shell為非"/sbin/nologin"的賬戶 3. 將上一步得到的賬號在/etc/shadow中查找,過濾出password hash不為空的帳號(即只有顯式通過passwd指令設置過密碼的賬號才可以登錄) 4. 遍歷過濾出的"可登錄帳號",調用pam_authenticate API/或者SSH login API進行登錄嘗試 5. 記錄并上報猜解出的弱口令0x2: 基于PAM API框架進行密碼猜解嘗試
對于Linux弱口令風險來說,空口令風險不存在(帳號創建默認空口令但是被系統鎖定)、john and ripper本地破解/etc/shadow(密碼學原理)無法防御,因為不可能禁止用戶讀取這個文件,禁止讀取會造成破壞正常業務的風險
#include <stdlib.h> #include <iostream> #include <fstream> #include <security/pam_appl.h> #include <unistd.h> #include <string.h>// To build this: // g++ test.cpp -lpam -o teststruct pam_response *reply;//function used to get user input int function_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) {*resp = reply;return PAM_SUCCESS; }int main(int argc, char** argv) {if(argc != 2) {fprintf(stderr, "Usage: check_user <username>\n");exit(1);}const char *username;username = argv[1];const struct pam_conv local_conversation = { function_conversation, NULL };pam_handle_t *local_auth_handle = NULL; // this gets set by pam_startint retval;// local_auth_handle gets set based on the service retval = pam_start("login", username, &local_conversation, &local_auth_handle);//retval = pam_start("common-auth", username, &local_conversation, &local_auth_handle);if (retval != PAM_SUCCESS){std::cout << "pam_start returned " << retval << std::endl;exit(retval);}reply = (struct pam_response *)malloc(sizeof(struct pam_response));// *** Get the password by any method, or maybe it was passed into this function.//reply[0].resp = getpass("Password: ");reply[0].resp = strdup("test");reply[0].resp_retcode = 0;retval = pam_authenticate(local_auth_handle, 0 | PAM_DISALLOW_NULL_AUTHTOK);if (retval != PAM_SUCCESS){if (retval == PAM_AUTH_ERR){std::cout << "Authentication failure." << std::endl;}else{std::cout << "pam_authenticate returned " << retval << std::endl;}exit(retval);}std::cout << "Authenticated." << std::endl;retval = pam_end(local_auth_handle, retval);if (retval != PAM_SUCCESS){std::cout << "pam_end returned " << retval << std::endl;exit(retval);}return retval; }pam位于SSH的底層(更下一層),調用pam_authenticate api不受/sbin/nologin的影響,從本質上來說和ssh登錄嘗試是一樣的,在代碼中要注意的是,調用pam_start時傳入"login"服務器名即可,因為僅僅需要使用"auth"鑒權行為
pam_start中的參數service_name服務名指定了使用哪個配置文件,如service_name為"login",將使用/etc/pam.d/login這個配置在centos、ubuntu下測試都通過
Relevant Link:
http://stackoverflow.com/questions/5913865/pam-authentication-for-a-legacy-application/5970078#5970078 http://stackoverflow.com/questions/5913865/pam-authentication-for-a-legacy-application http://www.jiancool.com/article/58701980019/;jsessionid=798A5A41EB356A6A1FC5C8E449523F6B?
Copyright (c) 2015 LittleHann All rights reserved
?
轉載于:https://www.cnblogs.com/LittleHann/p/4875535.html
總結
以上是生活随笔為你收集整理的Linux System Account SSH Weak Password Detection Automatic By System API的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OPW-00001: Unable to
- 下一篇: 电工助手App开发 第三周