papasmurf
papasmurf

Reputation: 313

How to confirm a JavaScript popup using Nokgiri or Mechanize

I'm running a script that will open up on my localhost. My local server is a vulnerable web app test suite.

I'm trying to confirm a XSS popup from a JavaScript alert. For example:

http://127.0.0.1:65412/v?=0.2<script>alert("TEST");</script>

I need to confirm the popup happened using either Mechanize or Nokogiri. Is it possible to confirm that the popup is there with Nokogiri or Mechanize?

For example:

def page(site)
  Nokogiri::HTML(RestClient.get(site))
end

puts page('http://127.0.0.1:65412/v?=0.2<script>alert("TEST");</script>')

Upvotes: 3

Views: 597

Answers (2)

the Tin Man
the Tin Man

Reputation: 160621

Nokogiri, and Mechanize because it is built on top of Nokogiri, can parse the HTML and return the <script> tag's contents. The tag's content is text so at that point it's necessary to look inside the text to find what you want:

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<html>
<head>
<script>alert("TEST");</script>
</head>
</html>
EOT

script_content = doc.at('script').content # => "alert(\"TEST\");"

It's easy to check to see if a sub-string exists at that point:

script_content['alert("TEST");'] # => "alert(\"TEST\");"

or:

!!script_content['alert("TEST");'] # => true

Note: It's not possible with Nokogiri, or Mechanize, to tell if a pop-up occurred as that'd happen inside a browser as it runs the JavaScript. Neither Nokogiri or Mechanize understand or interpret JavaScript. Only a tool like Watir or that interprets JavaScript could do that.

Upvotes: 2

max pleaner
max pleaner

Reputation: 26788

Definitely not, and that's because neither Mechanize or Nokogiri run Javascript.

Instead, you could use Selenium.

Something like this:

require 'selenium-webdriver'

class AlertChecker
  Driver = Selenium::WebDriver.for :firefox
  def initialize(url)
    Driver.navigate.to url
  end
  def raise_alert(text)
    Driver.execute_script "alert('#{text}')"
    self
  end
  def safely_get_alert
    begin
      Driver.switch_to.alert
    rescue Selenium::WebDriver::Error::NoAlertOpenError
    end
  end 
end

Usage:

alert_checker = AlertChecker.new("http://my.website")

alert = alert_checker.safely_get_alert
# => nil

alert_checker.raise_alert("hack")
alert = alert_checker.safely_get_alert
puts alert.text
# => 'hack'

# As far as I'm aware Selenium doesn't have a built-in way
# to tell you if it's an alert, confirm, or prompt.
# But you know it's a prompt, for example, you could also send
# keys before accepting or dismissing
alert.accept

alert = alert_checker.safely_get_alert
# => nil 

There are some tricky things with Selenium's handling of alerts, though.

There's no way for your code to detect the type (prompt, confirm, or alert) without using something like rescue or try. Everything is reached through switch_to.alert.

Also, if your browser has an alert open you cannot run any subsequent commands unless you handle alert. Say you try and navigate.to while the alert is open; you'd get an error along the lines of You didn't handle the alert and your navigate.to command would have to be rerun. When this error is raised, the alert object will be lost as well.

It's a little unappealing to use rescue as a control structure in this way but I'm not aware of any other option

Upvotes: 1

Related Questions