cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
1531
Views
7
Helpful
0
Comments
aaron.hackney
Level 1
Level 1

In part I of "Script an ASDM Session", we looked at how to MiTM an ASDM session in order to understand how to leverage the ASDM web interface for our own automation needs. In this article, I will disect a small python app that I wrote demonstrating how to script against the ASDM interface.

Disclaimer: Look, I'm a hacker. I hack away at code to get what I need done. My code isn't necessarily pretty, but I try and follow PEP8 style guide standards.

You can start by cloning this repo from github.

git clone https://github.com/aaronhackney/test_ptracer.git


In the repo, you will find a sample asdm library. I wrote this to be simplistic and readable. One would likely want to make this a little fancier, but for educational purposes, I intentionally made it simple.

Some things to note

  1. This article assumes a basic knowledge of python. While it's python centric, the strategies used here could be employed in any programming language with HTTP/HTTPS capabilities.
  2. In the script consuming the asdm library, I have hardcoded the username and password. One would want to take another approach for production code.
  3. Since I am using a self-signed certificate in the sample application, I have instructed the ssl python library to turn off certificate validation. Again, in a production environment, it would be wise to turn certificate validation back on and use a valid certificate for your asdm interface.
  4. There are just a couple of standard libraries that you will need to install. The details are in the readme.md file.

Authentication

Here, we can see that instead of obtaining an asdm session token, we are simply base64 encoding our username and password and passing these credentials to the asdm interface as a simple header.

def set_headers(self):

  self.headers = {

  'Content-Type': 'text/xml',

  'Authorization': 'Basic ' + self.b64_credentials

  }


Making the ASDM Call

In part I of "Script an ASDM Session", we saw that by using a MiTM packet capture, we could extract the payload of virtually any command issued by asdm session. Armed with that knowledge, we can reconstruct asdm calls in our our code.

From part I of "Script an ASDM Session", we saw that a configuration or data payload drop to the asdm interface looked a little like a soap api call.

<?xml version="1.0" encoding="ISO-8859-1"?>

<config-data config-action="merge" errors="continue">

<cli id="0">Interface GigabitEthernet0/0</cli>

<cli id="1">nameif INTERNET</cli>

</config-data>

To issue a packet tracer, let's use this same structure. You can see that we did this in the asdm library, where we wrote a function just for testing tcp packet-tracer packets originating from the outside interface. This class method takes a source IP, a destination IP, and a destination port and runs packet-tracer to see if this traffic "from the Internet" is allowed into the protected segments. Note that the source port is a random integer between 1024 and 65535 because, well, that's what a real client would do.

def set_ptrace_data(self, source_ip, dest_ip, dest_port):

  # Create a packet tracer with the given parameters and a random source port

  self.data = ('<?xml version="1.0" encoding="ISO-8859-1"?><config-data config-action="merge" '

  'errors="continue"><cli id="0">packet-tracer input outside tcp ' + source_ip + ' ' +

  str(random.randint(1024, 65535)) + ' ' + dest_ip + ' ' + str(dest_port) +

  ' xml</cli></config-data>')

  return

So, a simple example consuming this method might look like this:

asdm_username = 'cisco'                             # Set your credentials

asdm_password = 'sanfran'                           # Set your credentials

asa_ip = '172.16.127.127'                           # The IP address the asdm interface is listening on

asdm_port = 8443                                    # The port the asdm interface is listening on

asdm = ASDM()                                       # Create an instance of the ASDM class

asdm.set_credentials(asdm_username, asdm_password)  # Set your ASDM credentials

asdm.set_asdm_endpoint(asa_ip, asdm_port)           # Set management IP and port the ASDM service is listening on

asdm.set_headers()                                  # Set the auth and content headers

asdm.set_ssl_insecure()                             # turn off ssl certificate validation (testing only!)

asdm.set_ptrace_data('8.8.8.8', '208.13.96.1', 22)  # testing an ssh attempt from the Internet to the host

asdm.asdm_call()                                    # exectue the packet-tracer

print ("From 8.8.8.8 to tcp port 22 result = " . asdm.action)

So, hopefully, this blog post and the github code has left the reader with enough breadcrumbs to begin constructing their own asdm interface calls. The next logical steps would be to interface this with something like Ansible and/or constructing your own api that would provide simple rest interfaces to the asdm "xml-ish" interface.

Getting Started

Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the community: