Module: CamaleonCms::CaptchaImageGeneration

Included in:
CaptchaHelper, RuntimeCaptchaImageConcern
Defined in:
lib/camaleon_cms/captcha_image_generation.rb

Overview

Captcha challenge/image generation shared by the two entry points that expose it: CamaleonCms::RuntimeCaptchaImageConcern (the controller stack serving GET /captcha) and CamaleonCms::CaptchaHelper (views and the runtime helper surface). Both include this module, so a captcha hardening fix cannot land in one entry point and silently miss the copy that actually runs. Parity between the entry points is guarded by spec/lib/camaleon_cms/captcha_implementation_parity_spec.rb.

Constant Summary collapse

CAPTCHA_MIN_LENGTH =

The requested length is clamped so an attacker-supplied ?len= can neither make the worker build an arbitrarily large challenge string for ImageMagick to draw (H4 resource exhaustion) nor shrink the answer space to a brute-forceable size (H3).

4
CAPTCHA_MAX_LENGTH =
8
CAPTCHA_DEFAULT_LENGTH =
5

Instance Method Summary collapse

Instance Method Details

#cama_captcha_build(len = CAPTCHA_DEFAULT_LENGTH) ⇒ MiniMagick::Image

build a captcha image

Parameters:

  • len (Integer, nil) (defaults to: CAPTCHA_DEFAULT_LENGTH)

    Number of characters to include in captcha (default: 5)

Returns:

  • (MiniMagick::Image)


21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/camaleon_cms/captcha_image_generation.rb', line 21

def cama_captcha_build(len = CAPTCHA_DEFAULT_LENGTH)
  img = MiniMagick::Image.open(resolve_captcha_file("captcha_#{rand(12)}.jpg"))
  text = cama_rand_str(cama_captcha_length(len))
  # Single active challenge: replace, never accumulate. An append-only list let any previously
  # issued answer keep verifying, which (with a shrinkable length) made the captcha bypassable (H3).
  session[:cama_captcha] = [text]
  img.combine_options do |c|
    c.gravity('Center')
    c.fill('#FFFFFF')
    c.draw("text 0,5 #{text}")
    c.font(resolve_captcha_file('bumpyroad.ttf'))
    c.pointsize('30')
  end
end