• UAG Form Login SSO - Lessons from field

    This is next part of my UAG authentication presentation blogpost, where I am going to discuss about the form login authentication. I am a big fan of Ben Ari and usually follow his suggestions provided in his blog post for form login SSO
    http://blogs.technet.com/b/ben/archive/2010/09/02/uag-custom-form-login.aspx

    Usually it’s not possible to cover everything in single blog post. In this blog post I’m adding to the suggestions provided by my friend Ben in his blog using Troubleshooting approach I took on a case.

    I was working on a case, where customer has changed his logon form page on his website, after that Single Sign On through UAG stopped working. After login to the portal ,when user tries to open the application, he was getting the logon form, instead of the application. I did view source of the page and found that autosubmit script was not getting injected into the logon page.

    Troubleshooting Approach

    1. URL of the logon page, I asked Admin to open IE on the UAG server itself, then access the websites logon page and from there I got the URL of the logon page.

    2. The Form ,After the page was opened in the browser, I viewed the source of the page and copied the whole HTML. I will put my sample form page from my lab (not actual problem logon page) for reference here.

     

            *********************************************************************************

               <html>

              <head>

               </head>

              <body>

     <form ID="contosoform" action="login.html"  method="post">

     Username   <input   name="contoso_username" type="text" value="" />

     Password  <input  name="contoso_password" type="password" />

     <input  name="contosologin"  type="submit" value="Log In"/>

            </form>

            </body>

           </html>

     

    *********************************************************************************

    3.  After looking at the form, I noticed that the name of the form had changed, it was fabrikam-form earlier and now it was contosoform, so in the formlogin.xml file, I changed the name of the form, which is highlighted in the form login section
    for that application below

     

     *******************formlogin.xml for the application****************

          <APPLICATION>

                                   
                  <APPLICATION_TYPE> contosotest</APPLICATION_TYPE>

                                   
                     <USAGE description="form_login">

                                   
                            <PRIMARY_HOST_URL>.*</PRIMARY_HOST_URL>

                                   
                            <SECONDARY_HOST_URL>.*</SECONDARY_HOST_URL>

                                   
                                    <SCRIPT_NAME source="data_definition">FormLoginSubmitStandard</SCRIPT_NAME>

                                   
                                      <USER_AGENT>

                                                   
                                       <AGENT_TYPE search="group">all_supported</AGENT_TYPE>

                                                   
                                       <POLICY>multiplatform</POLICY>

                                                   
                                      <SCRIPT_NAME source="data_definition">FormLoginHandler</SCRIPT_NAME>

                                   
                                      </USER_AGENT>

                                   
                                     <MULTIPLE_LOGIN>true</MULTIPLE_LOGIN>

                                   
                                    <LOGIN_FORM>

                                                   
                                     <NAME> contosoform</NAME>

                                                   
                                        <METHOD>POST</METHOD>

                                                   
                                        <CONTROL handling="dummy_value">

                                                                   
                                        <TYPE>USER_NAME</TYPE>

                                                                   
                                        <NAME>contoso_username</NAME>

                                                                   
                                        <DEF_VALUE>uname</DEF_VALUE>

                                                   
                                         </CONTROL>

                                                   
                                        <CONTROL handling="dummy_value">

                                                                   
                                        <TYPE>PASSWORD</TYPE>

                                                                   
                                        <NAME>contoso_password</NAME>

                                                                   
                                         <DEF_VALUE>pwd</DEF_VALUE>

                                                   
                                        </CONTROL>

                                   
                                </LOGIN_FORM>

                                   
                   </USAGE>

                   
    </APPLICATION>

     

     

    ****************************************************************

    4. After modifying the formlogin.xml at (C:\Program Files\Microsoft Forefront Unified AccessGateway\von\Conf\WizardDefaults\FormLogin\CustomUpdate\FormLogin.xml) on the UAG server and activating the configuration, we tested SSO and it was still not working.

    5. Data analysis : Took UAG trace while doing Repro of the issue and found following in the tracing

                *************************************************************

              
         Entering CProcessForm::PreProcessInputData CProcessForm::PreProcessTag(), Start  

        Exiting from CProcessForm::PreProcessInputData CProcessForm::PreProcessTag(), End

             
        Exiting from CProcessForm::PreProcessInputData PreProcessInputData()::End

              
        Info:INFO: ProcessBufferFromRWS():(wfeID=000000000570EAB0) Required form Name/ID not found but should be : not a formlogin - not processing

     

              *************************************************************

    6. Then I noticed that not just the name of the form has changed but the tag to name the form, has also changed in the new logon page i.e. earlier they were using Name=”contosoform” and now they are using ID="contosoform"  i.e they had Name to identify form earlier now they were using ID.

     

            <form ID="contosoform" action="login.html" method="post">

     

    7. When I compared that with the formlogin.xml for this application , the part which deals with it i.e.

                                                   
                                         <NAME> contosoform </NAME>

     

    And I could clearly see that XML tags do not match the tags of the logon form as in XML we have <NAME></NAME> tags and in the form we have “ID” to identify the form. So I modified this tag to

                                 

                                          <ID> contosoform</ID>

     

    in the formlogin.xml .After making this change in formlogin.xml, Activated the UAG config and tested, then we got a message on the client screen, saying that we have more than one form. I once again did view source of the page and found that autosubmit script was getting injected. I searched the form tags and found that there were two forms on the logon page.

     

    8. Default Autosubmit script which is :

     

    **********************************************

    function FormLoginSubmit()

       {

            formsCol = document.forms;

         if (formsCol.length == 1)
      
           {

            document.forms[0].submit();
     
            }

        else

           {

              alert("more than one form");

          }

         return false;

    }

    **********************************************

    We can see that, this script checks that, if there is only one form in the logon page, if yes then submit that form else send an alert message “more than one form”.

     

    9. If we have more than one form on the logon page, then we need to use custom script and modify the form login.xml as well, to mention this custom script. I have an amazing friend called Stanley George who had this custom script ready and tested. He gave me this  script

     

    ***********************************************

    function FormLoginSubmit()

       {   

       
    document.getElementById('login-form').submit();     

        return false;

        }

    ***********************************************

    I put this script file at location (C:\Program Files\Microsoft Forefront Unified Access Gateway\von\Conf\Websites\<trunkname>\conf\Autosubmit_contoso.js) on all the nodes of the UAG array. When we use custom script, we also need to modify the formlogin.xml for that application, under the following section

     

                                  <SCRIPT_NAME source="file"> Autosubmit_contoso.js </SCRIPT_NAME>

    10. After this change in formlogin.xml, I activated the UAG configuration and tested again and Now SSO was working fine.

    11. I also made my final formlogin.xml to be little more specific with the URL , after all the changes the working formlogin.xml will look like this.

     

    *************************************************************************

    <APPLICATION>

                                    
                  <APPLICATION_TYPE>Contosotest</APPLICATION_TYPE>

                                   
                     <USAGE description="form_login">

                                   
                           <PRIMARY_HOST_URL>.*login\.html.*</PRIMARY_HOST_URL>

                                   
                            <SECONDARY_HOST_URL>.*login\.html.*</SECONDARY_HOST_URL>

                                   
                              <SCRIPT_NAME source="file">Autosubmit_contoso.js</SCRIPT_NAME>

                                   
                                <USER_AGENT>

                                                   
                              <AGENT_TYPE search="group">all_supported</AGENT_TYPE>

                                   
                   
                             <POLICY>multiplatform</POLICY>

                                                   
                             <SCRIPT_NAME source="data_definition">FormLoginHandler</SCRIPT_NAME>

                                   
                           </USER_AGENT>

                                   
                         <MULTIPLE_LOGIN>true</MULTIPLE_LOGIN>

                                   
                              <LOGIN_FORM>

                                                   
                                  <ID>contosoform</ID>

                                    <METHOD>POST</METHOD>

                                                   
                                     <CONTROL handling="dummy_value">

                                                                   
                                    <TYPE>USER_NAME</TYPE>

                                                                   
                                   <NAME>contoso_username</NAME>

                                                                   
                                  <DEF_VALUE>uname</DEF_VALUE>

                                                   
                                    </CONTROL>

                                                   
                                   <CONTROL handling="dummy_value">

                                                                   
                                        <TYPE>PASSWORD</TYPE>

                                                                   
                                     <NAME>contoso_password</NAME>

                                                                   
                                     <DEF_VALUE>pwd</DEF_VALUE>

                                                   
                                   </CONTROL>

                                   
                      </LOGIN_FORM>

                                   
              </USAGE>

                   
    </APPLICATION>

    *************************************************************************

    Note: When you test form login SSO or APPwrap, Please clear the browser cache before testing the changes as browser caches the html content and at times even after making the change in the fomlogin or in the script you may not see the results or change in the results.

     I am preparing a presentation on this topic as part 2 of my previous UAG authentication presentation, This presentation will further simplify what Ben has explained in his post and would add up my experiences in it.

     

  • Generating netstat output and scenario based tracing using netsh when a specific event occurs in the eventlog-using Powershell

    I was working on a case, where I needed to get netstat outpiut to understand certain connections  behavior and I needed to do that for a particular event in the event log. It was really difficult to get this output exactly at the time this event was occuring. So I started working on it in my lab. I used my previous blog post about nmcap and eventmon and idea of powershell, which is a amazing tool and technology.

    for event id I did not have to do much, i used the same script mentioned in my previous blog post where i had reference: http://blogs.technet.com/b/netmon/archive/2007/02/22/eventmon-stopping-a-capture-based-on-an-eventlog-event.aspx

    I simplified that in my blog post : http://blogs.technet.com/b/sooraj-sec/archive/2011/12/23/using-eventmon-and-nmcap-to-take-network-monitor-trace-when-a-particular-event-is-generated.aspx Now  i m trying to modify it further to get netstat output when an event occurs.

    Step1 :Copy the contents of the script given in above post shown below in a notepad and save it as EvtMon.vbs and put this in a folder lets call it netstat and in my lab i put it in c:\netstat location

     

    '======================================================================
    ' Print out the help when something is not typed in correctly or when
    ' nothing at all is typed in.

    Public Sub PrintHelp
        Wscript.Echo "Usage:"
        Wscript.Echo "  EvtMon EventNumber [LogFileDisplayName]"
        Wscript.Echo "    LogFile is optional.  If used, the eventlog name"
        Wscript.Echo "    file ie, application, system, security, etc..."
    End Sub

    ' Get the arguments.  Check for event nubmer and log file as arugments
    Set objArgs = WScript.Arguments

    ' See how many arguments we have and colect them.
    if objArgs.Count < 1 OR objArgs.Count > 2 Then
        PrintHelp
    ElseIf objArgs.Count > 1 Then
        EventNumber = objArgs(0)
        LogFile = objArgs(1)
    Else
        EventNumber = objArgs(0)
        LogFile = ""
    End If

    If EventNumber <> "" Then

        strComputer = "."

        ' Attatch to the WMI Service
        Set objWMIService = GetObject("winmgmts:{(Security)}\\" & _
                strComputer & "\root\cimv2")

        ' if the LogFile is populated add this to our query.  Create a
        ' Event Log monitoring object and send it a query.
        If LogFile = "" Then
            Set colMonitoredEvents = objWMIService.ExecNotificationQuery _   
                ("Select * from __InstanceCreationEvent Where " _
                    & "TargetInstance ISA 'Win32_NTLogEvent' " _
                        & "and TargetInstance.EventCode = '" _
                        & EventNumber & "'")
        Else
            Set colMonitoredEvents = objWMIService.ExecNotificationQuery _   
                ("Select * from __InstanceCreationEvent Where " _
                    & "TargetInstance ISA 'Win32_NTLogEvent' " _
                        & "and TargetInstance.EventCode = '" _
                        & EventNumber _
                        & "' and TargetInstance.LogFile = '" _
                        & LogFile & "'")
        End If

        ' Create an object which returns when the next event occurs.
        Set objLatestEvent = colMonitoredEvents.NextEvent
       
        ' Print some info based on the event log we encountered.
        Wscript.Echo objLatestEvent.TargetInstance.User
        Wscript.Echo objLatestEvent.TargetInstance.TimeWritten
        Wscript.Echo objLatestEvent.TargetInstance.Message
        WScript.Echo objLatestEvent.TargetInstance.Logfile
        Wscript.Echo
    End If

     

    Step2 : Copy the contents of the batch file below in a notepad and save it as netstat.bat in same folder

    @echo off

    cscript //NoLogo EvtMon.vbs %2 %3
    powershell.exe -command "&  netstat -ano | Out-file c:\netstat\netstat.txt
    ping -n 1 4.3.2.1
    goto :EOF

     

     

    Note: You can see that I m taking output of the file at location c:\netstat\netstat.txt

    Usage : After saving the two files at c:\netstat folder, Open up a elevated command prompt and then go to the folder, where we have saved these two files and then run command(this is an example command here,  1502 is the event id) -> netstat ports 1502 

    reference snapshots below

     

    Note : once you run this command it just waits for the event to occur

     

    This event "1502 "gets generated when you update the group policy , I used this event in my lab, for a quick repro as whenever you run gpupdate/force this event will be generated, so I ran gpupdate /force as shown below

     

    after this I got 1502 event and got my netstat output as well as you can see in my snapshot below

     

     

    for people who like to experiment, the batch file can be modified to get a filtered out put as shown below, in following batch file i filtered the output for filtered connections, similarly we can filter for other connection stated , even more specificaly the attacks e.g. half open connections, which show up as "Syn_received"

    ***********************************************

    @echo off

    cscript //NoLogo EvtMon.vbs %2 %3

    powershell.exe -command "&  netstat -aonp TCP | select-string "ESTABLISHED" | Out-file c:\netstat\netstat.txt

    ping -n 1 4.3.2.1
    goto :EOF

    ***********************************************

     

    Collecting Scenario based tracing using netsh when an event occurs

     

     Following section is about a scenario if you want to collect netsh scenario based trace to look at various networking components when a particular event occurs.

    So instructions about the eventmon.vbs and contents remain the same , You modify the contents of batch file as below and let us say save it as netsh1.bat

    *******************************************************************

    @echo off
    cscript //NoLogo EvtMon.vbs %2 %3
    netsh trace start scenario=netconnection capture=yes tracefile=c:\netconnect.etl
    ping -n 30 4.3.2.1
    netsh trace stop

    goto :EOF

     *******************************************************************

    and run it like

     

    here netsh1 is your file name, ports is just a place holder , 1704 is your event id.

     

    in the batch file i have introduced delay of few minutes by pinging 4.3.2.1 ,30 times so that we can get good amount of trace collected at the time of issue. we can vary this number as per amount of delay we want.

    so once the event will occur netsh tracing would start and after 30 pings tracing will stop and file will be located at c:\netconnect.etl.

    so after event occurs , you will see this at the end explaining the data has been captured with its location and that tracing was stopped.