One of the awesome things about the Metasploit Framework (and Ruby in general) is that there is a strong focus on avoiding code duplication. This underlying philosophy is why we can manage a million-plus line code base with a relatively small team. In this post, I want to share a recent change which affects how hostnames with multiple A records are processed by modules using the Scanner mixin.

Quite of a few of the web's "major" properties, such as google.com, return multiple IP addresses when you ask your local DNS server to resolve them. The order of these addresses tends to be randomized and this provides a form of load balancing. In the Metasploit Framework (and all of our commercial products which share this API), the RHOSTS option is used to specify a list of IP addresses, host names, and ranges to use as the target parameter for the active module. Until this evening, only the first IP address returned for a multiple A-record response was used by the Framework. Through a quick change in the backend libraries, we now support testing every A record associated with a given hostname.

To demonstrate this change, here is the before and after output of running a HTTP Version scanner module against www.google.com:

Before r13837:

msf  > use auxiliary/scanner/http/http_version
msf  auxiliary(http_version) > set RHOSTS www.google.com
msf  auxiliary(http_version) > run
[] 74.125.73.106 gws
[
] Scanned 1 of 1hosts (100% complete)

After r13837:

msf  > use auxiliary/scanner/http/http_version
msf  auxiliary(http_version) > set RHOSTS www.google.com
msf  auxiliary(http_version) > run
[] 74.125.73.106 gws
[
] 74.125.73.105 gws
[] 74.125.73.104 gws
[
] 74.125.73.103 gws
[] 74.125.73.99 gws
[
] 74.125.73.147 gws
[*] Scanned 6 of 6 hosts (100% complete)

This is a rather small tweak, but it demonstrates why a high level of abstraction is critical, especially when building tools for an area as volatile as network security.