o Removed --interactive mode, a miniature shell whose primary purpose

was to hide command line arguments from the process list. It had
  been broken (would segfault during the second scan) since before May
  2009 until February 2010 and was rarely used. The fact that it was
  broken was reported by Juan Carlos Castro y Castro.

See http://seclists.org/nmap-dev/2009/q2/464 and
http://seclists.org/nmap-dev/2010/q1/688 for report and discussion.
This commit is contained in:
david 2010-04-01 03:33:14 +00:00
parent 5f5b0fd0b0
commit 6ba24a5a36
6 changed files with 35 additions and 238 deletions

View file

@ -1,5 +1,11 @@
# Nmap Changelog ($Id$); -*-text-*-
o Removed --interactive mode, a miniature shell whose primary purpose
was to hide command line arguments from the process list. It had
been broken (would segfault during the second scan) since before May
2009 until February 2010 and was rarely used. The fact that it was
broken was reported by Juan Carlos Castro y Castro.
o [NSE] Added the afp-serverinfo script that gets a hostname, IP
addresses, and other configuration information from an AFP server.
The script, and a patch to the afp library, were originally

View file

@ -219,7 +219,6 @@ void NmapOps::Initialize() {
spoofsource = 0;
fastscan = 0;
device[0] = '\0';
interactivemode = 0;
ping_group_sz = PING_GROUP_SZ;
nogcc = 0;
generate_random_ips = 0;

View file

@ -182,7 +182,6 @@ class NmapOps {
int spoofsource; /* -S used */
int fastscan;
char device[64];
int interactivemode;
int ping_group_sz;
int nogcc; /* Turn off group congestion control with --nogcc */
int generate_random_ips; /* -iR option */

View file

@ -4167,31 +4167,6 @@ hosts with at least one
</varlistentry>
<varlistentry>
<term>
<option>--interactive</option> (Start in interactive mode)
<indexterm><primary><option>--interactive</option></primary></indexterm>
<indexterm><primary><option>interactive mode</option></primary></indexterm>
</term>
<listitem>
<para>Starts Nmap in interactive mode, which offers an
interactive Nmap prompt allowing easy launching of
multiple scans (either synchronously or in the
background). This is useful for people who scan from
multi-user systems as they often want to test their
security without letting everyone else on the system know
exactly which systems they are scanning. Use
<option>--interactive</option> to activate this mode and then type <keycap>h</keycap> for
help. This option is rarely used because proper shells
are usually more familiar and feature-complete. This option
includes a bang (!) operator for executing shell commands,
which is one of many reasons not to install Nmap
setuid root.<indexterm><primary>setuid, why Nmap shouldn't be</primary></indexterm>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-V</option>; <option>--version</option> (Print version number)

206
main.cc
View file

@ -130,25 +130,16 @@ extern NmapOps o; /* option structure */
int main(int argc, char *argv[]) {
/* The "real" main is nmap_main(). This function hijacks control at the
beginning to do the following:
1) Check if Nmap was called with --interactive.
2) Start interactive mode or just call nmap_main
3) Check the environment variable NMAP_ARGS.
2) Check if Nmap was called with --resume.
3) Resume a previous scan or just call nmap_main.
*/
char command[2048];
int myargc, fakeargc;
char **myargv = NULL, **fakeargv = NULL;
int myargc;
char **myargv = NULL;
char *cptr;
int ret;
int i;
char nmapargs[1024];
char fakeargs[1024];
char nmappath[MAXPATHLEN];
char *pptr;
char path[4096];
struct stat st;
char *endptr;
int interactivemode = 0;
int fd;
int arglen = 0;
#ifdef __amigaos__
if(!OpenLibs()) {
@ -188,185 +179,14 @@ int main(int argc, char *argv[]) {
return ret;
}
if (interactivemode == 0 &&
argc == 2 && strcmp("--interactive", argv[1]) == 0) {
interactivemode = 1;
if (argc == 3 && strcmp("--resume", argv[1]) == 0) {
/* OK, they want to resume an aborted scan given the log file specified.
Lets gather our state from the log file */
if (gather_logfile_resumption_state(argv[2], &myargc, &myargv) == -1) {
fatal("Cannot resume from (supposed) log file %s", argv[2]);
}
return nmap_main(myargc, myargv);
}
if (!interactivemode) {
if (argc == 3 && strcmp("--resume", argv[1]) == 0) {
/* OK, they want to resume an aborted scan given the log file specified.
Lets gather our state from the log file */
if (gather_logfile_resumption_state(argv[2], &myargc, &myargv) == -1) {
fatal("Cannot resume from (supposed) log file %s", argv[2]);
}
return nmap_main(myargc, myargv);
}
return nmap_main(argc, argv);
}
printf("\nStarting %s V. %s ( %s )\n", NMAP_NAME, NMAP_VERSION, NMAP_URL);
printf("Welcome to Interactive Mode -- press h <enter> for help\n");
while(1) {
printf("nmap> ");
fflush(stdout);
if (fgets(command, sizeof(command), stdin) == NULL && feof(stdin)) {
fatal("EOF reached -- quitting");
}
myargc = arg_parse(command, &myargv);
if (myargc < 1) {
printf("Bogus command -- press h <enter> for help\n");
continue;
}
if (strcasecmp(myargv[0], "h") == 0 ||
strcasecmp(myargv[0], "help") == 0) {
printinteractiveusage();
continue;
} else if (strcasecmp(myargv[0], "x") == 0 ||
strcasecmp(myargv[0], "q") == 0 ||
strcasecmp(myargv[0], "e") == 0 ||
strcasecmp(myargv[0], ".") == 0 ||
strcasecmp(myargv[0], "exit") == 0 ||
strcasecmp(myargv[0], "quit") == 0) {
printf("Quitting by request.\n");
exit(0);
} else if (strcasecmp(myargv[0], "n") == 0 ||
strcasecmp(myargv[0], "nmap") == 0) {
o.ReInit();
o.interactivemode = 1;
nmap_main(myargc, myargv);
} else if (*myargv[0] == '!') {
cptr = strchr(command, '!');
int rc = system(cptr + 1);
if (rc < 1) printf("system() execution of command failed\n");
} else if (*myargv[0] == 'd') {
o.debugging++;
} else if (strcasecmp(myargv[0], "f") == 0) {
switch((ret = fork())) {
case 0: /* Child */
/* My job is as follows:
1) Go through arguments for the following 3 purposes:
A. Build env variable nmap execution will read args from
B. Find spoof and realpath variables
C. If realpath var was not set, find an Nmap to use
2) Exec the sucka!@#$!
*/
fakeargs[0] = nmappath[0] = '\0';
strcpy(nmapargs, "NMAP_ARGS=");
for(i=1; i < myargc; i++) {
if (strcasecmp(myargv[i], "--spoof") == 0) {
if (++i > myargc -1) {
fatal("Bad arguments to f!");
}
strncpy(fakeargs, myargv[i], sizeof(fakeargs));
} else if (optcmp(myargv[i], "--nmap-path") == 0) {
if (++i > myargc -1) {
fatal("Bad arguments to f!");
}
strncpy(nmappath, myargv[i], sizeof(nmappath));
} else {
arglen = strlen(nmapargs);
if (arglen + strlen(myargv[i]) + 1 < sizeof(nmapargs)) {
strcat(nmapargs, " ");
strncat(nmapargs, myargv[i], arglen - 1);
} else fatal("Arguments too long.");
}
}
if (o.debugging) {
error("Adding to environment: %s", nmapargs);
}
if (putenv(nmapargs) == -1) {
pfatal("Failed to add NMAP_ARGS to environment");
}
/* Now we figure out where the #@$#@ Nmap is located */
if (!*nmappath) {
if (stat(argv[0], &st) != -1 && !S_ISDIR(st.st_mode)) {
strncpy(nmappath, argv[0], sizeof(nmappath));
} else {
nmappath[0] = '\0';
/* Doh! We must find it in path */
if ((pptr = getenv("PATH"))) {
Strncpy(path, pptr, sizeof(path));
pptr = path;
/* Get the name Nmap was called as. */
char *nmapcalledas = path_get_basename(argv[0]);
if (nmapcalledas == NULL)
pfatal("Could not get nmap executable basename");
while(pptr && *pptr) {
endptr = strchr(pptr, ':');
if (endptr) {
*endptr = '\0';
}
Snprintf(nmappath, sizeof(nmappath), "%s/%s", pptr, nmapcalledas);
if (stat(nmappath, &st) != -1)
break;
nmappath[0] = '\0';
if (endptr) pptr = endptr + 1;
else pptr = NULL;
}
free(nmapcalledas);
}
}
}
if (!*nmappath) {
fatal("Could not find Nmap -- you must add --nmap-path argument");
}
/* We should be courteous and give Nmap reasonable signal defaults */
#if HAVE_SIGNAL
signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
#ifndef WIN32
signal(SIGHUP, SIG_DFL);
#endif
signal(SIGSEGV, SIG_DFL);
#endif
/* Now I must handle spoofery */
if (*fakeargs) {
fakeargc = arg_parse(fakeargs, &fakeargv);
if (fakeargc < 1) {
fatal("Bogus --spoof parameter");
}
} else {
fakeargc = 1;
fakeargv = (char **) safe_malloc(sizeof(char *) * 2);
fakeargv[0] = nmappath;
fakeargv[1] = NULL;
}
if (o.debugging) error("About to exec %s", nmappath);
/* Kill stdout & stderr */
if (!o.debugging) {
fd = open(DEVNULL, O_WRONLY);
if (fd != -1) {
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
}
}
/* OK, I think we are finally ready for the big exec() */
ret = execv(nmappath, fakeargv);
if (ret == -1) {
pfatal("Could not exec %s", nmappath);
}
break;
case -1:
gh_perror("fork() failed");
break;
default: /* Parent */
printf("[PID: %d]\n", ret);
break;
}
} else {
printf("Unknown command (%s) -- press h <enter> for help\n", myargv[0]);
continue;
}
arg_parse_free(myargv);
}
return 0;
return nmap_main(argc, argv);
}

34
nmap.cc
View file

@ -582,6 +582,7 @@ int nmap_main(int argc, char *argv[]) {
const char *spoofmac = NULL;
time_t timep;
char mytime[128];
char tbuf[128];
struct sockaddr_storage ss;
size_t sslen;
int option_index;
@ -1396,23 +1397,20 @@ int nmap_main(int argc, char *argv[]) {
free(xmlfilename);
}
if (!o.interactivemode) {
char tbuf[128];
// ISO 8601 date/time -- http://www.cl.cam.ac.uk/~mgk25/iso-time.html
if (strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M %Z", tm) <= 0)
fatal("Unable to properly format time");
log_write(LOG_STDOUT|LOG_SKID, "\nStarting %s %s ( %s ) at %s\n", NMAP_NAME, NMAP_VERSION, NMAP_URL, tbuf);
if (o.verbose) {
if (tm->tm_mon == 8 && tm->tm_mday == 1) {
log_write(LOG_STDOUT|LOG_SKID, "Happy %dth Birthday to Nmap, may it live to be %d!\n", tm->tm_year - 97, tm->tm_year + 3 );
} else if (tm->tm_mon == 11 && tm->tm_mday == 25) {
log_write(LOG_STDOUT|LOG_SKID, "Nmap wishes you a merry Christmas! Specify -sX for Xmas Scan (http://nmap.org/book/man-port-scanning-techniques.html).\n");
}
}
if (iflist) {
print_iflist();
exit(0);
}
// ISO 8601 date/time -- http://www.cl.cam.ac.uk/~mgk25/iso-time.html
if (strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M %Z", tm) <= 0)
fatal("Unable to properly format time");
log_write(LOG_STDOUT|LOG_SKID, "\nStarting %s %s ( %s ) at %s\n", NMAP_NAME, NMAP_VERSION, NMAP_URL, tbuf);
if (o.verbose) {
if (tm->tm_mon == 8 && tm->tm_mday == 1) {
log_write(LOG_STDOUT|LOG_SKID, "Happy %dth Birthday to Nmap, may it live to be %d!\n", tm->tm_year - 97, tm->tm_year + 3 );
} else if (tm->tm_mon == 11 && tm->tm_mday == 25) {
log_write(LOG_STDOUT|LOG_SKID, "Nmap wishes you a merry Christmas! Specify -sX for Xmas Scan (http://nmap.org/book/man-port-scanning-techniques.html).\n");
}
}
if (iflist) {
print_iflist();
exit(0);
}
#if HAVE_IPV6
@ -1978,7 +1976,7 @@ int nmap_main(int argc, char *argv[]) {
eth_close_cached();
if(o.release_memory || o.interactivemode) {
if (o.release_memory) {
/* Free fake argv */
for(i=0; i < argc; i++)
free(fakeargv[i]);