2

Assume there exists a generic string collection that contains a variety of web service URLs:

List<string> webServiceCollection = new List<string>();
webServiceCollection.Add("http://<site>/_vti_bin/Lists.asmx");
webServiceCollection.Add("http://<site>/_vti_bin/Sites.asmx");

There a variety of methods, with a variety of input and return types in each web service. Is it possible to read the all the available operations and attempt the operation with default values? For this purpose, I am trying to write a security tool that will help test whether the web service allows the user to interact with them under a variety of accounts as an academic exercise.

Cœur
  • 37,241
  • 25
  • 195
  • 267
user3010406
  • 541
  • 2
  • 8
  • 22
  • 1
    There is an easy solution for your problem on msdn's website: https://blogs.msdn.microsoft.com/kaevans/2006/04/27/dynamically-invoking-a-web-service/ - good luck. – Yan Jul 18 '18 at 14:49
  • This assumes you know the method name and associated parameters on the InvokeMember – user3010406 Jul 18 '18 at 14:59
  • 2
    How about splitting your question... (1) [get method names](https://stackoverflow.com/questions/11295181/how-to-determine-method-names-and-parameters-in-wsdl-web-service), then (2) get parameters, (3) call the method dynamically – grek40 Jul 18 '18 at 18:31
  • if you are JUST trying to test the ACCESS security of these methods you should be able to send an empty dynamic request to the methods endpoints, if you get anything other then access not allowed then you know you got to the endpoint and past the authentication mechanisms. – Paul Swetz Jul 20 '18 at 17:36

2 Answers2

2

You can do something like this:

PSEUDO CODE

    System.Net.WebClient client = new System.Net.WebClient(); 
    string strUrl = @"http://localhost:xxxxx/Service.asmx?wsdl"; 
    System.IO.Stream stream = client.OpenRead(strUrl); 

    string serviceName = "Service"; 

    // Get a WSDL file describing a service. 
    ServiceDescription description = ServiceDescription.Read(stream); 

    ServiceDescriptionImporter importer = new ServiceDescriptionImporter(); 
    importer.ProtocolName = "Soap12";  // Use SOAP 1.2. 
    importer.AddServiceDescription(description, null, null); 

    // Generate a proxy client. 
    importer.Style = ServiceDescriptionImportStyle.Client; 

    // Generate properties to represent primitive values. 
    importer.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties; 

    // Initialize a Code-DOM tree into which we will import the service. 
    CodeNamespace nmspace = new CodeNamespace(); 
    CodeCompileUnit unit1 = new CodeCompileUnit(); 
    unit1.Namespaces.Add(nmspace); 

    // Import the service into the Code-DOM tree. This creates proxy code 
    // that uses the service. 
    ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit1); 

     if (warning == 0) 
     { 
        // Generate and print the proxy code in C#. 
        CodeDomProvider provider1 = CodeDomProvider.CreateProvider("CSharp"); 

        // Compile the assembly with the appropriate references 
        string[] assemblyReferences = new string[2] { "System.Web.Services.dll", "System.Xml.dll" }; 
        CompilerParameters parms = new CompilerParameters(assemblyReferences); 
        CompilerResults results = provider1.CompileAssemblyFromDom(parms, unit1); 

        foreach (CompilerError  oops in results.Errors) 
        { 
            Console.WriteLine("========Compiler error============"); 
            Console.WriteLine(oops.ErrorText); 
        } 

        //Invoke the web service method 
        foreach (PortType portType in description.PortTypes)
        {
            foreach (Operation operation in portType.Operations)
            {
                try
                {
                    object o = results.CompiledAssembly.CreateInstance(serviceName); 
                    Type t = o.GetType(); 
                    Console.WriteLine(t.InvokeMember(operation.Name, System.Reflection.BindingFlags.InvokeMethod, null, o, null)); 
                }catch(Exception ex){
                    Console.WriteLine(ex.Message);
                }
            }
        }
     } 

    else 
    { 
        // Print an error message. 
        Console.WriteLine("Warning: " + warning); 
    } 
Nitin Sawant
  • 7,278
  • 9
  • 52
  • 98
0

this will be your best attempt to try and achieve your goal:

string completeUrl ="<a href="http://localhost/testwebservice">http://localhost/testwebservice</a>";

// Create a request for the URL.         
WebRequest request = WebRequest.Create(completeUrl);

// If required by the server, set the credentials.
request.Credentials = CredentialCache.DefaultCredentials;


    // If you have a proxy configured.
    WebProxy proxyObject = new WebProxy("<a href="http://proxy.com/">http://proxy.com/</a>", true);
    request.Proxy = proxyObject;


    //Get the response.
    using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    {
      // Get the stream containing content returned by the server.
      using(Stream dataStream = response.GetResponseStream())
      {
        // Open the stream using a StreamReader for easy access.
        using(StreamReader reader = new StreamReader(dataStream))
        {
           // Read the content.
           string responseFromServer = reader.ReadToEnd();   
        }
      }
    }

and in order to add your try you should do:

List<string> webServiceCollection = new List<string>();
webServiceCollection.Add("http://<site>/_vti_bin/Lists.asmx");
webServiceCollection.Add("http://<site>/_vti_bin/Sites.asmx");

  foreach(var reqeust in webServiceCollection) 
  {
    string completeUrl = $"<a href="request">{request}</a>";;

    // Create a request for the URL.         
    WebRequest request = WebRequest.Create(completeUrl);

    // If required by the server, set the credentials.
    request.Credentials = CredentialCache.DefaultCredentials;


    // If you have a proxy configured.
    WebProxy proxyObject = new WebProxy("<a href="http://proxy.com/">http://proxy.com/</a>", true);
    request.Proxy = proxyObject;


    //Get the response.
    using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    {
      // Get the stream containing content returned by the server.
      using(Stream dataStream = response.GetResponseStream())
      {
        // Open the stream using a StreamReader for easy access.
        using(StreamReader reader = new StreamReader(dataStream))
        {
           // Read the content.
           string responseFromServer = reader.ReadToEnd();   
        }
      }
    }
  }
Barr J
  • 10,636
  • 1
  • 28
  • 46
  • thank you. However this has several problems. The URL formatting is in hypertext, and this doesn't execute any methods, it merely contacts the web service with a request. – user3010406 Jul 23 '18 at 19:28
  • the only way for you to execute methods directly, is to use the WS as a service reference. the other way is in the example above :) – Barr J Jul 24 '18 at 04:42