← Back to research

YesWeHack Dojo #53 · Report #2123-5018 · Code injection · Resolved · High (7.5)

Hacker Club: email parsing and ERB injection

The validator and email parser read the same address differently. I used that mismatch to get past validation, then put ERB template code into the invitation’s display name.

View report #2123-5018 on YesWeHack

What was the challenge?

The application offered a fake Hacker Club signup. It sent an invite only when the recipient address resolved to a reserved domain. The goal was to receive the invite and retrieve a flag stored by the application.

Read the source first

The setup code revealed the application's working directory, domain check, and invitation template. I started by reading those parts of the source.

def signup_allowed!(addr_text)
  domains = addr_text.scan(/@\s*([a-z0-9.-]+)/i).flatten.map(&:downcase)
  raise "rejected!" if domains.include?("dojo-yeswehack.com")
  addr_text
end

The parser disagreement

The custom validation used a regular expression, while Ruby's Mail library parsed the address according to email syntax. A comment inserted after the @ caused the regular expression to stop early; the Mail parser discarded the comment and still resolved the reserved domain.

Two parts of the application looked at the same string and reached different answers. That mismatch bypassed the guard.

Following the value into the template

The invitation renderer used the recipient display name in an ERB template. The value was interpolated into the template text before ERB evaluated it, turning controlled display-name content into executable template syntax.

def render_invite(m)
  name = m[:to].addrs.first.display_name || "guest"
  ERB.new("Welcome to the Hacker Club #{name}!").result(binding)
end

Combining the parser mismatch with unsafe template interpolation produced the intended challenge path: a validation bypass followed by server-side template injection.

Distractors and verification

The challenge included planted false flags and an irrelevant, patched exploit to steer automated solvers and hurried readers in the wrong direction. I traced the input through the code to check which path actually worked.

Key lessons

  • Validation and consumption must agree on how input is interpreted.
  • Interpolating untrusted input before template evaluation can turn data into code.
  • When source is available, read and trace it before testing blindly.
  • Verify apparently easy answers; deliberate distractions are part of the exercise.