Reputation: 2502
I'm attempting to potentially parse two XML files with Nokogiri, which is based on an attribute value existing. The problem is that my initial conditional is always returning true, even if the node doesn't exist at the xpath
. I think I've done everything right, but obviously I haven't.
Here are my two XML files:
dnsrecon_output.xml (typical file output)
<?xml version="1.0" ?>
<records>
<record ns_server="192.168.1.1" type="info" zone_transfer="failed"/>
<record ns_server="192.168.1.2" type="info" zone_transfer="failed"/>
<record address="192.168.1.1" mname="ns1.mynetwork.local" type="SOA"/>
<record Version="9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6_7.5" address="192.168.1.1" recursive="True" target="ns1.mynetwork.local" type="NS"/>
<record Version="9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6_7.5" address="192.168.1.2" recursive="True" target="ns2.mynetwork.local" type="NS"/>
<record address="192.168.1.3" name="web.local" type="A"/>
</records>
dnsrecon_brute.xml
<?xml version="1.0" ?>
<records>
<record address="192.168.1.3" name="dev.web.local" type="A"/>
<record name="ftp.web.local" target="dev.web.local" type="CNAME"/>
<record address="192.168.1.4" name="git.web.local" type="A"/>
<record address="192.168.1.5" name="ops.web.local" type="A"/>
<record address="192.168.1.6" name="whm.web.local" type="A"/>
<record address="192.168.1.7" name="www.web.local" type="A"/>
</records>
However, if zone_transfer=success
the output will look like this...
dnsrecon_output_xfer.xml (just to show what I'm trying to match)
<?xml version="1.0" ?>
<records>
<record ns_server="192.168.1.2" type="info" zone_transfer="success"/>
<record address="192.168.1.2" mname="ns" type="SOA" zone_server="192.168.1.2"/>
<record address="192.168.1.2" target="ns1.network.local" type="NS" zone_server="192.168.1.2"/>
<record address="192.168.1.100" name="win.network.local" type="A" zone_server="192.168.1.2"/>
<record address="192.168.1.2" name="ns1.network.local" type="A" zone_server="192.168.1.2"/>
<record address="192.168.1.2" mname="ns1.network.local" type="SOA"/>
</records>
And here's my Nokogiri parsing. Mainly I want to check to see if the zone_transfer=success
exists, if it doesn't move on to the *_brute.xml
file:
document = Nokogiri::XML(File.open("dnsrecon_output.xml"))
document.remove_namespaces!
# Strictly for Zone transfers
if document.xpath("//records//record[@zone_transfer='success']")
puts "Zone Transfer Successful ... YIKES!!!"
document.xpath("//records//record[@type='A']").each do |record|
# change the output here to match what we need it to...
puts "#{record.at_xpath("@address")} - #{record.at_xpath("@name")}"
end
else
puts "No zone transfers... moving to brute"
document2 = Nokogiri::XML(File.open("dnsrecon_brute.xml"))
document2.remove_namespaces!
document2.xpath("//records//record[@type='A' or @type='CNAME']").each do |record|
puts "#{record.at_xpath("@address")} - #{record.at_xpath("@name")}"
end
end
As you'll note, I'm initially parsing the dnsrecon_output.xml
file, which has the zone_transfer="failed"
in the record tag. However, my output in my console is:
Zone Transfer Successful ... YIKES!!!
192.168.1.3 - web.local
And never runs the else
portion, which is should. Where have I gone wrong with the attribute value checking?
Upvotes: 0
Views: 3068
Reputation: 8646
Your check returns an empty Nokogiri::XML::NodeSet
which is truthy.
Either read the attribute and compare its value:
if document.xpath("//records//record/@zone_transfer").first.value == 'success'
...
Note that this will only work if the xpath matches at least one element (so it wont work for the "brute" file).
or add a any?
to get a boolean return:
if document.xpath("//records//record[@zone_transfer='success']").any?
...
Upvotes: 3
Reputation: 48599
x = document.xpath("//records//record[@zone_transfer='success']")
p x
--output:--
[]
and:
if []
puts %q{It's true!}
end
--output:--
It's true.
The only values that evaluate to false in ruby are false
itself and nil
. Empty arrays, empty hashes, blank strings, 0
, etc. are all true.
Instead, you can do something like this:
if document.xpath("//records//record[@zone_transfer='success']").empty?
puts "no matching elements"
#got to next xml file
else
puts "found matches"
#do your other xpath search
end
--output:--
no matching elements
Upvotes: 0