CaptchaAI'nin geri arama URL'si özelliğini (pingback) kullandığınızda, sunucunuz CAPTCHA çözümleri alan bir HTTP uç noktasını kullanıma sunar. Doğrulama olmadan bu URL'yi keşfeden herkes sahte çözümler gönderebilir. Bu eğitimde geri arama uç noktalarının güvenliğinin nasıl sağlanacağı anlatılmaktadır.
Geri Arama Akışı
1. You submit task:
POST https://ocr.captchaai.com/in.php
?key=YOUR_API_KEY
&method=userrecaptcha
&googlekey=SITE_KEY
&pageurl=https://example.com
&pingback=https://your-server.com/captcha/callback
2. CaptchaAI solves the CAPTCHA
3. CaptchaAI sends result to your endpoint:
GET https://your-server.com/captcha/callback?id=TASK_ID&code=SOLUTION_TOKEN
Sorun: 3. adım, kimliği doğrulanmamış bir istektir. Gerçekten CaptchaAI'den geldiğini doğrulamanız gerekiyor.
Doğrulama Stratejisi 1: Görev Kimliği Doğrulaması
En basit yaklaşım; yalnızca gerçekten gönderdiğiniz görev kimliklerinin geri arama sonuçlarını kabul etmektir.
Python (Şişe)
import os
import threading
import requests
from flask import Flask, request, jsonify
app = Flask(__name__)
# Thread-safe set of pending task IDs
pending_tasks = set()
pending_lock = threading.Lock()
results = {}
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
def submit_captcha(sitekey, pageurl):
"""Submit CAPTCHA and register the task ID."""
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": pageurl,
"pingback": "https://your-server.com/captcha/callback",
"json": 1
})
data = resp.json()
if data.get("status") == 1:
task_id = data["request"]
with pending_lock:
pending_tasks.add(task_id)
return task_id
return None
@app.route("/captcha/callback")
def captcha_callback():
task_id = request.args.get("id")
solution = request.args.get("code")
# Validate: only accept known task IDs
with pending_lock:
if task_id not in pending_tasks:
return jsonify({"error": "unknown task"}), 403
pending_tasks.discard(task_id)
results[task_id] = solution
return "OK", 200
JavaScript (Ekspres)
const express = require("express");
const axios = require("axios");
const app = express();
const API_KEY = process.env.CAPTCHAAI_API_KEY;
const pendingTasks = new Set();
const results = new Map();
async function submitCaptcha(sitekey, pageurl) {
const resp = await axios.post("https://ocr.captchaai.com/in.php", null, {
params: {
key: API_KEY,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: pageurl,
pingback: "https://your-server.com/captcha/callback",
json: 1,
},
});
if (resp.data.status === 1) {
const taskId = resp.data.request;
pendingTasks.add(taskId);
return taskId;
}
return null;
}
app.get("/captcha/callback", (req, res) => {
const taskId = req.query.id;
const solution = req.query.code;
// Validate: only accept known task IDs
if (!pendingTasks.has(taskId)) {
return res.status(403).json({ error: "unknown task" });
}
pendingTasks.delete(taskId);
results.set(taskId, solution);
res.sendStatus(200);
});
app.listen(3000);
Doğrulama Stratejisi 2: HMAC İmza Tokenı
Geri arama URL'nize saldırganların tahmin edemeyeceği gizli bir belirteç ekleyin.
Python
import hashlib
import hmac
import os
CALLBACK_SECRET = os.environ["CALLBACK_SECRET"] # Random 32+ character string
def generate_callback_url(task_id):
"""Generate callback URL with HMAC signature."""
signature = hmac.new(
CALLBACK_SECRET.encode(),
task_id.encode(),
hashlib.sha256
).hexdigest()
return f"https://your-server.com/captcha/callback?token={signature}"
@app.route("/captcha/callback")
def captcha_callback():
task_id = request.args.get("id")
token = request.args.get("token")
solution = request.args.get("code")
# Verify HMAC signature
expected = hmac.new(
CALLBACK_SECRET.encode(),
task_id.encode(),
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(token, expected):
return jsonify({"error": "invalid signature"}), 403
results[task_id] = solution
return "OK", 200
JavaScript
const crypto = require("crypto");
const CALLBACK_SECRET = process.env.CALLBACK_SECRET;
function generateCallbackUrl(taskId) {
const signature = crypto
.createHmac("sha256", CALLBACK_SECRET)
.update(taskId)
.digest("hex");
return `https://your-server.com/captcha/callback?token=${signature}`;
}
app.get("/captcha/callback", (req, res) => {
const taskId = req.query.id;
const token = req.query.token;
const solution = req.query.code;
// Verify HMAC signature
const expected = crypto
.createHmac("sha256", CALLBACK_SECRET)
.update(taskId)
.digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(token), Buffer.from(expected))) {
return res.status(403).json({ error: "invalid signature" });
}
results.set(taskId, solution);
res.sendStatus(200);
});
Gönderirken oluşturulan URL'yi kullanın: pingback=https://your-server.com/captcha/callback?token=HMAC_SIGNATURE.
Doğrulama Stratejisi 3: IP İzin Verilenler Listesine Ekleme
Geri arama uç noktanızı CaptchaAI'nin sunucu IP'leriyle sınırlandırın.
Python (Şişe)
# CaptchaAI callback source IPs (verify current IPs with CaptchaAI support)
ALLOWED_IPS = {"138.201.XX.XX", "148.251.XX.XX"} # Replace with actual IPs
@app.before_request
def check_ip():
if request.path.startswith("/captcha/callback"):
client_ip = request.remote_addr
if client_ip not in ALLOWED_IPS:
return jsonify({"error": "forbidden"}), 403
JavaScript (Ekspres)
const ALLOWED_IPS = new Set(["138.201.XX.XX", "148.251.XX.XX"]);
app.use("/captcha/callback", (req, res, next) => {
const clientIp = req.ip || req.connection.remoteAddress;
if (!ALLOWED_IPS.has(clientIp)) {
return res.status(403).json({ error: "forbidden" });
}
next();
});
Not: Geri arama kaynağı IP'lerinin geçerli listesi için CaptchaAI desteğine başvurun. Ters proxy arkasındaysanız
X-Forwarded-Forüstbilgilerinin doğru şekilde yapılandırıldığından emin olun.
Tekrar Saldırısını Önleme
Geçerli geri aramalar bile tekrar oynatılabilir. Zaman damgası kontrolü ve tek kullanımlık yaptırım ekleyin:
Python
import time
CALLBACK_TTL = 300 # Reject callbacks older than 5 minutes
used_callbacks = set()
@app.route("/captcha/callback")
def captcha_callback():
task_id = request.args.get("id")
timestamp = request.args.get("ts")
solution = request.args.get("code")
# Check timestamp freshness
if timestamp:
age = time.time() - float(timestamp)
if age > CALLBACK_TTL or age < 0:
return jsonify({"error": "expired"}), 403
# One-time use
if task_id in used_callbacks:
return jsonify({"error": "already processed"}), 409
used_callbacks.add(task_id)
results[task_id] = solution
return "OK", 200
Birleşik Güvenlik Kontrol Listesi
| Katman | Karşı Koruma | Uygulama |
|---|---|---|
| Görev Kimliği doğrulaması | Rastgele/unknown görev enjeksiyonu | Bekleyen kimlikleri saklayın, bilinmeyenleri reddedin |
| HMAC imzası | URL tahmin etme, sahte geri aramalar | Geri arama URL'sini gizli olarak imzala |
| IP'yi izin verilenler listesine ekleme | Yetkisiz sunuculardan gelen istekler | CaptchaAI IP'lerini beyaz listeye alın |
| Tekrar oynatmayı önleme | Geçerli geri aramalar yeniden gönderildi | Tek kullanımlık + zaman damgası doğrulaması |
| HTTPS | Kulak misafiri, ortadaki adam | Geri arama uç noktasında TLS |
Sorun giderme
| Sorun | Sebep | Düzeltme |
|---|---|---|
| Tüm geri aramalar reddedildi | IP izin verilenler listesi CaptchaAI IP'lerini içermiyor | Mevcut IP'leri destekle doğrulayın; ters proxy başlıklarını kontrol edin |
| HMAC doğrulaması başarısız oluyor | Gönderme ve geri arama arasında görev kimliği uyuşmazlığı | in.php tarafından döndürülen görev kimliğini tam olarak kullandığınızdan emin olun |
| Yinelenen geri aramalar işlendi | Eşzamanlı geri aramalarda yarış durumu | Atomik küme işlemlerini veya veritabanı benzersiz kısıtlamalarını kullanın |
| Geri aramalar zaman aşımına uğradı | Uç noktanın yanıt vermesi çok uzun sürüyor | Eşzamansız işle – hemen kabul et, arka planda işle |
SSS
Dört doğrulama stratejisinin tümünü birlikte mi kullanmalıyım?
Minimum olarak görev kimliği doğrulamasını (Strateji 1) kullanın. Herkese açık uç noktalar için HMAC imzaları ekleyin (Strateji 2). CaptchaAI'nin kararlı geri çağırma IP'leri yayınlaması durumunda IP izin verilenler listesine ekleme (Strateji 3) idealdir. Tekrarın önlenmesi finansal veya hassas iş akışları için çok önemlidir.
CaptchaAI sonucu gönderdiğinde geri arama uç noktam kapalıysa ne olur?
Çözüm hâlâ yoklama uç noktası (res.php) aracılığıyla kullanılabilir. Bir zaman aşımı süresi içinde geri arama almayan tüm görevleri yoklayan bir geri dönüş uygulayın.
Geri arama kimlik doğrulaması için karşılıklı TLS (mTLS) kullanabilir miyim?
Teorik olarak evet - ancak CaptchaAI'nin geri arama sistemi standart HTTPS GET isteklerini kullanır.HMAC imzaları, sertifika yönetimi gerektirmeden eşdeğer kimlik doğrulama sağlar.
İlgili Makaleler
Sonraki Adımlar
CaptchaAI geri arama uç noktalarınızı güvence altına alın —API anahtarınızı alınve imza doğrulamasını uygulayın.
İlgili kılavuzlar: