0

Only the first open port in the <ports> </ports> tag is listed in the CSV output file; no other open ports are listed. The output is printed to the csv file but only the first line in the ports tag is output to the csv file. You can try by run the nmap command "nmap -sV -Pn -oX Output_3.xml scanme.nmap.org"

`import xml.etree.ElementTree as ET
import csv

def main():
    in_xml_port = 'Output_1.xml'
    xml_tree_port = ET.parse(in_xml_port)
    xml_root_port = xml_tree_port.getroot()
    
   # To save the output to csv file 
    with open('detected_hosts.csv', 'w', newline='') as file:
        writer = csv.writer(file)
        writer.writerow(['IP', 'Hostname', 'Status', 'Port', 'Service', 'Protocol', 'Product'])

        for host in xml_root_port.findall('host'):

            # finding all the necessary details from the xml tags
            master_ip = host.find('address').get('addr')
            
            master_hostnames = host.findall('hostnames')
            master_hostname = master_hostnames[0].findall('hostname')[0].attrib['name']
            
            port_status = host.findall('ports')
            port_status_1 = port_status[0].findall('port')
            port_state = port_status_1[0].findall('state')[0].attrib['state']
            
            port_element = host.findall('ports')
            port_id = port_element[0].findall('port')[0].attrib['portid']

            open_service = host.findall('ports')
            open_service_1 = open_service[0].findall('port')
            service_name = open_service_1[0].findall('service')[0].attrib['name']
            
            potocol_element = host.findall('ports')
            port_protocol = potocol_element[0].findall('port')[0].attrib['protocol']

            product_element = host.findall('ports')
            product_element_1 = product_element[0].findall('port')
            product_name = product_element_1[0].findall('service')[0].attrib['product']
       
            if port_state == 'open':
                host_status = 'open'
                writer.writerow([master_ip, master_hostname, port_state, port_id, service_name, port_protocol, product_name])

                
if __name__ == '__main__':
    main()`
  • Only the first open port (portid tag) in the tag in XML output is listed in the CSV output file. If you can please run this nmap command: nmap -sV -Pn -oX Output_1.xml scanme.nmap.org and save the above python code in the same directory, run the python file. Open the detected_hosts.csv CSV file, you will only see one open port number and there are other open ports also for that target and those are not listed in the csv file. Not able to output all the open port numbers to the csv file. – Nitheesh Paul Feb 14 '23 at 16:57
  • It will be much easier for the others to offer help if you can post the XML file here (make redaction if necessary). Not all of us have `nmap` already installed. – Fanchen Bao Feb 14 '23 at 18:27
  • @FanchenBao thank you for the reply. I have added few portions from the XML output. Hope it will help. – Nitheesh Paul Feb 14 '23 at 18:41

1 Answers1

1

The issue is that when searching for 'ports', the code only gets the first response. For instance, these two lines:

port_status_1 = port_status[0].findall('port')
port_state = port_status_1[0].findall('state')[0].attrib['state']

port_status_1 is a list of ports, yet when querying for port_state, the code restricts itself to only the first port port_status_1[0]. Hence, in the generated CSV file, only the info of the first open port is recorded.

Give the following script a try. The main logic is not changed, except that it uses a loop to get all 'port' from all 'ports'. In addition, it uses find() and get() to simplify the querying of an attribute.

import xml.etree.ElementTree as ET
import csv

def main():
    in_xml_port = 'Output_1.xml'
    xml_tree_port = ET.parse(in_xml_port)
    xml_root_port = xml_tree_port.getroot()
    
   # To save the output to csv file 
    with open('detected_hosts.csv', 'w', newline='') as file:
        writer = csv.writer(file)
        writer.writerow(['IP', 'Hostname', 'Status', 'Port', 'Service', 'Protocol', 'Product'])

        for host in xml_root_port.findall('host'):

            # finding all the necessary details from the xml tags
            master_ip = host.find('address').get('addr')
            
            master_hostnames = host.findall('hostnames')
            master_hostname = master_hostnames[0].findall('hostname')[0].attrib['name']

            for ports in host.findall('ports'):
                for port in ports.findall('port'):
                    port_state = port.find('state').get('state')
                    port_id = port.get('portid')
                    service_name = port.find('service').get('name')
                    port_protocol = port.get('protocol')
                    product_name = port.find('service').get('product')
                    if port_state == 'open':
                        writer.writerow([master_ip, master_hostname, port_state, port_id, service_name, port_protocol, product_name])
                
if __name__ == '__main__':
    main()

Fanchen Bao
  • 3,310
  • 1
  • 21
  • 34
  • 1
    Hi, I have checked your code, it is working perfectly, and I understood the mistake I have made. Thank you very much for your help. Much appreciated. – Nitheesh Paul Feb 15 '23 at 06:25