この記事では、よくある疑問にできるだけお答えしました。まず最初のステップは、どのような保護システムが使われているかを特定することです。そのために、代表的なキャプチャやボット対策システムの一覧を参照できます。ここには、どの仕組みが使われているかを素早く見分けるための画面イメージや主な特徴がまとめられています。
もしサイトで ALTCHA が使われていることが分かったら、次のステップはその特徴と動作をより詳しく確認することです。同じこの記事の中で、ALTCHA をサイトに導入するための手順書も確認できるので、あなたのサイト上でどのように機能しているのかをしっかり理解できます。これにより、現在の保護を正しく把握できるだけでなく、今後の運用や保守も計画的に行えるようになります。
ALTCHA を含むフォームをテストする際は、キャプチャが正しく組み込まれ機能しているか確認する必要があります。
サイトに埋め込まれたキャプチャを手動で確認する方法
自動解決には CapMonster Cloud のようなツールを使うと便利です。キャプチャのパラメータを送信すると、サーバー側で処理して利用可能なトークンを返してくれます。そのトークンをフォームに挿入すれば、ユーザー操作なしでチェックを通過できます。
CapMonster Cloud API を使った一般的な手順:
ALTCHAを解決するリクエストには、以下のパラメータを指定する必要があります:
type - CustomTask
class - altcha
websiteURL - キャプチャを解くページのアドレス
websiteKey - このタスクでは空文字列を送信することが許可されています。
challenge(metadata内) - ウェブページから取得したタスクのユニークID。
iterations(metadata内) - 計算の反復回数または最大値。重要:iterationsパラメータはmaxnumberの値に対応します!
salt(metadata内) - サイトから取得したsaltで、ハッシュ生成に使用されます。
signature(metadata内) - リクエストのデジタル署名。
userAgent - ブラウザのUser-Agent。Windowsの最新UAのみを送信してください。
https://api.capmonster.cloud/createTask{
"clientKey": "API_KEY",
"task": {
"type": "CustomTask",
"class": "altcha",
"websiteURL": "https://example.com",
"websiteKey": "",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
"metadata": {
"challenge": "3dd28253be6cc0c54d95f7f98c517e68744597cc6e66109619d1ac975c39181c",
"iterations": "5000",
"salt":"46d5b1c8871e5152d902ee3f?edk=1493462145de1ce33a52fb569b27a364&codeChallenge=464Cjs7PbiJJhJZ_ReJ-y9UGGDndcpsnP6vS8x1nEJyTkhjQkJyL2jcnYEuMKcrG&expires=1761048664",
"signature": "4b1cf0e0be0f4e5247e50b0f9a449830f1fbca44c32ff94bc080146815f31a18"
}
}
}
{
"errorId":0,
"taskId":407533072
}https://api.capmonster.cloud/getTaskResult{
"clientKey":"API_KEY",
"taskId": 407533072
}
{
"errorId": 0,
"status": "ready",
"solution": {
"data": {
"token": "eyJhbGdvcml0aG0iOiJTSEEtMjU2IiwiY2hhbGxlbmdlIjoiNjMxOGUzYzc2NjhlOTZiMmFlYjg2NGU2NmRmMTliODRkYmYwZDBhMWRjNjYwMDdiMGM5ZGI4ODZiNTUxNjQxNiIsIm51bWJlciI6MTY0NDcsInNhbHQiOiJiMTQ1YWE5ZmU5MjA3NjBiMDgxYTAwNTMiLCJzaWduYXR1cmUiOiI5NzM4MmJlODE2NDUwNzk5MzlhYmU2M2ZkYzZjN2E3ZGYwOTM5MzNjODljZTk0ZjgzNTgxYmUyNDU3ZmI4MDM0IiwidG9vayI6MTczLjl9",
"number": "16447"
}
}
}
// npm install playwright
// npx playwright install chromium
const { chromium } = require("playwright");
const API_KEY = "YOUR_API_KEY";
const ALTCHA_PAGE = "https://example.com"; // ALTCHAを設置したあなたのサイト
(async () => {
const browser = await chromium.launch({ headless: false, devtools: true });
const context = await browser.newContext();
const page = await context.newPage();
// Altchaエンドポイントからの全ての応答を取得
let challengeResp = null;
page.on("response", async (response) => {
try {
const url = response.url();
if (url.startsWith("https://captcha.example.com/altcha")) { // Altchaエンドポイント
challengeResp = await response.json();
console.log("Captured Altcha response:", challengeResp);
}
} catch (err) {
console.warn("Error parsing Altcha response:", err);
}
});
await page.goto(ALTCHA_PAGE, { waitUntil: "networkidle" });
// ウィジェットがあればクリック
const widgetHandle = await page.$("altcha-widget");
if (widgetHandle) {
try {
await widgetHandle.click();
} catch {}
}
// challengeの出現を待つ
const start = Date.now();
while (!challengeResp && Date.now() - start < 60000) { // タイムアウト延長
await new Promise((r) => setTimeout(r, 300));
}
if (!challengeResp) {
console.error("Failed to capture Altcha challenge.");
await browser.close();
return;
}
const { challenge, salt, signature, maxnumbers } = challengeResp;
// CapMonster Cloudでタスク作成
const createTaskBody = {
clientKey: API_KEY,
task: {
type: "CustomTask",
class: "altcha",
websiteURL: ALTCHA_PAGE,
websiteKey: "",
userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
metadata: {
challenge,
iterations: maxnumbers || 100000,
salt,
signature,
},
},
};
const taskResp = await fetch("https://api.capmonster.cloud/createTask", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(createTaskBody),
}).then((r) => r.json());
console.log("CreateTask response:", taskResp);
if (!taskResp?.taskId) {
console.error("CreateTask failed:", taskResp);
await browser.close();
return;
}
const taskId = taskResp.taskId;
// 解決を取得
let fullSolution = null;
const pollStart = Date.now();
while (Date.now() - pollStart < 120000) {
const res = await fetch("https://api.capmonster.cloud/getTaskResult", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ clientKey: API_KEY, taskId }),
}).then((r) => r.json());
if (res.status === "ready") {
fullSolution = res.solution;
console.log("Solution:", fullSolution);
break;
}
await new Promise((r) => setTimeout(r, 3000));
}
if (!fullSolution) {
console.error("No solution received in time.");
await browser.close();
return;
}
const token = fullSolution?.data?.token || fullSolution?.token || fullSolution?.data;
if (!token) {
console.error("Token not found in solution:", fullSolution);
await browser.close();
return;
}
//トークンを挿入
await page.evaluate((t) => {
let input = document.querySelector("#captchaParaValidar");
if (!input) {
input = document.createElement("input");
input.type = "hidden";
input.id = "captchaParaValidar";
input.name = "captchaParaValidar";
(document.querySelector("form") || document.body).appendChild(input);
}
input.value = t;
let alt = document.querySelector('input[name="altcha"]');
if (!alt) {
alt = document.createElement("input");
alt.type = "hidden";
alt.name = "altcha";
(document.querySelector("form") || document.body).appendChild(alt);
}
alt.value = t;
const widget = document.querySelector("altcha-widget");
if (widget) {
widget.setAttribute("data-state", "verified");
const checkbox = widget.querySelector("input[type='checkbox']");
if (checkbox) {
checkbox.checked = true;
checkbox.dispatchEvent(new Event("change", { bubbles: true }));
}
const label = widget.querySelector(".altcha-label");
if (label) label.textContent = "Verified";
}
}, token);
console.log("Token injected:", token);
})();1. ウィジェットのインストール
オプション1 — CDN経由(最も簡単)。HTMLの<head>に追加:
<script async defer src="https://cdn.jsdelivr.net/gh/altcha-org/altcha/dist/altcha.min.js" type="module"></script>オプション2 — npm経由:
npm install altchaJSファイルにウィジェットをインポート:
import "altcha";2. フォームへのウィジェット追加。
保護が必要なフォームに<altcha-widget>コンポーネントを挿入:
<form method="POST" action="/submit">
<altcha-widget challengeurl="/altcha/challenge"></altcha-widget>
<button type="submit">Send</button>
</form>challengeurl — チャレンジを発行するサーバーエンドポイント。
もしALTCHA Sentinel(ボットやスパム対策済みサーバー保護、機械学習とトラフィック解析)を使う場合は、自分のサーバーの代わりにそのURLを使用:
<altcha-widget
challengeurl="https://sentinel.example.com/v1/challenge?apiKey=YOUR_API_KEY">
</altcha-widget>3. サーバー側検証。
検証の流れ:
ALTCHA Sentinelによる検証:
import { verifyServerSignature } from 'altcha-lib';
// Sentinelで生成された秘密APIキー
const apiKeySecret = 'sec_...';
// ウィジェットからのpayload
const payload = '...';
// 検証
const { verificationData, verified } = await verifyServerSignature(payload, apiKeySecret);
if (verified) {
// 検証成功 — フォームデータを処理可能
}
const resp = await fetch('https://sentinel.example.com/v1/verify/signature', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ payload }),
});
const { verified } = await resp.json();
if (verified) {
// 検証成功 — フォーム処理
}
APIは同じpayloadの再利用を自動で防止。
4. Sentinelなしで検証(独自サーバー)
チャレンジ生成:
import { createChallenge } from 'altcha-lib';
const hmacKey = '$ecret.key'; // あなたのHMAC秘密キー
const challenge = await createChallenge({ hmacKey });
// ウィジェット用にJSONでチャレンジを返すフォーム送信時のpayload検証:
import { verifySolution } from 'altcha-lib';
const hmacKey = '$ecret.key'; // あなたのHMAC秘密キー
const verified = await verifySolution(payload, hmacKey);
if (verified) {
// 検証成功 — フォームデータ処理
}
この場合、/altcha/challengeエンドポイントを自分で作成し、サーバーでチャレンジを検証。
すでにキャプチャや別の保護システムが導入されているサイトを引き継いだものの、コードにはアクセスできない場合でも心配はいりません!どの技術が使われているかを特定するのはそれほど難しくありません。動作が正しいか確認するには、隔離されたテスト環境で認識サービスCapMonster Cloudを利用し、トークン処理の仕組みと検証ロジックが正しく機能しているかをチェックできます。
ALTCHAの場合も、システムを特定し、その挙動を調べて、保護機能が正しく動いていることを確認すれば十分です。この記事では、ALTCHAを見分ける方法と、その導入や再設定に関する手順書の見つけ方を紹介しました。これにより、防御を安心して維持し、その動作をしっかりと管理できます。