juice-shop / multi-juicer

Host and manage multiple Juice Shop instances for security trainings and Capture The Flags
Apache License 2.0
273 stars 129 forks source link

Missing points configuration for emptyUserRegistration #166

Closed stuebingerb closed 1 year ago

stuebingerb commented 1 year ago

juice-balancer pod complains:

Difficulty for challenge "emptyUserRegistration" is unknown. MultiJuicer version might be incompatible with the Juice Shop version used.

juice-balancer version: multi-juicer: ghcr.io/juice-shop/multi-juicer/juice-balancer:v6.0.0 juice-shop version: juice-shop: bkimminich/juice-shop:v15.0.0

This also breaks the score board sorting, and the relevant pod will show up with empty points.

J12934 commented 1 year ago

😅 Just ran a CTF / hackathon yesterday, had the same thing happen.

I just updated the mapping. Will release a 6.0.1 version ASAP. Will also start working on a proper solution that this hacky lookup map isn't required any more :D

Thank you for reaching out and reporting this 👍

stuebingerb commented 1 year ago

Thanks! We're currently in a running CTF 😉 😀 (but we know how to work around, so all fine)

J12934 commented 1 year ago

Ok perfect :D

We used this quickly hacked together script to calculate the scores, just in case it's helpful for you: (Label selectors likjely need to be updated a bit if you are already on v6, this was still using run using v5.3.0)

const keyDifficultyMapping = Object.freeze({
  restfulXssChallenge: 3,
  accessLogDisclosureChallenge: 4,
  registerAdminChallenge: 3,
  adminSectionChallenge: 2,
  fileWriteChallenge: 6,
  resetPasswordBjoernOwaspChallenge: 3,
  tokenSaleChallenge: 5,
  rceChallenge: 5,
  emptyUserRegistration: 2,
  captchaBypassChallenge: 3,
  changePasswordBenderChallenge: 5,
  christmasSpecialChallenge: 4,
  usernameXssChallenge: 4,
  persistedXssUserChallenge: 3,
  directoryListingChallenge: 1,
  localXssChallenge: 1,
  dbSchemaChallenge: 3,
  deprecatedInterfaceChallenge: 2,
  easterEggLevelOneChallenge: 4,
  emailLeakChallenge: 5,
  ephemeralAccountantChallenge: 4,
  errorHandlingChallenge: 1,
  manipulateClockChallenge: 4,
  extraLanguageChallenge: 5,
  feedbackChallenge: 2,
  forgedCouponChallenge: 6,
  forgedFeedbackChallenge: 3,
  forgedReviewChallenge: 3,
  jwtForgedChallenge: 6,
  forgottenDevBackupChallenge: 4,
  forgottenBackupChallenge: 4,
  typosquattingAngularChallenge: 5,
  ghostLoginChallenge: 3,
  dataExportChallenge: 4,
  httpHeaderXssChallenge: 4,
  continueCodeChallenge: 6,
  dlpPasswordSprayingChallenge: 5,
  dlpPastebinDataLeakChallenge: 4,
  typosquattingNpmChallenge: 4,
  loginAdminChallenge: 2,
  loginAmyChallenge: 3,
  loginBenderChallenge: 3,
  oauthUserPasswordChallenge: 4,
  loginCisoChallenge: 5,
  loginJimChallenge: 3,
  loginRapperChallenge: 2,
  loginSupportChallenge: 6,
  basketManipulateChallenge: 3,
  misplacedSignatureFileChallenge: 4,
  timingAttackChallenge: 6,
  easterEggLevelTwoChallenge: 4,
  noSqlCommandChallenge: 4,
  noSqlOrdersChallenge: 5,
  noSqlReviewsChallenge: 4,
  redirectCryptoCurrencyChallenge: 1,
  weakPasswordChallenge: 2,
  negativeOrderChallenge: 3,
  premiumPaywallChallenge: 6,
  privacyPolicyChallenge: 1,
  privacyPolicyProofChallenge: 3,
  changeProductChallenge: 3,
  reflectedXssChallenge: 2,
  passwordRepeatChallenge: 1,
  resetPasswordBenderChallenge: 4,
  resetPasswordBjoernChallenge: 5,
  resetPasswordJimChallenge: 3,
  resetPasswordMortyChallenge: 5,
  retrieveBlueprintChallenge: 5,
  ssrfChallenge: 6,
  sstiChallenge: 6,
  scoreBoardChallenge: 1,
  closeNotificationsChallenge: 1,
  securityPolicyChallenge: 2,
  persistedXssFeedbackChallenge: 4,
  hiddenImageChallenge: 4,
  rceOccupyChallenge: 6,
  supplyChainAttackChallenge: 5,
  twoFactorAuthUnsafeSecretStorageChallenge: 5,
  jwtUnsignedChallenge: 5,
  uploadSizeChallenge: 3,
  uploadTypeChallenge: 3,
  unionSqlInjectionChallenge: 4,
  videoXssChallenge: 6,
  basketAccessChallenge: 2,
  knownVulnerableComponentChallenge: 4,
  weirdCryptoChallenge: 2,
  redirectChallenge: 4,
  xxeFileDisclosureChallenge: 3,
  xxeDosChallenge: 5,
  zeroStarsChallenge: 1,
  missingEncodingChallenge: 1,
  svgInjectionChallenge: 5,
  exposedMetricsChallenge: 1,
  freeDeluxeChallenge: 3,
  csrfChallenge: 3,
  xssBonusChallenge: 1,
  resetPasswordUvoginChallenge: 4,
  geoStalkingMetaChallenge: 2,
  geoStalkingVisualChallenge: 2,
  killChatbotChallenge: 5,
  nullByteChallenge: 4,
  bullyChatbotChallenge: 1,
  lfrChallenge: 5,
  closeNotificationsChallenge: 1,
});

// Work on POSIX and Windows
const fs = require("fs");
const stdinBuffer = fs.readFileSync(0); // STDIN_FILENO = 0
const deployments = JSON.parse(stdinBuffer.toString());

deployments.items.map((deployment) => {
  const challenges = JSON.parse(deployment.metadata.annotations["multi-juicer.iteratec.dev/challenges"])

  const score = challenges
    .map((challenge) => challenge.key)
    .map((key) => {
      if (!keyDifficultyMapping.hasOwnProperty(key)) {
        console.error("missing " + key)
        return 1;
      }
      return keyDifficultyMapping[key]
    })
    .map(difficulty => difficulty * 10)
    .reduce((a,b) => {return a + b}, 0)

  return {name: deployment.metadata.name, score}
})
.toSorted((a,b) => b.score - a.score)
.forEach(({name, score}) => console.log(`${name}: ${score}`))
kubectl get deployments.apps -l app=juice-shop -ojson | node emergency-score.js