Client/server application and Windows Integrated Auth

Ask a Question related to ASP.NET Security, Design and Development.

  1. #1

    Default Client/server application and Windows Integrated Auth

    Hi,

    I have a .NET WinForms application that needs to identify the user and
    authenticate this against a datastore (could be Access, SQL Server, or
    Oracle). Currently, our login process is forms based so whatever login the
    user enters, together with the password, are matched against a table in the
    datastore to determine what level of access they should receive.

    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).

    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
    [url]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[/url]
    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.GetCurre nt();
    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();
    }
    }
    }

    Joubert Guest

  2. Similar Questions and Discussions

    1. Forms Auth Info passed to Windows Auth?
      The requirement is to build an ASP.Net intranet application, so external users can log in to the main web portal via forms authentication, using...
    2. Single external signon with Integrated Auth apps and regular webs
      Hi, Well, after reading all of the posts in here, I'm still not quite sure if what I would like is possible. Here's my scenario: IIS5 (or 6 if...
    3. .net Impersonate with integrated authentication client server problem
      Hi, I build a asp.net web application to update user accounts in Active Directory (AD). This application works fine on my test server when I acces...
    4. issues mixing integrated Windows authentication and anonymous on same application
      I'm having issues mixing integrated Windows authentication and anonymous access on same IIS app. Basically, any post back event fails (Forms...
    5. Is it possible for IIS and SQL server on Separate Machines with integrated auth
      Hi It is possible that IIS and SQL Server can reside on Seperate Machines and you can use Integrated Windows Authentication to connect. ...
  3. #2

    Default Re: Client/server application and Windows Integrated Auth


    "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
    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
    > [url]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[/url]
    > 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.GetCurre nt();
    > 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();
    > }
    > }
    > }
    >

    Ken Schaefer Guest

  4. #3

    Default Re: Client/server application and Windows Integrated Auth

    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
    > > [url]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[/url]
    > > 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.GetCurre nt();
    > > 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();
    > > }
    > > }
    > > }
    > >
    >
    >
    >
    Joubert Guest

  5. #4

    Default Re: Client/server application and Windows Integrated Auth

    After further research, it seems that instead of using the SID of a user
    account, I should in fact be using its NativeGuid (i.e.
    DirectoryEntry.NativeGuid) - this is supposed to uniquely identify the
    directory entry (which in my case is the user account).

    Thoughts?

    "Joubert" wrote:
    > 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
    > > > [url]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[/url]
    > > > 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.GetCurre nt();
    > > > 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();
    > > > }
    > > > }
    > > > }
    > > >
    > >
    > >
    > >
    Joubert Guest

  6. #5

    Default Re: Client/server application and Windows Integrated Auth

    "Joubert" <Joubert@discussions.microsoft.com> wrote in message
    news:8EBF2C3B-32EE-45F0-95E9-136F0C9D51ED@microsoft.com...
    > Hi Ken,
    >
    >> "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?

    No, it's not correct.

    Jill Sanders sets up a PC called STDOM, and creates a user account gsmith
    and assigns any password. She then attempts to connect to the webserver.
    Webserver denies anonymous access, and requires the user/client to
    authenticate.

    The rogue user (Jill Sanders) sends the credentials STDOM\gsmith + arbitrary
    password. The webserver then consults the STDOM domain controller and says
    "are these credentials valid for STDOM\gsmith?". The Domain Controller will
    say "no, that's not the real password for gsmith - require them to send a
    different set of credentials"

    This is assuming that you're using Basic, Digest, Integrated Windows Auth
    (not anonymous access)

    Cheers
    Ken


    Ken Schaefer Guest

  7. #6

    Default Re: Client/server application and Windows Integrated Auth



    "Ken Schaefer" wrote:
    > "Joubert" <Joubert@discussions.microsoft.com> wrote in message
    > news:8EBF2C3B-32EE-45F0-95E9-136F0C9D51ED@microsoft.com...
    > > Hi Ken,
    > >
    > >> "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?
    >
    >
    > No, it's not correct.
    >
    > Jill Sanders sets up a PC called STDOM, and creates a user account gsmith
    > and assigns any password. She then attempts to connect to the webserver.
    > Webserver denies anonymous access, and requires the user/client to
    > authenticate.
    The setup I described does not involve a server component - i.e. there is no
    webserver. There is only a client application (i.e. WinForms) than connects
    directly to the datastore, i.e. the client application does the
    authentication.

    So my thinking is that since the application's execution environment cannot
    be controlled you cannot merely rely on the fact that a "DOMAIN\username" is
    authenticated since the application can be put in a domain with the same name
    and run by a user with the same username.

    Does this make more sense?

    Cheers
    Joubert
    >
    > The rogue user (Jill Sanders) sends the credentials STDOM\gsmith + arbitrary
    > password. The webserver then consults the STDOM domain controller and says
    > "are these credentials valid for STDOM\gsmith?". The Domain Controller will
    > say "no, that's not the real password for gsmith - require them to send a
    > different set of credentials"
    >
    > This is assuming that you're using Basic, Digest, Integrated Windows Auth
    > (not anonymous access)
    >
    > Cheers
    > Ken
    >
    >
    >
    Joubert Guest

  8. #7

    Default Re: Client/server application and Windows Integrated Auth

    Why not let the datastore authenticate the user and do the authorization
    then? Like some others have pointed out on this thread, doing authorization
    on the client might be potentially dangerous. If the user is an admin and
    can attach a debugger, they can do whatever they want to your code. They
    can't do this to the server though.

    Hacking the kernel mode security stuff on the workstation is actually fairly
    hard to do (overcoming file ACLs and stuff that is protected by kernel
    objects), but all bets are still off if the local user is an admin.

    It really depends on how important it is that your security can't be hacked
    (what is the real threat) and what your deployment environment is like, but
    remember that people put security on the server and try to keep others from
    running debuggers on it for a reason.

    Joe K.
    >
    > The setup I described does not involve a server component - i.e. there is
    > no
    > webserver. There is only a client application (i.e. WinForms) than
    > connects
    > directly to the datastore, i.e. the client application does the
    > authentication.
    >
    > So my thinking is that since the application's execution environment
    > cannot
    > be controlled you cannot merely rely on the fact that a "DOMAIN\username"
    > is
    > authenticated since the application can be put in a domain with the same
    > name
    > and run by a user with the same username.
    >
    > Does this make more sense?
    >
    > Cheers
    > Joubert
    >

    Joe Kaplan \(MVP - ADSI\) Guest

  9. #8

    Default Re: Client/server application and Windows Integrated Auth

    "Joe Kaplan (MVP - ADSI)" wrote:
    > Like some others have pointed out on this thread, doing authorization on
    > the client might be potentially dangerous. If the user is an admin and
    > can attach a debugger, they can do whatever they want to your code.
    It's even worse than that - users don't need any special privileges
    to debug their own processes. There's no need to be an admin, or to
    have SeDebugPrivilege, etc.


    Pavel Lebedinsky Guest

  10. #9

    Default Re: Client/server application and Windows Integrated Auth

    Hi Joe,

    "Joe Kaplan (MVP - ADSI)" wrote:
    > Why not let the datastore authenticate the user and do the authorization
    > then? Like some others have pointed out on this thread, doing authorization
    Because the datastore may not have a server component, e.g. Access.
    Although, perhaps what we should do then is to support Windows Integrated
    Auth for server based datastores (in our case SQL Server and Oracle) but do
    not allow it for MS Access databases.
    > on the client might be potentially dangerous. If the user is an admin and
    > can attach a debugger, they can do whatever they want to your code. They
    > can't do this to the server though.
    >
    > Hacking the kernel mode security stuff on the workstation is actually fairly
    > hard to do (overcoming file ACLs and stuff that is protected by kernel
    > objects), but all bets are still off if the local user is an admin.
    >
    > It really depends on how important it is that your security can't be hacked
    > (what is the real threat) and what your deployment environment is like, but
    > remember that people put security on the server and try to keep others from
    > running debuggers on it for a reason.
    Thanks for your remarks - useful comments.

    Regards
    Joubert
    >
    > Joe K.
    >
    > >
    > > The setup I described does not involve a server component - i.e. there is
    > > no
    > > webserver. There is only a client application (i.e. WinForms) than
    > > connects
    > > directly to the datastore, i.e. the client application does the
    > > authentication.
    > >
    > > So my thinking is that since the application's execution environment
    > > cannot
    > > be controlled you cannot merely rely on the fact that a "DOMAIN\username"
    > > is
    > > authenticated since the application can be put in a domain with the same
    > > name
    > > and run by a user with the same username.
    > >
    > > Does this make more sense?
    > >
    > > Cheers
    > > Joubert
    > >
    >
    >
    >
    Joubert Guest

  11. #10

    Default Re: Client/server application and Windows Integrated Auth


    "Joubert" <Joubert@discussions.microsoft.com> wrote in message
    news:CD99B859-228B-45EC-ACE5-30442CF266E2@microsoft.com...
    > Hi Joe,
    >
    > "Joe Kaplan (MVP - ADSI)" wrote:
    >
    >> Why not let the datastore authenticate the user and do the authorization
    >> then? Like some others have pointed out on this thread, doing
    >> authorization
    >
    > Because the datastore may not have a server component, e.g. Access.
    > Although, perhaps what we should do then is to support Windows Integrated
    > Auth for server based datastores (in our case SQL Server and Oracle) but
    > do
    > not allow it for MS Access databases.
    In this case I would just say that your ability to provide any true security
    is going to be very limited based on all of the replies you've received from
    me and other much smarter people. With a server-based data store, you have
    a much better set of options. The real question is whether the risk
    associated with the Access-based data store is acceptable or not.

    Best of luck,

    Joe


    Joe Kaplan \(MVP - ADSI\) Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139