Secret Hitler Vulns

Two low-moderate vulnerabilites on the open source Secret Hitler game. Note that a lot of the vulnerabilites are due to the use of JSON parsing, which allows attackers to submit arbitrary objects to the endpoints.

Obfuscated IP Leakage

The check in the /profile endpoint is unnecessarily complex, and forgets an edge case.

if (req && req.user && requestingUser && requestingUser !== 'undefined' && req.user.username && requestingUser !== req.user.username) {
  // Error 

Note that if the user is not signed in, then req.user becomes undefined. Thus, the branch becomes false and I am able to set requestingUser to whatever they want.

As a proof of concept, visit and note the inclusion of the lastConnectedIP attribute.

While the information leaked is somewhat useless - an obfuscated IP address, not the real IP - this would be useful to fix in case more information is included in the /profile endpoint later.

Email Leakage

Attackers could use the /account/reset-password endpoint to leak emails from the database.

This vulnerability can be mitigated by disabling JSON parsing.

The findOne function with controlled inputs,


combined with predictable responses,

.then(account => {
  if (!account) {
    // 401 response
  } else {
    // No response

means that the endpoint can act as a canary, lending itself to a standard blind injection.

As a proof of concept, consider the query = {
  $gte: "a",
  $lte: "b"

This would error only if there was a verification email already between “a” and “b”. In other words, the attacker will know if there is an email starting with the letter “a”. By iteratively tightening the search constraints, for example with = {
  $gte: "aa",
  $lte: "ab"

attackers can exfiltrate any number of email addresses from the database.