View | Details | Raw Unified | Return to bug 39906
Collapse All | Expand All

(-)a/debian/templates/apache-shared-opac-antibot.conf (-1 / +1 lines)
Lines 3-9 RewriteEngine on Link Here
3
#NOTE: To override this setting of ANTIBOT_DO, in the parent VirtualHost add the following: SetEnvIf Request_URI ^ ANTIBOT_OVERRIDE=true
3
#NOTE: To override this setting of ANTIBOT_DO, in the parent VirtualHost add the following: SetEnvIf Request_URI ^ ANTIBOT_OVERRIDE=true
4
#You can then provide your own conditions for setting the ANTIBOT_DO environmental variable
4
#You can then provide your own conditions for setting the ANTIBOT_DO environmental variable
5
RewriteCond %{ENV:ANTIBOT_OVERRIDE} ^$
5
RewriteCond %{ENV:ANTIBOT_OVERRIDE} ^$
6
RewriteCond expr "%{REQUEST_URI} =~ m#^/cgi-bin/koha/(opac-detail.pl|opac-export.pl|opac-suggestions.pl|opac-search.pl|opac-authoritiesdetail.pl|opac-ISBDdetail.pl|opac-MARCdetail.pl|opac-shelves.pl)$#"
6
RewriteCond expr "%{REQUEST_URI} =~ m#^/cgi-bin/koha/(opac-main.pl|opac-detail.pl|opac-export.pl|opac-suggestions.pl|opac-search.pl|opac-authoritiesdetail.pl|opac-ISBDdetail.pl|opac-MARCdetail.pl|opac-shelves.pl)$#"
7
RewriteCond %{HTTP:Cookie} !(^|;\s*)CGISESSID= [NC]
7
RewriteCond %{HTTP:Cookie} !(^|;\s*)CGISESSID= [NC]
8
#NOTE: The KOHA_INIT is set by Javascript by the fast challenge webpage
8
#NOTE: The KOHA_INIT is set by Javascript by the fast challenge webpage
9
RewriteCond %{HTTP:Cookie} !(^|;\s*)KOHA_INIT= [NC]
9
RewriteCond %{HTTP:Cookie} !(^|;\s*)KOHA_INIT= [NC]
(-)a/koha-tmpl/opac-tmpl/lib/koha_fast_challenge/index.js (-24 / +110 lines)
Lines 1-34 Link Here
1
document.addEventListener("DOMContentLoaded", event => {
1
document.addEventListener("DOMContentLoaded", (event) => {
2
    const timeout_base = 0;
2
  // --- Configuration ---
3
    let timeout_incr = 250;
3
  const config = {
4
    baseTimeout: 250,
5
    penalties: {
6
      webdriver: 20,
7
      spoofedWebdriver: 50,
8
      noPlugins: 10,
9
      noMimeTypes: 10,
10
      noLanguages: 10,
11
      noUserAgent: 50,
12
      fastRFA: 5,
13
      noInteraction: 25,
14
    },
15
    workerBaseIterations: 750000,
16
    interactionCheckDelay: 3000,
17
    botScoreThreshold: 15,
18
  };
4
19
5
    if (navigator.webdriver){
20
  let checksHaveRun = false;
6
        timeout_incr += 10000
21
7
    }
22
  function runAntiBotChecks() {
8
    if (navigator.plugins.length === 0){
23
    if (checksHaveRun) return;
9
        timeout_incr += 5000;
24
    checksHaveRun = true;
10
    }
25
11
    if (navigator.mimeTypes.length === 0){
26
    let botScore = 0;
12
        timeout_incr += 5000;
27
    let userInteracted = false;
13
    }
28
14
    if (!navigator.languages || navigator.languages.length === 0){
29
    // --- Detection Phase ---
15
        timeout_incr += 5000;
30
    if (navigator.webdriver) botScore += config.penalties.webdriver;
31
    if (navigator.plugins.length === 0) botScore += config.penalties.noPlugins;
32
    if (navigator.mimeTypes.length === 0)
33
      botScore += config.penalties.noMimeTypes;
34
    if (!navigator.languages || navigator.languages.length === 0)
35
      botScore += config.penalties.noLanguages;
36
    if (!navigator.userAgent) botScore += config.penalties.noUserAgent;
37
38
    try {
39
      const descriptor = Object.getOwnPropertyDescriptor(
40
        Navigator.prototype,
41
        "webdriver"
42
      );
43
      if (descriptor && !descriptor.get.toString().includes("native code")) {
44
        botScore += config.penalties.spoofedWebdriver;
45
      }
46
    } catch (e) {
47
      botScore += config.penalties.spoofedWebdriver;
16
    }
48
    }
49
17
    const timestamp1 = performance.now();
50
    const timestamp1 = performance.now();
18
    requestAnimationFrame(() => {
51
    requestAnimationFrame(() => {
19
        const delay = performance.now() - timestamp1;
52
      if (performance.now() - timestamp1 < 20) {
20
        if (delay < 20){
53
        botScore += config.penalties.fastRFA;
21
            timeout_incr += 1000;
54
      }
22
        }
23
    });
55
    });
24
56
25
    let final_timeout = timeout_base + timeout_incr;
57
    const interactionEvents = ["mousemove", "keydown", "scroll"];
58
    const recordInteraction = () => {
59
      userInteracted = true;
60
      interactionEvents.forEach((name) =>
61
        document.removeEventListener(name, recordInteraction)
62
      );
63
    };
64
    interactionEvents.forEach((name) =>
65
      document.addEventListener(name, recordInteraction, { passive: true })
66
    );
67
68
    // --- Action Phase ---
26
    setTimeout(() => {
69
    setTimeout(() => {
27
        let koha_init_cookie = "KOHA_INIT=1; path=/; SameSite=Lax";
70
      if (!userInteracted) {
28
        if (location.protocol === 'https:'){
71
        botScore += config.penalties.noInteraction;
29
            koha_init_cookie += "; Secure";
72
      }
73
74
      console.log(`Final bot score: ${botScore}`);
75
76
      if (botScore >= config.botScoreThreshold) {
77
        console.log("High bot score. Engaging parallel CPU trap.");
78
        try {
79
          const worker = new Worker("worker.js");
80
          const taskIterations =
81
            config.workerBaseIterations * (1 + botScore / 20);
82
          worker.postMessage({ iterations: taskIterations });
83
        } catch (e) {
84
          console.error("Could not create Web Worker.", e);
30
        }
85
        }
31
        document.cookie = koha_init_cookie;
86
      }
32
        location.reload();
87
88
      const finalTimeout = config.baseTimeout + botScore * 150;
89
      setCookieAndReload(finalTimeout);
90
    }, config.interactionCheckDelay);
91
  }
92
93
  function setCookieAndReload(final_timeout) {
94
    console.log(`Final timeout: ${final_timeout}ms`);
95
    setTimeout(() => {
96
      let koha_init_cookie = "KOHA_INIT=1; path=/; SameSite=Lax";
97
      if (location.protocol === "https:") {
98
        koha_init_cookie += "; Secure";
99
      }
100
      document.cookie = koha_init_cookie;
101
      location.reload();
33
    }, final_timeout);
102
    }, final_timeout);
103
  }
104
105
  // --- Visibility API Implementation ---
106
  if (document.visibilityState === "visible") {
107
    runAntiBotChecks();
108
  } else {
109
    document.addEventListener(
110
      "visibilitychange",
111
      function onVisible() {
112
        if (document.visibilityState === "visible") {
113
          document.removeEventListener("visibilitychange", onVisible);
114
          runAntiBotChecks();
115
        }
116
      },
117
      { once: true }
118
    );
119
  }
34
});
120
});
(-)a/koha-tmpl/opac-tmpl/lib/koha_fast_challenge/worker.js (-1 / +19 lines)
Line 0 Link Here
0
- 
1
self.onmessage = function (e) {
2
  const iterations = e.data.iterations || 100000;
3
  let primes = 0;
4
5
  function isPrime(num) {
6
    for (let i = 2, s = Math.sqrt(num); i <= s; i++) {
7
      if (num % i === 0) return false;
8
    }
9
    return num > 1;
10
  }
11
12
  for (let i = 0; i < iterations; i++) {
13
    if (isPrime(i)) {
14
      primes++;
15
    }
16
  }
17
18
  self.postMessage({ done: true, primes: primes });
19
};

Return to bug 39906