Re: Client/server application and Windows Integrated Auth

From: Joubert (Joubert_at_discussions.microsoft.com)
Date: 02/01/05

  • Next message: Joubert: "Re: Client/server application and Windows Integrated Auth"
    Date: Tue, 1 Feb 2005 11:33:05 -0800
    
    

    Hi Ken,

    "Ken Schaefer" wrote:

    >
    > "Joubert" <Joubert@discussions.microsoft.com> wrote in message
    > news:F6E36F51-8307-4B41-9C0C-05BBAFC22CEB@microsoft.com...
    > > Hi,
    > >
    > > We now want to support Windows Integrated auth so that the user does not
    > > have to enter a login name and password. One way to do this is to identify
    > > the user based on their domain\username. However, this can be spoofed, by
    > > setting up another computer so that the application is run under the same
    > > domain\username and then connecting to the datastore (since the user
    > > doesn't
    > > actually have to login to the domain in order to access the datastore,
    > > e.g.
    > > Access file on local drive or when connecting to SQL Server via TCP/IP).
    >
    > This can only be "spoofed" if the person setting up the application has both
    > the username *and* the corresponding password. If you have users that know

    No, you can spoof it without have the "real" password because you are not
    using the "real" Windows user account to identify yourself. Here's a sketch
    of the scenario:

    Setup
    =====
    Let's say the datastore is an MS Access database and is on a fileshare
    somewhere. In the authentication table the user George Smith is (literally)
    identified as STDOM\gsmith
    If George logs onto his network, Windows will return his domain\username as
    STDOM\gsmith (assuming he logged into that account). His Windows password is
    never stored in the application's datastore (the MS Access database).
    Remember we want the user not have to bother to enter their username /
    password - they've already done it in Windows.

    Naughty person
    ===========
    Now, let's say Jill Sander wants to impersonate George in order to get to
    information stored in the application datastore which only George can see
    because of his identity. She can setup a PC with the computer name "STDOM"
    (or on PC setup a Windows domain called "STDOM"). Further, she can create a
    user account called "gsmith" and choose whatever password she likes.
    She now simply logs into that account (Windows will now ID her as
    STDOM\gsmith) and launch the application. When she opens the datastore with
    the application it will do a match against the authentication table in the
    datastore and identify her has George Smith.

    Avoid the spoof
    ==========
    So, from the example above it appears as if simply using DOMAIN\username is
    not an adequate solution. And now we're back at my original e-mail.
    I am thinking of using the user's SID and store that in the authentication
    table in the datastore instead of teh DOMAIN\username. This should ensure it
    is in fact the SAME person and so avoid the possibility of impersonation.

    Is this assessment accurate?

    Regards
    Joubert

    > other user's passwords, then you're going to have a security issue no matter
    > what you do (for example, someone can obtain the SID knowing the username
    > and password)
    >
    > Cheers
    > Ken
    >
    > >
    > > The one solution I've come up with is to store the user's SID instead of
    > > domain\username, since according to the article at
    > > http://www.microsoft.com/resources/documentation/WindowsServ/2003/standard/proddocs/en-us/Default.asp?url=/resources/documentation/WindowsServ/2003/standard/proddocs/en-us/sag_ADintro_12.asp
    > > this is guaranteed to be unique and is in fact the method Windows uses to
    > > refer to user accounts.
    > >
    > > Is my assessment of how to implement Windows Integrated auth correct?
    > >
    > > I have even written a short C# application that retrieves the SID for a
    > > user
    > > account (I include the source below).
    > >
    > > using System;
    > > using System.Text;
    > > using System.Diagnostics;
    > > using System.DirectoryServices;
    > >
    > > namespace GetWindowsAuthName
    > > {
    > > /// <summary>
    > > /// Summary description for Class1.
    > > /// </summary>
    > > class Application
    > > {
    > > /// <summary>
    > > /// The main entry point for the application.
    > > /// </summary>
    > > [STAThread]
    > > static void Main(string[] args)
    > > {
    > > PrintUsageInstructions();
    > >
    > > System.Security.Principal.WindowsIdentity identity =
    > > System.Security.Principal.WindowsIdentity.GetCurrent();
    > > string username;
    > >
    > > if (args.Length > 0)
    > > {
    > > username = args[0];
    > > }
    > > else
    > > {
    > >
    > > username = identity.Name;
    > > }
    > >
    > > PrintSidInformation(username);
    > >
    > > Console.WriteLine();
    > > Console.Write("Press <ENTER> to continue...");
    > > Console.ReadLine();
    > > }
    > >
    > > private static void PrintSidInformation(string username)
    > > {
    > > Console.WriteLine("Getting SID for: " + username);
    > > Console.WriteLine("SID = " + GetSid(username));
    > > }
    > >
    > > private static void PrintUsageInstructions()
    > > {
    > > Console.WriteLine("Usage instructions:");
    > > Console.WriteLine(@"GetWinAuthDetails [username@domain]
    > > [domain\username]");
    > > Console.WriteLine();
    > > }
    > >
    > > private static string GetSid(string strLogin)
    > > {
    > > string str = "";
    > > // Parse the string to check if domain name is present.
    > > int idx = strLogin.IndexOf('\\');
    > > if (idx == -1)
    > > {
    > > idx = strLogin.IndexOf('@');
    > > }
    > >
    > > string strDomain;
    > > string strName;
    > >
    > > if (idx != -1)
    > > {
    > > strDomain = strLogin.Substring(0, idx);
    > > strName = strLogin.Substring(idx+1);
    > > }
    > > else
    > > {
    > > strDomain = Environment.MachineName;
    > > strName = strLogin;
    > > }
    > >
    > > Debug.WriteLine("Domain: " + strDomain);
    > > Debug.WriteLine("Username: " + strName);
    > >
    > >
    > > DirectoryEntry obDirEntry = null;
    > > try
    > > {
    > > Int64 iBigVal = 5;
    > > Byte[] bigArr = BitConverter.GetBytes(iBigVal);
    > > obDirEntry = new DirectoryEntry("WinNT://" + strDomain + "/" + strName);
    > > System.DirectoryServices.PropertyCollection coll = obDirEntry.Properties;
    > > object obVal = coll["objectSid"].Value;
    > > if (null != obVal)
    > > {
    > > str = ConvertByteToStringSid((Byte[])obVal);
    > > }
    > >
    > > }
    > > catch (Exception ex)
    > > {
    > > str = "";
    > > Debug.Write(ex.Message);
    > > }
    > > return str;
    > > }
    > >
    > > private static string ConvertByteToStringSid(Byte[] sidBytes)
    > > {
    > > short sSubAuthorityCount = 0;
    > > StringBuilder strSid = new StringBuilder();
    > > strSid.Append("S-");
    > > try
    > > {
    > > // Add SID revision.
    > > strSid.Append(sidBytes[0].ToString());
    > >
    > > sSubAuthorityCount = Convert.ToInt16(sidBytes[1]);
    > >
    > > // Next six bytes are SID authority value.
    > > if (sidBytes[2] != 0 || sidBytes[3] != 0)
    > > {
    > > string strAuth = String.Format("0x{0:2x}{1:2x}{2:2x}{3:2x}{4:2x}{5:2x}",
    > > (Int16)sidBytes[2],
    > > (Int16)sidBytes[3],
    > > (Int16)sidBytes[4],
    > > (Int16)sidBytes[5],
    > > (Int16)sidBytes[6],
    > > (Int16)sidBytes[7]);
    > > strSid.Append("-");
    > > strSid.Append(strAuth);
    > > }
    > > else
    > > {
    > > Int64 iVal = (Int32)(sidBytes[7]) +
    > > (Int32)(sidBytes[6] << 8) +
    > > (Int32)(sidBytes[5] << 16) +
    > > (Int32)(sidBytes[4] << 24);
    > > strSid.Append("-");
    > > strSid.Append(iVal.ToString());
    > > }
    > >
    > > // Get sub authority count...
    > > int idxAuth = 0;
    > > for (int i = 0; i < sSubAuthorityCount; i++)
    > > {
    > > idxAuth = 8 + i * 4;
    > > UInt32 iSubAuth = BitConverter.ToUInt32(sidBytes, idxAuth);
    > > strSid.Append("-");
    > > strSid.Append(iSubAuth.ToString());
    > > }
    > > }
    > > catch (Exception ex)
    > > {
    > > Trace.WriteLine(ex.Message);
    > > return "";
    > > }
    > > return strSid.ToString();
    > > }
    > > }
    > > }
    > >
    >
    >
    >


  • Next message: Joubert: "Re: Client/server application and Windows Integrated Auth"

    Relevant Pages