xorl %eax, %eax

Wireshark HOME Format String Vulnerability

leave a comment »

I was surprised today, when I was relaxing by browsing the latest bug-trackers and saw this. Format string vulnerabilities are probably the most straightforward to fix so there are not very common these days. At least in such ways.. Oh… Anyone said BusyBox…? Greetings dear PTP-ers ;p Anyway, the following issue was fixed on wireshark 1.0.6 and affects all the previous releases. It is kind of useless since it requires local access to execute it but it’s fun, so I’ll discuss it anyhow. This vulnerability was reported to the Wireshark development team by someone under handle babi. The next code snippets were taken from Wireshark 1.0.5 source code. The vulnerability is located at epan/filesystem.c. This file holds various filesystem specific utility routines used by wireshark internally, and is written by Gerald Combs of the Wireshark Project. The vulnerable function is this:

940  static const char *
941  get_persconffile_dir(const gchar *profilename)
942  {

As its name implies, this function is used to retrieve the personal configuration file directory. Here is what it does:

943          static char *persconffile_profile_dir = NULL;
944
945          if (persconffile_profile_dir) {
946                  g_free (persconffile_profile_dir);
947          }
948

It declares a static pointer and initializes it to NULL. Then, if this value is not NULL, it frees it using g_free() at line 946. Else, it continues like this:

949          if (profilename && strlen(profilename) > 0 &&
950              strcmp(profilename, DEFAULT_PROFILE) != 0) {
951            persconffile_profile_dir = g_strdup_printf ("%s%s%s", get_profiles_dir (),
952                                                        G_DIR_SEPARATOR_S, profilename);

If the profile name and its length are not NULL, and if the profile name is not the default one, then use g_strdup_printf() to retrieve the profiles directory, insert the appropriate directory seperator and finally the profile name. Nothing notable here, but what if this condition at line 949 fails? Here is the else part:

953          } else {
954            persconffile_profile_dir = g_strdup_printf (get_persconffile_dir_no_profile ());
955          }
956
957          return persconffile_profile_dir;
958  }

Well, it just stores to persconffile_profile_dir a string being duplicated using g_strdup_printf() but with no format string specifier! And finally, this function returns this value. Let’s now move to get_persconffile_dir_no_profile() and see where it takes the string that it returns. The latter function can be found at the same source code file. Here it is:

831  /*
832   * Get the directory in which personal configuration files reside;
833   * in UNIX-compatible systems, it's ".wireshark", under the user's home
834   * directory, and on Windows systems, it's "Wireshark", under %APPDATA%
835   * or, if %APPDATA% isn't set, it's "%USERPROFILE%\Application Data"
836   * (which is what %APPDATA% normally is on Windows 2000).
837   */
838  static const char *
839  get_persconffile_dir_no_profile(void)
840  {

The comment is pretty explanatory so, here is a stripped down version, with only the useful for us parts (I’m ignoring the Win32 parts):

839  get_persconffile_dir_no_profile(void)
840  {
       ...
846          const char *homedir;
       ...
902          homedir = getenv("HOME");
903          if (homedir == NULL) {
       ...
909                  pwd = getpwuid(getuid());
910                  if (pwd != NULL) {
       ...
915                          homedir = g_strdup(pwd->pw_dir);
916                  } else
917                          homedir = "/tmp";
918          }
919          persconffile_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", homedir, PF_DIR);
       ...
922          return persconffile_dir;
923  }

So, it takes it directly from the HOME environment variable or if it fails, it tries out the same using getpwuid() and as a last resort, the /tmp directory. If we manipulate the HOME environment variable to contain malicious format string input we can exploit this issue and execute arbitrary code. Format string exploitation is extremely trivial and well documented even with the latest protection mechanisms enabled. At last, here is the patch for this simple bug:

     } else {
-      persconffile_profile_dir = g_strdup_printf (get_persconffile_dir_no_profile ());
+      persconffile_profile_dir = g_strdup_printf ("%s", get_persconffile_dir_no_profile ());
     }

Proof of concept? :P
Just:

export HOME="%n%n%n%n%n"

and either run wireshark or tshark… Now, imagine how difficult the exploitation could be ;p

Wireshark has definitely more vulnerabilities, and numerous remotely exploitable ones since it is a huge project with many parsing operations. But I found this kind of bug funny, even automated auditing tools such as static code analysis GCC patches would have detect this one.

Whatever, back to work! :)

Written by xorl

February 11, 2009 at 15:38

Posted in bugs

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s