Skip to content

Commit 43db34c

Browse files
authored
Land rapid7#19413, Add automated acceptance tests for cmd_exec API
2 parents ab7e02d + cbd763f commit 43db34c

File tree

13 files changed

+1249
-37
lines changed

13 files changed

+1249
-37
lines changed
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
2+
name: Acceptance
3+
4+
# Optional, enabling concurrency limits: https://docs.github.com/en/actions/using-jobs/using-concurrency
5+
#concurrency:
6+
# group: ${{ github.ref }}-${{ github.workflow }}
7+
# cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
8+
9+
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
10+
permissions:
11+
actions: none
12+
checks: none
13+
contents: none
14+
deployments: none
15+
id-token: none
16+
issues: none
17+
discussions: none
18+
packages: none
19+
pages: none
20+
pull-requests: none
21+
repository-projects: none
22+
security-events: none
23+
statuses: none
24+
25+
on:
26+
workflow_dispatch:
27+
inputs:
28+
metasploitPayloadsCommit:
29+
description: 'metasploit-payloads branch would like to test'
30+
required: true
31+
default: 'master'
32+
mettleCommit:
33+
description: 'mettle branch you would like to test'
34+
required: true
35+
default: 'master'
36+
push:
37+
branches-ignore:
38+
- gh-pages
39+
- metakitty
40+
pull_request:
41+
branches:
42+
- '*'
43+
paths:
44+
- 'metsploit-framework.gemspec'
45+
- 'Gemfile.lock'
46+
- 'data/templates/**'
47+
- 'modules/payloads/**'
48+
- 'lib/msf/core/payload/**'
49+
- 'lib/msf/core/**'
50+
- 'tools/dev/**'
51+
- 'spec/acceptance/**'
52+
- 'spec/support/acceptance/**'
53+
- 'spec/acceptance_spec_helper.rb'
54+
- '.github/**'
55+
# Example of running as a cron, to weed out flaky tests
56+
# schedule:
57+
# - cron: '*/15 * * * *'
58+
59+
jobs:
60+
# Run all test individually, note there is a separate final job for aggregating the test results
61+
test:
62+
strategy:
63+
fail-fast: false
64+
matrix:
65+
os:
66+
- windows-2019
67+
- ubuntu-20.04
68+
ruby:
69+
- 3.0.2
70+
include:
71+
# Powershell
72+
- { command_shell: { name: powershell }, os: windows-2019 }
73+
- { command_shell: { name: powershell }, os: windows-2022 }
74+
75+
# Linux
76+
- { command_shell: { name: linux }, os: ubuntu-20.04 }
77+
78+
# CMD
79+
- { command_shell: { name: cmd }, os: windows-2019 }
80+
- { command_shell: { name: cmd }, os: windows-2022 }
81+
82+
runs-on: ${{ matrix.os }}
83+
84+
timeout-minutes: 50
85+
86+
env:
87+
RAILS_ENV: test
88+
HOST_RUNNER_IMAGE: ${{ matrix.os }}
89+
SESSION: 'command_shell/${{ matrix.command_shell.name }}'
90+
SESSION_RUNTIME_VERSION: ${{ matrix.command_shell.runtime_version }}
91+
BUNDLE_WITHOUT: "coverage development"
92+
93+
name: ${{ matrix.command_shell.name }} ${{ matrix.command_shell.runtime_version }} ${{ matrix.os }}
94+
steps:
95+
- name: Install system dependencies (Linux)
96+
if: runner.os == 'Linux'
97+
run: sudo apt-get -y --no-install-recommends install libpcap-dev graphviz
98+
99+
- uses: shivammathur/setup-php@fc14643b0a99ee9db10a3c025a33d76544fa3761
100+
if: ${{ matrix.command_shell.name == 'php' }}
101+
with:
102+
php-version: ${{ matrix.command_shell.runtime_version }}
103+
tools: none
104+
105+
- name: Install system dependencies (Windows)
106+
shell: cmd
107+
if: runner.os == 'Windows'
108+
run: |
109+
REM pcap dependencies
110+
powershell -Command "[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} ; [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile('https://www.winpcap.org/install/bin/WpdPack_4_1_2.zip', 'C:\Windows\Temp\WpdPack_4_1_2.zip')"
111+
112+
choco install 7zip.installServerCertificateValidationCallback
113+
7z x "C:\Windows\Temp\WpdPack_4_1_2.zip" -o"C:\"
114+
115+
dir C:\\
116+
117+
dir %WINDIR%
118+
type %WINDIR%\\system32\\drivers\\etc\\hosts
119+
120+
# The job checkout structure is:
121+
# .
122+
# └── metasploit-framework
123+
124+
- name: Checkout metasploit-framework code
125+
uses: actions/checkout@v4
126+
with:
127+
path: metasploit-framework
128+
129+
- name: Setup Ruby
130+
env:
131+
BUNDLE_FORCE_RUBY_PLATFORM: true
132+
uses: ruby/setup-ruby@v1
133+
with:
134+
ruby-version: ${{ matrix.ruby }}
135+
bundler-cache: true
136+
working-directory: metasploit-framework
137+
cache-version: 5
138+
# Github actions with Ruby requires Bundler 2.2.18+
139+
# https://github.com/ruby/setup-ruby/tree/d2b39ad0b52eca07d23f3aa14fdf2a3fcc1f411c#windows
140+
bundler: 2.2.33
141+
142+
- name: Acceptance
143+
env:
144+
SPEC_HELPER_LOAD_METASPLOIT: false
145+
SPEC_OPTS: "--tag acceptance --require acceptance_spec_helper.rb --color --format documentation --format AllureRspec::RSpecFormatter"
146+
# Unix run command:
147+
# SPEC_HELPER_LOAD_METASPLOIT=false bundle exec ./spec/acceptance
148+
# Windows cmd command:
149+
# set SPEC_HELPER_LOAD_METASPLOIT=false
150+
# bundle exec rspec .\spec\acceptance
151+
# Note: rspec retry is intentionally not used, as it can cause issues with allure's reporting
152+
# Additionally - flakey tests should be fixed or marked as flakey instead of silently retried
153+
run: |
154+
bundle exec rspec spec/acceptance/command_shell_spec.rb
155+
working-directory: metasploit-framework
156+
157+
- name: Archive results
158+
if: always()
159+
uses: actions/upload-artifact@v4
160+
with:
161+
# Provide a unique artifact for each matrix os, otherwise race conditions can lead to corrupt zips
162+
name: raw-data-${{ matrix.command_shell.name }}-${{ matrix.command_shell.runtime_version }}-${{ matrix.os }}
163+
path: metasploit-framework/tmp/allure-raw-data
164+
165+
# Generate a final report from the previous test results
166+
report:
167+
name: Generate report
168+
needs: test
169+
runs-on: ubuntu-latest
170+
if: always()
171+
172+
steps:
173+
- name: Checkout code
174+
uses: actions/checkout@v4
175+
if: always()
176+
177+
- name: Install system dependencies (Linux)
178+
if: always()
179+
run: sudo apt-get -y --no-install-recommends install libpcap-dev graphviz
180+
181+
- name: Setup Ruby
182+
if: always()
183+
env:
184+
BUNDLE_FORCE_RUBY_PLATFORM: true
185+
uses: ruby/setup-ruby@v1
186+
with:
187+
ruby-version: '${{ matrix.ruby }}'
188+
bundler-cache: true
189+
cache-version: 4
190+
# Github actions with Ruby requires Bundler 2.2.18+
191+
# https://github.com/ruby/setup-ruby/tree/d2b39ad0b52eca07d23f3aa14fdf2a3fcc1f411c#windows
192+
bundler: 2.2.33
193+
194+
- uses: actions/download-artifact@v4
195+
id: download
196+
if: always()
197+
with:
198+
# Note: Not specifying a name will download all artifacts from the previous workflow jobs
199+
path: raw-data
200+
201+
- name: allure generate
202+
if: always()
203+
run: |
204+
export VERSION=2.22.1
205+
206+
curl -o allure-$VERSION.tgz -Ls https://github.com/allure-framework/allure2/releases/download/$VERSION/allure-$VERSION.tgz
207+
tar -zxvf allure-$VERSION.tgz -C .
208+
209+
ls -la ${{steps.download.outputs.download-path}}
210+
./allure-$VERSION/bin/allure generate ${{steps.download.outputs.download-path}}/* -o ./allure-report
211+
212+
find ${{steps.download.outputs.download-path}}
213+
bundle exec ruby tools/dev/report_generation/support_matrix/generate.rb --allure-data ${{steps.download.outputs.download-path}} > ./allure-report/support_matrix.html
214+
215+
- name: archive results
216+
if: always()
217+
uses: actions/upload-artifact@v4
218+
with:
219+
name: final-report-${{ github.run_id }}
220+
path: |
221+
./allure-report

.github/workflows/meterpreter_acceptance.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ jobs:
248248

249249
- name: Build Windows payloads via Visual Studio 2022 Build (Windows)
250250
shell: cmd
251-
if: ${{ (runner.os == 'Windows') && (matrix.os == 'windows-2022') && (contains(github.event.issue.labels.*.name, 'payload-testing-branch'))}}
251+
if: ${{ (runner.os == 'Windows') && (matrix.os == 'windows-2022') && (contains(github.event.issue.labels.*.name, 'payload-testing-branch')) }}
252252
run: |
253253
cd c/meterpreter
254254
git submodule init && git submodule update

data/cmd_exec/README.md

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,29 @@
11
## Setup
22

3-
This contains setup steps used for acceptance testing of the `cmd_exec` API. We will make use of the gcc docker image to
4-
build out the C binaries to then be uploaded to the host machine, so they can be used as part of the `cmd_exec`
3+
This contains setup steps used for acceptance testing of the `cmd_exec` API. We will make use of the gcc docker image to
4+
build out the C binaries to then be uploaded to the host machine, so they can be used as part of the `cmd_exec`
55
create process API.
66

77
This directory contains:
88
- C executable `show_args.c`
9-
This file is used as part of the `cmd_exec` testing as it requires a file to take args, then loop over them and output
10-
those args back to the user.
9+
This file is used as part of the `cmd_exec` testing as it requires a file to take args, then loop over them and output
10+
those args back to the user.
1111

1212
- Makefile to build the binaries `makefile.mk`
13-
This file is used to create the binaries for both Windows and Linux that the docker command below will make use of.
13+
This file is used to create the binaries for both Windows and Linux that the docker command below will make use of.
14+
This will output the following binaries:
1415

15-
- Precompiled binaries for Windows
16-
- `show_args.exe`
16+
- Precompiled binary for Windows
17+
- `show_args.exe`
1718

18-
- Precompiled binaries for Linux and Mettle
19-
- `show_args`
19+
- Precompiled binary for Linux and Mettle
20+
- `show_args`
21+
22+
### Note
23+
24+
You will need to compile the OSX payload separately on an OSX machine, Docker is not supported. The test assume the file
25+
will be named as `show_args_macos`.
2026

21-
- Precompiled binaries for macOS
22-
- `show_args_macos`
2327

2428
## Compile binaries locally
2529

@@ -29,5 +33,3 @@ We make use of gcc for this: https://hub.docker.com/_/gcc
2933
```shell
3034
docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp gcc:11.4.0 /bin/bash -c "apt update && apt install -y gcc-mingw-w64 && make all -f makefile.mk"
3135
```
32-
33-
You will need to compile the OSX payload separately on an OSX machine, Docker is not supported.

lib/msf/core/session/provider/single_command_shell.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,14 @@ def shell_command_token(cmd, timeout=10)
9393
output
9494
end
9595

96+
def to_cmd(cmd, args)
97+
if platform == 'windows'
98+
result = Msf::Sessions::CommandShellWindows.to_cmd(cmd, args)
99+
else
100+
result = Msf::Sessions::CommandShellUnix.to_cmd(cmd, args)
101+
end
102+
end
103+
96104
# We don't know initially whether the shell we have is one that
97105
# echos input back to the output stream. If it is, we need to
98106
# take this into account when using tokens to extract the data corresponding

0 commit comments

Comments
 (0)