Web & Server Hack/Sec
ahmet hocanin paylastigi orjinal metin https://www.beyazhacker.com/forum/web-server-hack-ve-guvenlik/python-ile-http-sunucusu-olusturma-ve-dosya-paylasimi?origin=auto_suggest
Dosya/Klasör Paylaşım ve İndirme Uygulaması - Kullanıcı Dokümentasyonu
Genel Bilgilendirme
Bu uygulama, kullanıcıların dosya veya klasörleri yerel ağda veya ınternet czerinden paylaşmasına olanak tanıyan bir masaüstü aracıdır. Flask tabanlı bir web sunucusu ile çalışır ve kullanıcı dostu bir arayüz sunar. Paylaşılan dosyalar AES algoritması ile şifrelenir ve bu şifreler kullanıcı tarafından belirlenir.
Uygulamanın Özellikleri
1. Dosya ve Klasör Paylaşımı: Kullanıcılar, herhangi bir klasörü paylaşabilir ve içerisindeki dosyaları şifreli olarak indirmeye sunabilir.
2. Yanıltıcı Şifre: Yanıltıcı bir şifre girildiğinde, kullanıcıya sahte dosyalar görüntülenir ve indirilebilir.
3. AES Şifreleme: Dosyalar AES algoritması kullanılarak şifrelenir, bu sayede veriler güvenli bir şekilde paylaşılır.
4. QR Kod Oluşturma: Paylaşılan dosya veya klasöre erişim için QR kod oluşturulur.
5. Karanlık Mod: Uygulamada kullanıcı dostu bir karanlık mod seçeneği bulunmaktadır.
Kurulum
1. Gerekli Paketlerin Kurulumu: Programı kullanabilmek için şu paketlerin kurulu olduğundan emin olun:
• Flask: pip install flask
• PyCryptodome: pip install pycryptodome
• Pillow: pip install pillow
• qrcode: pip install qrcode
2. Programı Çalıştırma:
• python3 paylasim.py komutu ile programı çalıştırın.
Kullanım Kılavuzu
1. Şifre Belirleyin: "Şifre Belirleyin" alanına, dosyalarınızı şifrelemek için kullanmak istediğiniz şifreyi girin ve "Şifreyi Ayarla" butonuna tıklayın.
2. Klasör Seçin: "Klasör Seç" butonuna tıklayarak paylaşmak istediğiniz klasörü seçin.
3. Port ve Süre Belirleyin: Çalışacak sunucu için bir port numarası girin. Ayrıca, sunucunun ne kadar süre açık kalması gerektiğini dakika cinsinden belirleyin.
4. Sunucuyu Başlat: "Sunucuyu Başlat" butonuna tıklayarak sunucuyu çalıştırın. Sunucu başlatıldıktan sonra yerel ve dış IP adresleri gösterilecektir.
5. Dosya ve Klasör Paylaşımı:
• Kullanıcılar, web arayüzü üzerinden belirlediğiniz şifreyi girerek dosyaları indirebilir.
• Yanıltıcı şifre girmeleri durumunda, sahte dosyaları görüntüleyeceklerdir.
6. Sunucuyu Durdur: Sunucuyu durdurmak için "Sunucuyu Durdur" butonuna tıklayın. Sunucu durdurulduktan sonra IP adresleri ve QR kodlar devre dışı kalacaktır.
7. QR Kod Kullanımı:
• Yerel veya dış IP adreslerinin yanında bulunan "QR Kod Göster" butonlarına tıklayarak ilgili IP adresine erişim için bir QR kod oluşturabilirsiniz.
Güvenlik Önlemleri
• Yanıltıcı Şifre: Uygulama, gerçek şifreyi bilmeyenlerin sahte içeriklere erişebilmesi için yanıltıcı bir şifre sunar. Bu, gerçek içeriklerin korunmasına yardımcı olur.
• AES Şifreleme: Tüm dosyalar AES algoritması ile şifrelenir, bu nedenle verileriniz güvenli bir şekilde paylaşılır.
• Süreli Sunucu: Sunucunun açık kalma süresi sınırlıdır ve bu, istenmeyen erişimleri engellemeye yardımcı olur.
Sorun Giderme
• Sunucu Başlamıyor: Port numarasının zaten kullanımda olmadığından emin olun. Farklı bir port numarası deneyin.
• Yanlış Şifre Hatası: Girilen şifrenin doğruluğunu kontrol edin. Gerçek şifre ile yanıltıcı şifreyi karıştırmadığınızdan emin olun.
• QR Kod Oluşturulamıyor: Sunucu başlatılmadan QR kod oluşturulamaz. Öncelikle sunucuyu başlatın.
Kısıtlamalar ve Gelecekteki Güncellemeler
• Şu anda sadece klasör paylaşımı desteklenmektedir, ancak gelecekte dosya bazlı paylaşım desteği de eklenebilir.
• Kullanıcı arayüzü daha modern ve dinamik hale getirilmesi planlanmaktadır.
import os
import socket
import threading
import tkinter as tk
from tkinter import messagebox, filedialog, ttk, Menu
from flask import Flask, request, send_file, redirect, url_for, flash, render_template_string
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Protocol.KDF import scrypt
import requests
import zipfile
import random
import string
import qrcode
from io import BytesIO
from PIL import Image, ImageTk
import signal
import sys
import time
# Flask web sunucusu oluşturma
app = Flask(__name__)
app.secret_key = "supersecretkey"
ENCRYPTION_FOLDER = "encrypted_files"
SELECTED_PATH = None # Seçilen dosya veya klasör burada saklanacak
user_password = None # Kullanıcı tarafından belirlenen gerçek şifre
auto_stop_timer = None # Sunucunun otomatik kapanması için zamanlayıcı
server_thread = None # Sunucu iş parçacığını takip etmek için
# Yanıltıcı şifre
DECOY_PASSWORD = "decoy123" # Saldırganın kaynak kodunda görebileceği yanıltıcı şifre
# Yanıltıcı klasör ve dosyalar oluşturma
def create_decoy_files():
"""
Yanıltıcı şifre girildiğinde gösterilecek sahte dosyalar oluşturur.
"""
decoy_path = os.path.join(ENCRYPTION_FOLDER, "decoy")
os.makedirs(decoy_path, exist_ok=True)
for i in range(3):
file_name = ''.join(random.choices(string.ascii_letters + string.digits, k=8)) + ".txt"
with open(os.path.join(decoy_path, file_name), "w") as f:
f.write("Bu bir sahte dosyadır.\n" * 5)
return decoy_path
# AES şifreleme ve çözme fonksiyonları
def encrypt_file(file_path, password):
"""
Dosyayı belirtilen şifre kullanılarak AES algoritması ile şifreler.
"""
key = scrypt(password.encode(), salt=b'salt', key_len=32, N=2**14, r=8, p=1)
cipher = AES.new(key, AES.MODE_GCM)
with open(file_path, 'rb') as f:
plaintext = f.read()
ciphertext, tag = cipher.encrypt_and_digest(plaintext)
encrypted_file_path = file_path + ".enc"
with open(encrypted_file_path, 'wb') as f:
f.write(cipher.nonce)
f.write(tag)
f.write(ciphertext)
return encrypted_file_path
def decrypt_file(file_path, password):
"""
Şifrelenmiş dosyayı belirtilen şifre kullanılarak çözer.
"""
key = scrypt(password.encode(), salt=b'salt', key_len=32, N=2**14, r=8, p=1)
with open(file_path, 'rb') as f:
nonce = f.read(16)
tag = f.read(16)
ciphertext = f.read()
cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
plaintext = cipher.decrypt_and_verify(ciphertext, tag)
return plaintext
def zip_folder(folder_path, password):
"""
Klasörü belirtilen şifre ile şifreleyerek zip arşivine ekler.
"""
zip_path = f"{folder_path}.zip"
with zipfile.ZipFile(zip_path, 'w') as zipf:
for root, dirs, files in os.walk(folder_path):
for file in files:
file_path = os.path.join(root, file)
encrypted_path = encrypt_file(file_path, password)
zipf.write(encrypted_path, os.path.relpath(encrypted_path, folder_path))
return zip_path
# Flask ile web arayüzü oluşturma@app.route('/')
def index():
"""
Ana sayfa: Şifre doğrulama ekranı.
"""
return '''
<!-- Test sırasında bırakılmış gibi görünen unutulmuş şifre bilgisi -->
<script>
// DEBUG: Legacy decryption function - remove before deployment
function decodeLegacyKey(encodedKey) {
// Saldırganları yanıltmak için karmaşık bir çözümleme işlemi gibi gösteriyoruz.
let decoded = "";
for (let i = 0; i < encodedKey.length; i += 2) {
let part = parseInt(encodedKey.substr(i, 2), 16) ^ 0x7A; // XOR ile çözümleme taklidi
decoded += String.fromCharCode(part);
}
return decoded;
}
// Şifrelenmiş eski bir test verisi gibi görünen dize
var legacyEncodedPassword = "214f243f3d2f252f"; // Saldırganların çözümlemek isteyebileceği yanıltıcı şifre
// Bypass şifresini "çözümleyerek" oluşturuyoruz
var bypassPassword = decodeLegacyKey(legacyEncodedPassword);
// Not: bypassPassword yalnızca geçici test amaçlıdır.
</script>
<h2>Dosya/Klasör Görüntüleme ve İndirme</h2>
<form method="POST" action="/authenticate">
<label for="password">Şifre Girin:</label>
<input type="password" id="password" name="password">
<button type="submit">Gönder</button>
</form>
'''
@app.route('/authenticate', methods=['POST'])
def authenticate():
"""
Kullanıcı tarafından girilen şifreyi doğrular ve uygun içeriği gösterir.
"""
entered_password = request.form['password']
if entered_password == user_password:
# Gerçek içerik
if SELECTED_PATH and os.path.isdir(SELECTED_PATH):
files = os.listdir(SELECTED_PATH)
return render_template_string('''
<h2>Gerçek Klasör İçeriği</h2>
<ul>
{% for file in files %}
<li>
{{ file }}
<form method="POST" action="/download_single" style="display: inline;">
<input type="hidden" name="filename" value="{{ file }}">
<button type="submit">İndir</button>
</form>
</li>
{% endfor %}
</ul>
<form method="POST" action="/download_all">
<button type="submit">Tümünü İndir</button>
</form>
''', files=files)
else:
flash("Gerçek içerik bulunamadı.")
return redirect(url_for('index'))
elif entered_password == DECOY_PASSWORD:
# Yanıltıcı içerik
decoy_path = create_decoy_files()
decoy_files = os.listdir(decoy_path)
return render_template_string('''
<h2>Yanıltıcı Klasör İçeriği</h2>
<ul>
{% for file in files %}
<li>
{{ file }}
<form method="POST" action="/download_decoy" style="display: inline;">
<input type="hidden" name="filename" value="{{ file }}">
<button type="submit">İndir</button>
</form>
</li>
{% endfor %}
</ul>
''', files=decoy_files)
else:
flash("Yanlış şifre!")
return redirect(url_for('index'))
@app.route('/download_decoy', methods=['POST'])
def download_decoy():
"""
Yanıltıcı dosyayı indirir.
"""
filename = request.form['filename']
decoy_path = os.path.join(ENCRYPTION_FOLDER, "decoy", filename)
if os.path.isfile(decoy_path):
return send_file(decoy_path, as_attachment=True)
else:
flash("Dosya bulunamadı!")
return redirect(url_for('index'))
@app.route('/download_single', methods=['POST'])
def download_single():
"""
Kullanıcının seçtiği gerçek dosyayı indirir.
"""
filename = request.form['filename']
file_path = os.path.join(SELECTED_PATH, filename)
encrypted_path = encrypt_file(file_path, user_password)
if os.path.isfile(encrypted_path):
return send_file(encrypted_path, as_attachment=True)
else:
flash("Dosya bulunamadı!")
return redirect(url_for('index'))
@app.route('/download_all', methods=['POST'])
def download_all():
"""
Seçilen klasördeki tüm dosyaları indirir.
"""
if SELECTED_PATH and os.path.isdir(SELECTED_PATH):
zip_path = zip_folder(SELECTED_PATH, user_password)
return send_file(zip_path, as_attachment=True)
else:
flash("Klasör bulunamadı!")
return redirect(url_for('index'))
# IP adreslerini alma
def get_local_ip():
"""
Yerel IP adresini alır.
"""
return socket.gethostbyname(socket.gethostname())
def get_external_ip():
"""
Dış IP adresini alır.
"""
try:
response = requests.get('http://icanhazip.com')
return response.text.strip()
except:
return "Dış IP alınamadı"
# QR kod oluşturma
def generate_qr_code(url):
"""
Belirtilen URL için QR kodu oluşturur.
"""
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data(url)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
return ImageTk.PhotoImage(img)
# Tkinter Masaüstü Arayüzü
class SimpleHTTPGUI:
"""
Tkinter kullanarak masaüstü uygulamasının arayüzünü sağlar.
"""
def __init__(self, root):
self.root = root
self.root.title("Dosya/Klasör Paylaşım ve İndirme Uygulaması")
self.root.grid_columnconfigure(0, weight=1)
self.root.grid_columnconfigure(1, weight=1)
self.root.grid_columnconfigure(2, weight=1)
self.root.grid_columnconfigure(3, weight=1)
self.root.grid_rowconfigure(0, weight=1)
self.root.grid_rowconfigure(1, weight=1)
self.root.grid_rowconfigure(2, weight=1)
self.root.grid_rowconfigure(3, weight=1)
self.root.grid_rowconfigure(4, weight=1)
self.root.grid_rowconfigure(5, weight=1)
self.root.grid_rowconfigure(6, weight=1)
self.root.grid_rowconfigure(7, weight=1)
self.root.grid_rowconfigure(8, weight=1)
self.root.grid_rowconfigure(9, weight=1)
self.root.grid_rowconfigure(10, weight=1)
self.root.grid_rowconfigure(11, weight=1)
# Menü Barı
menu_bar = Menu(root)
root.config(menu=menu_bar)
ayarlar_menu = Menu(menu_bar, tearoff=0)
ayarlar_menu.add_command(label="Karanlık Modu Aç/Kapat", command=self.toggle_dark_mode)
menu_bar.add_cascade(label="Ayarlar", menu=ayarlar_menu)
title_label = ttk.Label(root, text="Dosya/Klasör Paylaşım ve İndirme Uygulaması", font=("Helvetica", 16))
title_label.grid(row=0, column=0, columnspan=4, pady=10)
# Şifre Belirleme Alanı
ttk.Label(root, text="Şifre Belirleyin:").grid(row=1, column=0, padx=5, pady=5, sticky="e")
self.password_entry = ttk.Entry(root, show="*")
self.password_entry.grid(row=1, column=1, columnspan=2, padx=5, pady=5, sticky='nsew')
self.set_password_button = ttk.Button(root, text="Şifreyi Ayarla", command=self.set_password)
self.set_password_button.grid(row=1, column=2, padx=5, pady=5)
# Klasör Seçme
ttk.Label(root, text="Klasör Seçin:").grid(row=2, column=0, padx=5, pady=5, sticky="e")
self.path_label = ttk.Label(root, text="Henüz klasör seçilmedi")
self.path_label.grid(row=2, column=1, columnspan=2, padx=5, pady=5, sticky='nsew')
self.choose_path_button = ttk.Button(root, text="Klasör Seç", command=self.choose_path)
self.choose_path_button.grid(row=2, column=2, padx=5, pady=5)
# Sunucu Başlatma ve Durdurma
ttk.Label(root, text="Port Numarası:").grid(row=3, column=0, padx=5, pady=5, sticky="e")
self.port_entry = ttk.Entry(root)
self.port_entry.grid(row=3, column=1, columnspan=2, padx=5, pady=5, sticky='nsew')
self.start_button = ttk.Button(root, text="Sunucuyu Başlat", command=self.start_server)
ttk.Label(root, text="Sunucu Açık Kalma Süresi (dakika):").grid(row=4, column=0, padx=5, pady=5, sticky="e")
self.duration_entry = ttk.Entry(root)
self.duration_entry.grid(row=4, column=1, columnspan=2, padx=5, pady=5, sticky='nsew')
self.start_button.grid(row=5, column=0, columnspan=4, pady=10, sticky='nsew')
self.stop_button = ttk.Button(root, text="Sunucuyu Durdur", command=self.stop_server, state=tk.DISABLED)
self.stop_button.grid(row=6, column=0, columnspan=4, pady=5, sticky='nsew')
# Sunucu Durum Göstergesi
self.status_label = ttk.Label(root, text="Sunucu Durumu: Durdurulmuş", foreground="red")
self.status_label.grid(row=7, column=0, columnspan=4, pady=10)
# IP Adresleri ve kopyalama butonları
ttk.Label(root, text="Yerel IP:").grid(row=7, column=0, padx=5, pady=5, sticky="e")
self.local_ip_label = ttk.Label(root, text="Yerel IP adresi henüz mevcut değil")
self.local_ip_label.grid(row=8, column=1, padx=5, pady=5, sticky='nsew')
self.local_ip_copy_button = ttk.Button(root, text="Kopyala", command=lambda: self.copy_to_clipboard(self.local_ip_label.cget("text")))
self.local_ip_copy_button.grid(row=8, column=2, padx=5, pady=5, sticky='nsew')
ttk.Label(root, text="Dış IP:").grid(row=8, column=0, padx=5, pady=5, sticky="e")
self.external_ip_label = ttk.Label(root, text="Dış IP adresi henüz mevcut değil")
self.external_ip_label.grid(row=9, column=1, padx=5, pady=5, sticky='nsew')
self.external_ip_copy_button = ttk.Button(root, text="Kopyala", command=lambda: self.copy_to_clipboard(self.external_ip_label.cget("text")))
self.external_ip_copy_button.grid(row=9, column=2, padx=5, pady=5, sticky='nsew')
# QR Kod Gösterme
self.local_qr_button = ttk.Button(root, text="Yerel IP QR Kod Göster", command=self.show_local_qr_code, state=tk.DISABLED)
self.local_qr_button.grid(row=10, column=0, columnspan=4, pady=5, sticky='nsew')
self.external_qr_button = ttk.Button(root, text="Dış IP QR Kod Göster", command=self.show_external_qr_code, state=tk.DISABLED)
self.external_qr_button.grid(row=11, column=0, columnspan=4, pady=5, sticky='nsew')
def set_password(self):
"""
Kullanıcının belirlediği şifreyi ayarlar.
"""
global user_password
user_password = self.password_entry.get()
if user_password:
self.show_custom_messagebox("Başarılı", "Şifre başarıyla ayarlandı.")
else:
self.show_custom_messagebox("Hata", "Lütfen geçerli bir şifre girin.", error=True)
def choose_path(self):
"""
Kullanıcının paylaşmak istediği klasörü seçmesini sağlar.
"""
global SELECTED_PATH
path = filedialog.askdirectory()
if path:
self.path_label.config(text=path)
SELECTED_PATH = path
self.show_custom_messagebox("Başarılı", "Klasör seçildi ve paylaşım için hazır.")
def start_server(self):
"""
Sunucuyu başlatır ve kullanıcıya gerekli bağlantı bilgilerini gösterir.
"""
global server_thread
port = self.port_entry.get()
if not port:
port = 5000
self.port_entry.insert(0, str(port))
else:
port = int(port)
if not user_password:
self.show_custom_messagebox("Hata", "Lütfen önce bir şifre belirleyin.", error=True)
return
if not SELECTED_PATH or not os.path.isdir(SELECTED_PATH):
self.show_custom_messagebox("Hata", "Lütfen önce bir klasör seçin.", error=True)
return
server_thread = threading.Thread(target=lambda: app.run(host="0.0.0.0", port=port))
server_thread.daemon = True
server_thread.start()
duration = self.duration_entry.get()
if duration.isdigit():
duration_minutes = int(duration)
threading.Timer(duration_minutes * 60, self.stop_server).start()
self.local_ip_label.config(text=f"http://{get_local_ip()}:5000")
self.external_ip_label.config(text=f"http://{get_external_ip()}:5000")
self.start_button.config(state=tk.DISABLED)
self.local_qr_button.config(state=tk.NORMAL)
self.external_qr_button.config(state=tk.NORMAL)
self.stop_button.config(state=tk.NORMAL)
self.status_label.config(text="Sunucu Durumu: Çalışıyor", foreground="green")
self.show_custom_messagebox("Başlatıldı", f"Sunucu {port} portunda çalışmaya başladı.")
def stop_server(self):
"""
Sunucuyu durdurur ve arayüzü eski haline getirir.
"""
global server_thread
if server_thread:
os.kill(os.getpid(), signal.SIGTERM)
server_thread = None
self.local_ip_label.config(text="Yerel IP adresi henüz mevcut değil")
self.external_ip_label.config(text="Dış IP adresi henüz mevcut değil")
self.start_button.config(state=tk.NORMAL)
self.stop_button.config(state=tk.DISABLED)
self.local_qr_button.config(state=tk.DISABLED)
self.external_qr_button.config(state=tk.DISABLED)
self.status_label.config(text="Sunucu Durumu: Durdurulmuş", foreground="red")
def copy_to_clipboard(self, text):
"""
Belirtilen metni panoya kopyalar.
"""
self.root.clipboard_clear()
self.root.clipboard_append(text)
self.show_custom_messagebox("Kopyalandı", f"Bağlantı panoya kopyalandı: {text}")
def show_local_qr_code(self):
"""
Yerel IP adresi için QR kodu gösterir.
"""
local_url = self.local_ip_label.cget("text")
local_qr_image = generate_qr_code(local_url)
local_qr_window = tk.Toplevel(self.root)
local_qr_window.title("Yerel IP QR Kod")
local_label = tk.Label(local_qr_window, image=local_qr_image)
local_label.image = local_qr_image
local_label.pack()
def show_external_qr_code(self):
"""
Dış IP adresi için QR kodu gösterir.
"""
external_url = self.external_ip_label.cget("text")
external_qr_image = generate_qr_code(external_url)
external_qr_window = tk.Toplevel(self.root)
external_qr_window.title("Dış IP QR Kod")
external_label = tk.Label(external_qr_window, image=external_qr_image)
external_label.image = external_qr_image
external_label.pack()
def toggle_dark_mode(self):
"""
Karanlık modu açıp kapatma işlevi.
"""
if self.root.cget("bg") == "#2e2e2e":
self.root.config(bg=self.root.cget('default'))
for widget in self.root.winfo_children():
widget.config(bg=self.root.cget('default'), fg='black')
else:
self.root.config(bg="#2e2e2e")
for widget in self.root.winfo_children():
if isinstance(widget, ttk.Label) or isinstance(widget, ttk.Button) or isinstance(widget, ttk.Entry):
style = ttk.Style()
style.configure("Dark.TLabel", background="#2e2e2e", foreground="white")
style.configure("Dark.TButton", background="#444444", foreground="white")
style.configure("Dark.TEntry", fieldbackground="#444444", foreground="white")
widget.config(style="Dark.TLabel" if isinstance(widget, ttk.Label) else
"Dark.TButton" if isinstance(widget, ttk.Button) else
"Dark.TEntry")
else:
widget.config(bg="#444444", fg="white")
def show_connection_settings(self):
"""
Bağlantı ayarlarını gösteren bir bilgi kutusu.
"""
self.show_custom_messagebox("Bağlantı Ayarları", "Bu menüden bağlantı ve diğer ayarları yapabilirsiniz.")
# Program başlatma
root = tk.Tk()
app_gui = SimpleHTTPGUI(root)
root.mainloop()