juice-shop

Форк
0
/
vulnCodeSnippet.ts 
120 строк · 4.3 Кб
1
/*
2
 * Copyright (c) 2014-2024 Bjoern Kimminich & the OWASP Juice Shop contributors.
3
 * SPDX-License-Identifier: MIT
4
 */
5

6
import { type NextFunction, type Request, type Response } from 'express'
7
import fs from 'fs'
8
import yaml from 'js-yaml'
9
import { getCodeChallenges } from '../lib/codingChallenges'
10
import * as accuracy from '../lib/accuracy'
11
import * as utils from '../lib/utils'
12

13
const challengeUtils = require('../lib/challengeUtils')
14

15
interface SnippetRequestBody {
16
  challenge: string
17
}
18

19
interface VerdictRequestBody {
20
  selectedLines: number[]
21
  key: string
22
}
23

24
const setStatusCode = (error: any) => {
25
  switch (error.name) {
26
    case 'BrokenBoundary':
27
      return 422
28
    default:
29
      return 200
30
  }
31
}
32

33
export const retrieveCodeSnippet = async (challengeKey: string) => {
34
  const codeChallenges = await getCodeChallenges()
35
  if (codeChallenges.has(challengeKey)) {
36
    return codeChallenges.get(challengeKey) ?? null
37
  }
38
  return null
39
}
40

41
exports.serveCodeSnippet = () => async (req: Request<SnippetRequestBody, Record<string, unknown>, Record<string, unknown>>, res: Response, next: NextFunction) => {
42
  try {
43
    const snippetData = await retrieveCodeSnippet(req.params.challenge)
44
    if (snippetData == null) {
45
      res.status(404).json({ status: 'error', error: `No code challenge for challenge key: ${req.params.challenge}` })
46
      return
47
    }
48
    res.status(200).json({ snippet: snippetData.snippet })
49
  } catch (error) {
50
    const statusCode = setStatusCode(error)
51
    res.status(statusCode).json({ status: 'error', error: utils.getErrorMessage(error) })
52
  }
53
}
54

55
export const retrieveChallengesWithCodeSnippet = async () => {
56
  const codeChallenges = await getCodeChallenges()
57
  return [...codeChallenges.keys()]
58
}
59

60
exports.serveChallengesWithCodeSnippet = () => async (req: Request, res: Response, next: NextFunction) => {
61
  const codingChallenges = await retrieveChallengesWithCodeSnippet()
62
  res.json({ challenges: codingChallenges })
63
}
64

65
export const getVerdict = (vulnLines: number[], neutralLines: number[], selectedLines: number[]) => {
66
  if (selectedLines === undefined) return false
67
  if (vulnLines.length > selectedLines.length) return false
68
  if (!vulnLines.every(e => selectedLines.includes(e))) return false
69
  const okLines = [...vulnLines, ...neutralLines]
70
  const notOkLines = selectedLines.filter(x => !okLines.includes(x))
71
  return notOkLines.length === 0
72
}
73

74
exports.checkVulnLines = () => async (req: Request<Record<string, unknown>, Record<string, unknown>, VerdictRequestBody>, res: Response, next: NextFunction) => {
75
  const key = req.body.key
76
  let snippetData
77
  try {
78
    snippetData = await retrieveCodeSnippet(key)
79
    if (snippetData == null) {
80
      res.status(404).json({ status: 'error', error: `No code challenge for challenge key: ${key}` })
81
      return
82
    }
83
  } catch (error) {
84
    const statusCode = setStatusCode(error)
85
    res.status(statusCode).json({ status: 'error', error: utils.getErrorMessage(error) })
86
    return
87
  }
88
  const vulnLines: number[] = snippetData.vulnLines
89
  const neutralLines: number[] = snippetData.neutralLines
90
  const selectedLines: number[] = req.body.selectedLines
91
  const verdict = getVerdict(vulnLines, neutralLines, selectedLines)
92
  let hint
93
  if (fs.existsSync('./data/static/codefixes/' + key + '.info.yml')) {
94
    const codingChallengeInfos = yaml.load(fs.readFileSync('./data/static/codefixes/' + key + '.info.yml', 'utf8'))
95
    if (codingChallengeInfos?.hints) {
96
      if (accuracy.getFindItAttempts(key) > codingChallengeInfos.hints.length) {
97
        if (vulnLines.length === 1) {
98
          hint = res.__('Line {{vulnLine}} is responsible for this vulnerability or security flaw. Select it and submit to proceed.', { vulnLine: vulnLines[0].toString() })
99
        } else {
100
          hint = res.__('Lines {{vulnLines}} are responsible for this vulnerability or security flaw. Select them and submit to proceed.', { vulnLines: vulnLines.toString() })
101
        }
102
      } else {
103
        const nextHint = codingChallengeInfos.hints[accuracy.getFindItAttempts(key) - 1] // -1 prevents after first attempt
104
        if (nextHint) hint = res.__(nextHint)
105
      }
106
    }
107
  }
108
  if (verdict) {
109
    await challengeUtils.solveFindIt(key)
110
    res.status(200).json({
111
      verdict: true
112
    })
113
  } else {
114
    accuracy.storeFindItVerdict(key, false)
115
    res.status(200).json({
116
      verdict: false,
117
      hint
118
    })
119
  }
120
}
121

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.