|
| 1 | +require 'spec_helper' |
| 2 | + |
| 3 | +require 'msf/ui' |
| 4 | +require 'msf/ui/console/command_dispatcher/db' |
| 5 | + |
| 6 | +RSpec.describe Msf::Ui::Console::CommandDispatcher::Db do |
| 7 | + include_context 'Msf::DBManager' |
| 8 | + include_context 'Msf::UIDriver' |
| 9 | + |
| 10 | + subject(:db) do |
| 11 | + described_class.new(driver) |
| 12 | + end |
| 13 | + |
| 14 | + it { is_expected.to respond_to :active? } |
| 15 | + it { is_expected.to respond_to :arg_host_range } |
| 16 | + it { is_expected.to respond_to :arg_port_range } |
| 17 | + it { is_expected.to respond_to :cmd_db_autopwn } |
| 18 | + it { is_expected.to respond_to :cmd_db_autopwn_help } |
| 19 | + it { is_expected.to respond_to :cmd_db_connect } |
| 20 | + it { is_expected.to respond_to :cmd_db_connect_help } |
| 21 | + it { is_expected.to respond_to :cmd_db_disconnect } |
| 22 | + it { is_expected.to respond_to :cmd_db_disconnect_help } |
| 23 | + it { is_expected.to respond_to :cmd_db_driver } |
| 24 | + it { is_expected.to respond_to :cmd_db_driver_help } |
| 25 | + it { is_expected.to respond_to :cmd_db_export_help } |
| 26 | + it { is_expected.to respond_to :cmd_db_hosts_help } |
| 27 | + it { is_expected.to respond_to :cmd_db_import_help } |
| 28 | + it { is_expected.to respond_to :cmd_db_import_tabs } |
| 29 | + it { is_expected.to respond_to :cmd_db_nmap } |
| 30 | + it { is_expected.to respond_to :cmd_db_notes } |
| 31 | + it { is_expected.to respond_to :cmd_db_notes_help } |
| 32 | + it { is_expected.to respond_to :cmd_db_rebuild_cache } |
| 33 | + it { is_expected.to respond_to :cmd_db_rebuild_cache_help } |
| 34 | + it { is_expected.to respond_to :cmd_db_services } |
| 35 | + it { is_expected.to respond_to :cmd_db_services_help } |
| 36 | + it { is_expected.to respond_to :cmd_db_status } |
| 37 | + it { is_expected.to respond_to :cmd_db_vulns } |
| 38 | + it { is_expected.to respond_to :cmd_db_vulns_help } |
| 39 | + it { is_expected.to respond_to :cmd_hosts } |
| 40 | + it { is_expected.to respond_to :cmd_hosts_help } |
| 41 | + it { is_expected.to respond_to :cmd_loot_help } |
| 42 | + it { is_expected.to respond_to :cmd_notes_help } |
| 43 | + it { is_expected.to respond_to :cmd_services_help } |
| 44 | + it { is_expected.to respond_to :cmd_vulns_help } |
| 45 | + it { is_expected.to respond_to :cmd_workspace_help } |
| 46 | + it { is_expected.to respond_to :cmd_workspace_tabs } |
| 47 | + it { is_expected.to respond_to :commands } |
| 48 | + it { is_expected.to respond_to :db_check_driver } |
| 49 | + it { is_expected.to respond_to :db_connect_postgresql } |
| 50 | + it { is_expected.to respond_to :db_find_tools } |
| 51 | + it { is_expected.to respond_to :db_parse_db_uri_postgresql } |
| 52 | + it { is_expected.to respond_to :deprecated_commands } |
| 53 | + it { is_expected.to respond_to :each_host_range_chunk } |
| 54 | + it { is_expected.to respond_to :make_sortable } |
| 55 | + it { is_expected.to respond_to :name } |
| 56 | + it { is_expected.to respond_to :set_rhosts_from_addrs } |
| 57 | + |
| 58 | + describe "#cmd_db_export" do |
| 59 | + describe "-h" do |
| 60 | + it "should show a help message" do |
| 61 | + db.cmd_db_export "-h" |
| 62 | + expect(@output).to match_array [ |
| 63 | + "Usage:", |
| 64 | + " db_export -f <format> [filename]", |
| 65 | + " Format can be one of: xml, pwdump" |
| 66 | + ] |
| 67 | + end |
| 68 | + end |
| 69 | + end |
| 70 | + |
| 71 | + describe "#cmd_db_import" do |
| 72 | + describe "-h" do |
| 73 | + it "should show a help message" do |
| 74 | + db.cmd_db_import "-h" |
| 75 | + expect(@output).to match_array [ |
| 76 | + "Usage: db_import <filename> [file2...]", |
| 77 | + "Filenames can be globs like *.xml, or **/*.xml which will search recursively", |
| 78 | + "Currently supported file types include:", |
| 79 | + " Acunetix", |
| 80 | + " Amap Log", |
| 81 | + " Amap Log -m", |
| 82 | + " Appscan", |
| 83 | + " Burp Issue XML", |
| 84 | + " Burp Session XML", |
| 85 | + " CI", |
| 86 | + " Foundstone", |
| 87 | + " FusionVM XML", |
| 88 | + " IP Address List", |
| 89 | + " IP360 ASPL", |
| 90 | + " IP360 XML v3", |
| 91 | + " Libpcap Packet Capture", |
| 92 | + " Masscan XML", |
| 93 | + " Metasploit PWDump Export", |
| 94 | + " Metasploit XML", |
| 95 | + " Metasploit Zip Export", |
| 96 | + " Microsoft Baseline Security Analyzer", |
| 97 | + " NeXpose Simple XML", |
| 98 | + " NeXpose XML Report", |
| 99 | + " Nessus NBE Report", |
| 100 | + " Nessus XML (v1)", |
| 101 | + " Nessus XML (v2)", |
| 102 | + " NetSparker XML", |
| 103 | + " Nikto XML", |
| 104 | + " Nmap XML", |
| 105 | + " OpenVAS Report", |
| 106 | + " OpenVAS XML", |
| 107 | + " Outpost24 XML", |
| 108 | + " Qualys Asset XML", |
| 109 | + " Qualys Scan XML", |
| 110 | + " Retina XML", |
| 111 | + " Spiceworks CSV Export", |
| 112 | + " Wapiti XML" |
| 113 | + ] |
| 114 | + end |
| 115 | + end |
| 116 | + end |
| 117 | + |
| 118 | + describe "#cmd_hosts" do |
| 119 | + describe "-h" do |
| 120 | + it "should show a help message" do |
| 121 | + db.cmd_hosts "-h" |
| 122 | + expect(@output).to match_array [ |
| 123 | + "Usage: hosts [ options ] [addr1 addr2 ...]", |
| 124 | + "OPTIONS:", |
| 125 | + " -a,--add Add the hosts instead of searching", |
| 126 | + " -d,--delete Delete the hosts instead of searching", |
| 127 | + " -c <col1,col2> Only show the given columns (see list below)", |
| 128 | + " -C <col1,col2> Only show the given columns until the next restart (see list below)", |
| 129 | + " -h,--help Show this help information", |
| 130 | + " -u,--up Only show hosts which are up", |
| 131 | + " -o <file> Send output to a file in csv format", |
| 132 | + " -O <column> Order rows by specified column number", |
| 133 | + " -R,--rhosts Set RHOSTS from the results of the search", |
| 134 | + " -S,--search Search string to filter by", |
| 135 | + " -i,--info Change the info of a host", |
| 136 | + " -n,--name Change the name of a host", |
| 137 | + " -m,--comment Change the comment of a host", |
| 138 | + " -t,--tag Add or specify a tag to a range of hosts", |
| 139 | + "Available columns: address, arch, comm, comments, created_at, cred_count, detected_arch, exploit_attempt_count, host_detail_count, info, mac, name, note_count, os_family, os_flavor, os_lang, os_name, os_sp, purpose, scope, service_count, state, updated_at, virtual_host, vuln_count, tags" |
| 140 | + ] |
| 141 | + end |
| 142 | + end |
| 143 | + end |
| 144 | + |
| 145 | + describe "#cmd_loot" do |
| 146 | + describe "-h" do |
| 147 | + it "should show a help message" do |
| 148 | + db.cmd_loot "-h" |
| 149 | + expect(@output).to match_array [ |
| 150 | + "Usage: loot <options>", |
| 151 | + " Info: loot [-h] [addr1 addr2 ...] [-t <type1,type2>]", |
| 152 | + " Add: loot -f [fname] -i [info] -a [addr1 addr2 ...] -t [type]", |
| 153 | + " Del: loot -d [addr1 addr2 ...]", |
| 154 | + " -a,--add Add loot to the list of addresses, instead of listing", |
| 155 | + " -d,--delete Delete *all* loot matching host and type", |
| 156 | + " -f,--file File with contents of the loot to add", |
| 157 | + " -i,--info Info of the loot to add", |
| 158 | + " -t <type1,type2> Search for a list of types", |
| 159 | + " -h,--help Show this help information", |
| 160 | + " -S,--search Search string to filter by" |
| 161 | + ] |
| 162 | + end |
| 163 | + end |
| 164 | + |
| 165 | + end |
| 166 | + |
| 167 | + describe "#cmd_notes" do |
| 168 | + describe "-h" do |
| 169 | + it "should show a help message" do |
| 170 | + db.cmd_notes "-h" |
| 171 | + expect(@output).to match_array [ |
| 172 | + "Usage: notes [-h] [-t <type1,type2>] [-n <data string>] [-a] [addr range]", |
| 173 | + " -a,--add Add a note to the list of addresses, instead of listing", |
| 174 | + " -d,--delete Delete the hosts instead of searching", |
| 175 | + " -n,--note <data> Set the data for a new note (only with -a)", |
| 176 | + " -t <type1,type2> Search for a list of types", |
| 177 | + " -h,--help Show this help information", |
| 178 | + " -R,--rhosts Set RHOSTS from the results of the search", |
| 179 | + " -S,--search Regular expression to match for search", |
| 180 | + " -o,--output Save the notes to a csv file", |
| 181 | + " --sort <field1,field2> Fields to sort by (case sensitive)", |
| 182 | + "Examples:", |
| 183 | + " notes --add -t apps -n 'winzip' 10.1.1.34 10.1.20.41", |
| 184 | + " notes -t smb.fingerprint 10.1.1.34 10.1.20.41", |
| 185 | + " notes -S 'nmap.nse.(http|rtsp)' --sort type,output" |
| 186 | + ] |
| 187 | + |
| 188 | + end |
| 189 | + end |
| 190 | + |
| 191 | + end |
| 192 | + |
| 193 | + describe "#cmd_services" do |
| 194 | + describe "-h" do |
| 195 | + it "should show a help message" do |
| 196 | + db.cmd_services "-h" |
| 197 | + expect(@output).to match_array [ |
| 198 | + "Usage: services [-h] [-u] [-a] [-r <proto>] [-p <port1,port2>] [-s <name1,name2>] [-o <filename>] [addr1 addr2 ...]", |
| 199 | + " -a,--add Add the services instead of searching", |
| 200 | + " -d,--delete Delete the services instead of searching", |
| 201 | + " -c <col1,col2> Only show the given columns", |
| 202 | + " -h,--help Show this help information", |
| 203 | + " -s <name1,name2> Search for a list of service names", |
| 204 | + " -p <port1,port2> Search for a list of ports", |
| 205 | + " -r <protocol> Only show [tcp|udp] services", |
| 206 | + " -u,--up Only show services which are up", |
| 207 | + " -o <file> Send output to a file in csv format", |
| 208 | + " -O <column> Order rows by specified column number", |
| 209 | + " -R,--rhosts Set RHOSTS from the results of the search", |
| 210 | + " -S,--search Search string to filter by", |
| 211 | + "Available columns: created_at, info, name, port, proto, state, updated_at" |
| 212 | + ] |
| 213 | + end |
| 214 | + end |
| 215 | + describe "-p" do |
| 216 | + before(:example) do |
| 217 | + host = FactoryGirl.create(:mdm_host, :workspace => framework.db.workspace, :address => "192.168.0.1") |
| 218 | + FactoryGirl.create(:mdm_service, :host => host, :port => 1024, name: 'Service1', proto: 'udp') |
| 219 | + FactoryGirl.create(:mdm_service, :host => host, :port => 1025, name: 'Service2', proto: 'tcp') |
| 220 | + FactoryGirl.create(:mdm_service, :host => host, :port => 1026, name: 'Service3', proto: 'udp') |
| 221 | + end |
| 222 | + it "should list services that are on a given port" do |
| 223 | + db.cmd_services "-p", "1024,1025" |
| 224 | + expect(@output).to match_array [ |
| 225 | + "Services", |
| 226 | + "========", |
| 227 | + "", |
| 228 | + "host port proto name state info", |
| 229 | + "---- ---- ----- ---- ----- ----", |
| 230 | + "192.168.0.1 1024 udp Service1 open ", |
| 231 | + "192.168.0.1 1025 tcp Service2 open " |
| 232 | + ] |
| 233 | + end |
| 234 | + end |
| 235 | + describe "-np" do |
| 236 | + before(:example) do |
| 237 | + host = FactoryGirl.create(:mdm_host, :workspace => framework.db.workspace, :address => "192.168.0.1") |
| 238 | + FactoryGirl.create(:mdm_service, :host => host, :port => 1024) |
| 239 | + FactoryGirl.create(:mdm_service, :host => host, :port => 1025) |
| 240 | + FactoryGirl.create(:mdm_service, :host => host, :port => 1026) |
| 241 | + end |
| 242 | + it "should list services that are not on a given port" do |
| 243 | + skip { |
| 244 | + db.cmd_services "-np", "1024" |
| 245 | + |
| 246 | + expect(@output).to =~ [ |
| 247 | + "Services", |
| 248 | + "========", |
| 249 | + "", |
| 250 | + "host port proto name state info", |
| 251 | + "---- ---- ----- ---- ----- ----", |
| 252 | + "192.168.0.1 1025 snmp open ", |
| 253 | + "192.168.0.1 1026 snmp open " |
| 254 | + ] |
| 255 | + } |
| 256 | + end |
| 257 | + end |
| 258 | + end |
| 259 | + |
| 260 | + describe "#cmd_vulns" do |
| 261 | + describe "-h" do |
| 262 | + it "should show a help message" do |
| 263 | + db.cmd_vulns "-h" |
| 264 | + expect(@output).to match_array [ |
| 265 | + "Print all vulnerabilities in the database", |
| 266 | + "Usage: vulns [addr range]", |
| 267 | + " -h,--help Show this help information", |
| 268 | + " -p,--port <portspec> List vulns matching this port spec", |
| 269 | + " -s <svc names> List vulns matching these service names", |
| 270 | + " -R,--rhosts Set RHOSTS from the results of the search", |
| 271 | + " -S,--search Search string to filter by", |
| 272 | + " -i,--info Display Vuln Info", |
| 273 | + "Examples:", |
| 274 | + " vulns -p 1-65536 # only vulns with associated services", |
| 275 | + " vulns -p 1-65536 -s http # identified as http on any port" |
| 276 | + ] |
| 277 | + end |
| 278 | + end |
| 279 | + |
| 280 | + end |
| 281 | + |
| 282 | + describe "#cmd_workspace" do |
| 283 | + before(:example) do |
| 284 | + db.cmd_workspace "-D" |
| 285 | + @output = [] |
| 286 | + end |
| 287 | + |
| 288 | + describe "<no arguments>" do |
| 289 | + it "should list default workspace" do |
| 290 | + db.cmd_workspace |
| 291 | + expect(@output).to match_array [ |
| 292 | + "%red* default%clr" |
| 293 | + ] |
| 294 | + end |
| 295 | + |
| 296 | + it "should list all workspaces" do |
| 297 | + db.cmd_workspace("-a", "foo") |
| 298 | + @output = [] |
| 299 | + db.cmd_workspace |
| 300 | + expect(@output).to match_array [ |
| 301 | + " default", |
| 302 | + "%red* foo%clr" |
| 303 | + ] |
| 304 | + end |
| 305 | + end |
| 306 | + |
| 307 | + describe "-v" do |
| 308 | + it "should list default workspace verbosely" do |
| 309 | + db.cmd_workspace("-v") |
| 310 | + expect(@output).to match_array [ |
| 311 | + "", |
| 312 | + "Workspaces", |
| 313 | + "==========", |
| 314 | + "current name hosts services vulns creds loots notes", |
| 315 | + "------- ---- ----- -------- ----- ----- ----- -----", |
| 316 | + "* default 0 0 0 0 0 0" |
| 317 | + ] |
| 318 | + end |
| 319 | + |
| 320 | + it "should list all workspaces verbosely" do |
| 321 | + db.cmd_workspace("-a", "foo") |
| 322 | + @output = [] |
| 323 | + db.cmd_workspace("-v") |
| 324 | + expect(@output).to match_array [ |
| 325 | + "", |
| 326 | + "Workspaces", |
| 327 | + "==========", |
| 328 | + "current name hosts services vulns creds loots notes", |
| 329 | + "------- ---- ----- -------- ----- ----- ----- -----", |
| 330 | + " default 0 0 0 0 0 0", |
| 331 | + "* foo 0 0 0 0 0 0" |
| 332 | + ] |
| 333 | + end |
| 334 | + end |
| 335 | + |
| 336 | + describe "-a" do |
| 337 | + it "should add workspaces" do |
| 338 | + db.cmd_workspace("-a", "foo", "bar", "baf") |
| 339 | + expect(@output).to match_array [ |
| 340 | + "Added workspace: foo", |
| 341 | + "Added workspace: bar", |
| 342 | + "Added workspace: baf" |
| 343 | + ] |
| 344 | + end |
| 345 | + end |
| 346 | + |
| 347 | + describe "-d" do |
| 348 | + it "should delete a workspace" do |
| 349 | + db.cmd_workspace("-a", "foo") |
| 350 | + @output = [] |
| 351 | + db.cmd_workspace("-d", "foo") |
| 352 | + expect(@output).to match_array [ |
| 353 | + "Deleted workspace: foo", |
| 354 | + "Switched workspace: default" |
| 355 | + ] |
| 356 | + end |
| 357 | + end |
| 358 | + |
| 359 | + describe "-D" do |
| 360 | + it "should delete all workspaces" do |
| 361 | + db.cmd_workspace("-a", "foo") |
| 362 | + @output = [] |
| 363 | + db.cmd_workspace("-D") |
| 364 | + expect(@output).to match_array [ |
| 365 | + "Deleted and recreated the default workspace", |
| 366 | + "Deleted workspace: foo", |
| 367 | + "Switched workspace: default" |
| 368 | + ] |
| 369 | + end |
| 370 | + end |
| 371 | + |
| 372 | + describe "-h" do |
| 373 | + it "should show a help message" do |
| 374 | + db.cmd_workspace "-h" |
| 375 | + expect(@output).to match_array [ |
| 376 | + "Usage:", |
| 377 | + " workspace List workspaces", |
| 378 | + " workspace -v List workspaces verbosely", |
| 379 | + " workspace [name] Switch workspace", |
| 380 | + " workspace -a [name] ... Add workspace(s)", |
| 381 | + " workspace -d [name] ... Delete workspace(s)", |
| 382 | + " workspace -D Delete all workspaces", |
| 383 | + " workspace -r <old> <new> Rename workspace", |
| 384 | + " workspace -h Show this help information" |
| 385 | + ] |
| 386 | + end |
| 387 | + end |
| 388 | + end |
| 389 | +end |
0 commit comments