|
| 1 | +--- |
| 2 | +title: owasp juice shop > npm audit |
| 3 | +categories: owasp juice shop |
| 4 | +--- |
| 5 | +In this post, we will audit the OWASP juice shop app with npm. You should have already cloned the juice |
| 6 | +shop code and installed the modules with NPM. Some familiarity with jq for filtering json is assumed. |
| 7 | + |
| 8 | +# Audit |
| 9 | + |
| 10 | +Let's run the audit command. |
| 11 | +``` |
| 12 | +networkandcode@ubuntu20:~/juice-shop$ npm audit |
| 13 | +npm ERR! code EAUDITNOLOCK |
| 14 | +npm ERR! audit Neither npm-shrinkwrap.json nor package-lock.json found: Cannot audit a project without a lockfile |
| 15 | +npm ERR! audit Try creating one first with: npm i --package-lock-only |
| 16 | +
|
| 17 | +npm ERR! A complete log of this run can be found in: |
| 18 | +npm ERR! /home/networkandcode/.npm/_logs/2021-08-07T09_55_10_522Z-debug.log |
| 19 | +``` |
| 20 | + |
| 21 | +It throws an error as there is no package.lock in the directory. We can generate it using the reference |
| 22 | +command given above. |
| 23 | +``` |
| 24 | +$ npm i --package-lock-only |
| 25 | +npm notice created a lockfile as package-lock.json. You should commit this file. |
| 26 | +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^2.1.2 (node_modules/jest-haste-map/node_modules/fsevents): |
| 27 | +npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"}) |
| 28 | +
|
| 29 | +audited 2005 packages in 30.644s |
| 30 | +
|
| 31 | +117 packages are looking for funding |
| 32 | + run `npm fund` for details |
| 33 | +
|
| 34 | +found 25 vulnerabilities (3 low, 10 moderate, 9 high, 3 critical) |
| 35 | + run `npm audit fix` to fix them, or `npm audit` for details |
| 36 | +``` |
| 37 | + |
| 38 | +The output above shows this app has 25 vulnerabilities, we can get more details about those using the |
| 39 | +npm audit command. |
| 40 | +``` |
| 41 | +$ npm audit |
| 42 | +---TRUNCATED-- |
| 43 | + High Arbitrary File Creation/Overwrite via insufficient symlink |
| 44 | + protection due to directory cache poisoning |
| 45 | + |
| 46 | + Package tar |
| 47 | + |
| 48 | + Patched in >=3.2.3 <4.0.0 || >=4.4.15 <5.0.0 || >=5.0.7 <6.0.0 || |
| 49 | + >=6.1.2 |
| 50 | + |
| 51 | + Dependency of sqlite3 |
| 52 | + |
| 53 | + Path sqlite3 > node-gyp > tar |
| 54 | + |
| 55 | + More info https://npmjs.com/advisories/1771 |
| 56 | +---TRUNCATED--- |
| 57 | +``` |
| 58 | + |
| 59 | +The detail of one of the vulnerabilities is shown above. The exit code of the previous command can be |
| 60 | +checked, it would be 1 meaning it failed, as there are vulnerabilities. |
| 61 | +``` |
| 62 | +$ echo $? |
| 63 | +1 |
| 64 | +``` |
| 65 | +This is useful in CI pipelines, where the npm audit stage would be failed or passed according to the |
| 66 | +exit code. |
| 67 | + |
| 68 | +# JSON |
| 69 | +Its sometimes handy to store the results in a json file that filtering easier. |
| 70 | +``` |
| 71 | +$npm audit --json > /tmp/auditresult.json |
| 72 | +$ echo $? |
| 73 | +1 |
| 74 | +``` |
| 75 | + |
| 76 | +The exit code above is still 1 meaning it failed because of vulnerabilities. Let's try fitelring with |
| 77 | +jq. |
| 78 | + |
| 79 | +We can traverse through the following main keys |
| 80 | +``` |
| 81 | +$ cat /tmp/auditresult.json | jq 'keys' |
| 82 | +[ |
| 83 | + "actions", |
| 84 | + "advisories", |
| 85 | + "metadata", |
| 86 | + "muted", |
| 87 | + "runId" |
| 88 | +] |
| 89 | +
|
| 90 | +``` |
| 91 | + |
| 92 | +Let's see what are the keys in advisories. |
| 93 | +``` |
| 94 | +$ cat /tmp/auditresult.json | jq '.advisories' | jq 'keys' |
| 95 | +[ |
| 96 | + "1065", |
| 97 | + "1122", |
| 98 | + "135", |
| 99 | + "1523", |
| 100 | + "154", |
| 101 | + "1673", |
| 102 | + "1675", |
| 103 | + "1676", |
| 104 | + "17", |
| 105 | + "1769", |
| 106 | + "1770", |
| 107 | + "1771", |
| 108 | + "532", |
| 109 | + "55", |
| 110 | + "577", |
| 111 | + "658", |
| 112 | + "782", |
| 113 | + "88" |
| 114 | +] |
| 115 | +``` |
| 116 | + |
| 117 | +Let's pick the last one 88. |
| 118 | +``` |
| 119 | +$ cat /tmp/auditresult.json | jq '.advisories."88"' | jq keys |
| 120 | +[ |
| 121 | + "access", |
| 122 | + "created", |
| 123 | + "cves", |
| 124 | + "cwe", |
| 125 | + "deleted", |
| 126 | + "findings", |
| 127 | + "found_by", |
| 128 | + "id", |
| 129 | + "metadata", |
| 130 | + "module_name", |
| 131 | + "overview", |
| 132 | + "patched_versions", |
| 133 | + "recommendation", |
| 134 | + "references", |
| 135 | + "reported_by", |
| 136 | + "severity", |
| 137 | + "title", |
| 138 | + "updated", |
| 139 | + "url", |
| 140 | + "vulnerable_versions" |
| 141 | +] |
| 142 | +``` |
| 143 | + |
| 144 | +We shall check the associated cves of this vulnerability |
| 145 | +``` |
| 146 | +$ cat /tmp/auditresult.json | jq '.advisories."88".cves' |
| 147 | +[ |
| 148 | + "CVE-2016-1000223" |
| 149 | +] |
| 150 | +``` |
| 151 | + |
| 152 | +Or we can get it's complete details. |
| 153 | +``` |
| 154 | +$ cat /tmp/auditresult.json | jq '.advisories."88"' |
| 155 | +{ |
| 156 | + "findings": [ |
| 157 | + { |
| 158 | + "version": "0.2.6", |
| 159 | + "paths": [ |
| 160 | + "express-jwt>jsonwebtoken>jws", |
| 161 | + "jsonwebtoken>jws" |
| 162 | + ] |
| 163 | + } |
| 164 | + ], |
| 165 | + "id": 88, |
| 166 | + "created": "2016-03-22T16:50:45.816Z", |
| 167 | + "updated": "2019-06-24T15:15:36.951Z", |
| 168 | + "deleted": null, |
| 169 | + "title": "Forgeable Public/Private Tokens", |
| 170 | + "found_by": { |
| 171 | + "name": "Brian Brennan and Tim McLean" |
| 172 | + }, |
| 173 | + "reported_by": { |
| 174 | + "name": "Brian Brennan and Tim McLean" |
| 175 | + }, |
| 176 | + "module_name": "jws", |
| 177 | + "cves": [ |
| 178 | + "CVE-2016-1000223" |
| 179 | + ], |
| 180 | + "vulnerable_versions": "<3.0.0", |
| 181 | + "patched_versions": ">=3.0.0", |
| 182 | + "overview": "Affected versions of the `jws` package allow users to select what algorithm the server will use to verify a provided JWT. A malicious actor can use this behaviour to arbitrarily modify the contents of a JWT while still passing verification. For the common use case of the JWT as a bearer token, the end result is a complete authentication bypass with minimal effort.\n\n", |
| 183 | + "recommendation": "Update to version 3.0.0 or later.", |
| 184 | + "references": "- [Auth0 - Critical Vulnerabilities in JWT Libraries](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/)\n- [Commit #585d0e1](https://github.com/brianloveswords/node-jws/commit/585d0e1e97b6747c10cf5b7689ccc5618a89b299#diff-4ac32a78649ca5bdd8e0ba38b7006a1e)", |
| 185 | + "access": "public", |
| 186 | + "severity": "high", |
| 187 | + "cwe": "CWE-310", |
| 188 | + "metadata": { |
| 189 | + "module_type": "Multi.Library", |
| 190 | + "exploitability": 7, |
| 191 | + "affected_components": "" |
| 192 | + }, |
| 193 | + "url": "https://npmjs.com/advisories/88" |
| 194 | +} |
| 195 | +``` |
| 196 | + |
| 197 | +# Audit Level |
| 198 | + |
| 199 | +By default, the audit will catch and fail for any vulnerability, but usually we may interested only in |
| 200 | +high or critical vulnerabiliities, alteast for pipelines. In such case we can give the optional flag |
| 201 | +'--audit-level=high', so that all vulnerabilities with criticality high and above(critical) would be |
| 202 | +caught. However there wouldn't be any difference in the output, the exit code would only vary, and |
| 203 | +depends on high / critical vulnerabilities. |
| 204 | +``` |
| 205 | +$ npm audit --audit-level=high |
| 206 | +--TRUNCATED-- |
| 207 | +found 25 vulnerabilities (3 low, 10 moderate, 9 high, 3 critical) in 2005 scanned packages |
| 208 | +--TRUNCATED-- |
| 209 | +
|
| 210 | +$ echo $? |
| 211 | +1 |
| 212 | +``` |
| 213 | +The exit code is still 1, as although low and moderate vulnerabilities are ignored, there are still 9 |
| 214 | +high and 3 critical vulnerabilites. |
| 215 | + |
| 216 | +# Fix |
| 217 | + |
| 218 | +In certain cases, its possible to give an automatic fix using npm with `npm audit fix` command fix |
| 219 | +vulnerabilities. Its not possible always though as in our case, we can simulate this with the |
| 220 | +--dry-run flag to foresee what really happens. |
| 221 | +``` |
| 222 | +networkandcode@ubuntu20:~/juice-shop$ npm audit fix --dry-run |
| 223 | +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^2.1.2 (node_modules/jest-haste-map/node_modules/fsevents): |
| 224 | +npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"}) |
| 225 | +
|
| 226 | +up to date in 12.151s |
| 227 | +
|
| 228 | +117 packages are looking for funding |
| 229 | + run `npm fund` for details |
| 230 | +
|
| 231 | +fixed 0 of 25 vulnerabilities in 2005 scanned packages |
| 232 | + 6 vulnerabilities required manual review and could not be updated |
| 233 | + 3 package updates for 19 vulnerabilities involved breaking changes |
| 234 | + (use `npm audit fix --force` to install breaking changes; or refer to `npm audit` for steps to fix these manually) |
| 235 | +``` |
| 236 | + |
| 237 | +So it clearly says no vulnerabilities are fixed, and could also lead to breaking changes if the fix is |
| 238 | +forced. We have to then go through the recommendation for each vulnerability and try and fix it |
| 239 | +manually after reviewing that it doesnt break other packages. |
| 240 | + |
| 241 | +Thats the end of this post, we saw how to perform few commands in the npm audit family, and how the exit |
| 242 | + code can be checked to see if failed auditing or not. |
| 243 | + |
| 244 | +--end-of-post-- |
0 commit comments