diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000000..577bfad60f1 Binary files /dev/null and b/.DS_Store differ diff --git a/config/default.yml b/config/default.yml index 86038cb3dba..850eae173bf 100644 --- a/config/default.yml +++ b/config/default.yml @@ -412,6 +412,10 @@ memories: caption: 'My old workplace...' geoStalkingVisualSecurityQuestion: 10 geoStalkingVisualSecurityAnswer: 'ITsec' + - + image: 'bee.png' + caption: 'Juice Shop is now cooler😎' + user: bjoernGoogle ctf: showFlagsInNotifications: false showCountryDetailsInNotifications: none # Options: none name flag both diff --git a/data/static/challenges.yml b/data/static/challenges.yml index 06a30410b20..ebdc812bdad 100644 --- a/data/static/challenges.yml +++ b/data/static/challenges.yml @@ -93,6 +93,17 @@ hintUrl: '' mitigationUrl: ~ key: nftUnlockChallenge +- + name: 'Mint the Honey Pot' + category: 'Sensitive Data Exposure' + tags: + - Security Misconfiguration + description: 'Mint the Honey Pot NFT by gathering BEEs from the bee owner.' + difficulty: 3 + hint: 'Extract more BEEs than the owner has.' + hintUrl: '' + mitigationUrl: ~ + key: nftMintChallenge - name: 'Blocked RCE DoS' category: 'Insecure Deserialization' diff --git a/frontend/angular.json b/frontend/angular.json index a944ad68d2d..8557a102c69 100644 --- a/frontend/angular.json +++ b/frontend/angular.json @@ -30,7 +30,11 @@ "node_modules/flag-icons/sass/flag-icons.scss", "node_modules/font-mfizz/dist/font-mfizz.css", "node_modules/highlight.js/styles/github.css", - "node_modules/ngx-spinner/animations/timer.css" + "node_modules/ngx-spinner/animations/timer.css", + "node_modules/codemirror/lib/codemirror.css", + "node_modules/codemirror/theme/dracula.css", + "node_modules/codemirror/theme/material.css" + ], "allowedCommonJsDependencies": [ "jwt-decode", diff --git a/frontend/package.json b/frontend/package.json index eda32a4ccdb..38fab004cd7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,6 +12,7 @@ }, "private": true, "dependencies": { + "@agnostico/browser-solidity-compiler": "^0.1.1", "@angular-devkit/build-angular": "^15.0.4", "@angular-material-extensions/password-strength": "^6.0.0", "@angular/animations": "^15.0.4", @@ -28,6 +29,7 @@ "@angular/platform-browser": "^15.0.4", "@angular/platform-browser-dynamic": "^15.0.4", "@angular/router": "^15.0.4", + "@ctrl/ngx-codemirror": "^6.1.0", "@fortawesome/fontawesome-svg-core": "~1.2.30", "@fortawesome/free-brands-svg-icons": "^5.14.0", "@fortawesome/free-regular-svg-icons": "^5.14.0", @@ -35,9 +37,14 @@ "@nguniversal/express-engine": "10.0.1", "@ngx-translate/core": "^13.0.0", "@ngx-translate/http-loader": "^6.0.0", + "@remix-project/remix-solidity": "^0.5.15", + "@wagmi/core": "^0.5.8", "anuglar2-qrcode": "~2.0.3", "canvas-confetti": "^1.4.0", + "codemirror": "^5.65.13", + "codemirror-solidity": "^0.2.5", "core-js": "^3.22.5", + "ethers": "^5.7.2", "file-saver": "^2.0.2", "flag-icons": "^6.6.4", "font-mfizz": "^2.4.1", @@ -56,7 +63,9 @@ "sass": "^1.32.2", "snarkdown": "^1.2.2", "socket.io-client": "^3.1.0", + "solc": "^0.8.20", "typescript": "~4.8.4", + "url": "^0.11.1", "zone.js": "~0.11.4" }, "devDependencies": { @@ -72,7 +81,9 @@ "@typescript-eslint/eslint-plugin": "^4.11.0", "@typescript-eslint/eslint-plugin-tslint": "^4.11.0", "@typescript-eslint/parser": "^4.11.0", + "assert": "^2.0.0", "codelyzer": "^6.0.0", + "crypto-browserify": "^3.12.0", "eslint": "^7.16.0", "eslint-config-prettier": "7.1.0", "eslint-config-standard-with-typescript": "^21.0.1", @@ -81,6 +92,7 @@ "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.2.1", "eslint-plugin-standard": "^4.1.0", + "https-browserify": "^1.0.0", "jasmine": "^3.9.0", "jasmine-core": "~3.9.0", "jasmine-spec-reporter": "~7.0.0", @@ -89,6 +101,10 @@ "karma-coverage": "^2.0.3", "karma-jasmine": "~4.0.1", "karma-jasmine-html-reporter": "^1.7.0", + "os-browserify": "^0.3.0", + "path-browserify": "^1.0.1", + "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", "stylelint": "^13.8.0", "stylelint-config-sass-guidelines": "^7.1.0", "stylelint-scss": "^3.18.0", diff --git a/frontend/src/app/Services/keys.service.ts b/frontend/src/app/Services/keys.service.ts index 3210b7f1159..27ef85b9ca2 100644 --- a/frontend/src/app/Services/keys.service.ts +++ b/frontend/src/app/Services/keys.service.ts @@ -20,6 +20,22 @@ export class KeysService { }) ) } + nftMinted () { + return this.http.get(this.host + '/nftMinted').pipe( + map((response: any) => response), + catchError((err) => { + throw err + }) + ) + } + checkNftMinted () { + return this.http.get(this.host + '/checkNftMinted').pipe( + map((response: any) => response), + catchError((err) => { + throw err + }) + ) + } submitKey (privateKey: string) { const endpoint = this.host + '/submitKey' diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 969a83136eb..40d412aa07f 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -139,6 +139,12 @@ import { CodeSnippetComponent } from './code-snippet/code-snippet.component' import { CodeAreaComponent } from './code-area/code-area.component' import { NgxTextDiffModule } from 'ngx-text-diff' import { CodeFixesComponent } from './code-fixes/code-fixes.component' +import { WalletconnectComponent } from './walletconnect/walletconnect.component' +import { CodemirrorModule } from "@ctrl/ngx-codemirror" +import "codemirror/mode/javascript/javascript"; +import "codemirror/mode/markdown/markdown"; +import "codemirror-solidity/solidity"; + export function HttpLoaderFactory (http: HttpClient) { return new TranslateHttpLoader(http, './assets/i18n/', '.json') @@ -202,9 +208,11 @@ export function HttpLoaderFactory (http: HttpClient) { FeedbackDetailsComponent, CodeSnippetComponent, CodeAreaComponent, - CodeFixesComponent + CodeFixesComponent, + WalletconnectComponent ], imports: [ + CodemirrorModule, BrowserModule, Routing, TranslateModule.forRoot( diff --git a/frontend/src/app/app.routing.ts b/frontend/src/app/app.routing.ts index 3fef074df71..1d8e32ffff3 100644 --- a/frontend/src/app/app.routing.ts +++ b/frontend/src/app/app.routing.ts @@ -42,6 +42,7 @@ import { PhotoWallComponent } from './photo-wall/photo-wall.component' import { DeluxeUserComponent } from './deluxe-user/deluxe-user.component' import { AccountingGuard, AdminGuard, LoginGuard } from './app.guard' import { NFTUnlockComponent } from './nft-unlock/nft-unlock.component' +import { WalletconnectComponent } from "./walletconnect/walletconnect.component"; // vuln-code-snippet start adminSectionChallenge scoreBoardChallenge const routes: Routes = [ @@ -55,6 +56,10 @@ const routes: Routes = [ component: AccountingComponent, canActivate: [AccountingGuard] }, + { + path: 'wallet-poc', + component: WalletconnectComponent + }, { path: 'about', component: AboutComponent diff --git a/frontend/src/app/nft-unlock/nft-unlock.component.scss b/frontend/src/app/nft-unlock/nft-unlock.component.scss index ef9edb74c95..de23f03e7f0 100644 --- a/frontend/src/app/nft-unlock/nft-unlock.component.scss +++ b/frontend/src/app/nft-unlock/nft-unlock.component.scss @@ -59,6 +59,9 @@ mat-card:nth-child(1) { .box-text { margin-top: 8px; } +.form-group{ + margin-top: 16px; +} .form-group { display: flex; diff --git a/frontend/src/app/photo-wall/photo-wall.component.html b/frontend/src/app/photo-wall/photo-wall.component.html index d6ec735a211..2a1576ba28d 100644 --- a/frontend/src/app/photo-wall/photo-wall.component.html +++ b/frontend/src/app/photo-wall/photo-wall.component.html @@ -3,67 +3,101 @@ ~ SPDX-License-Identifier: MIT --> - -

{{"LABEL_PHOTO_WALL" | translate}}

+ +

{{ "LABEL_PHOTO_WALL" | translate }}

- - {{ image.caption }} -
-
{{ image.caption }}
- - - -
-
+ + {{ image.caption }} +
+
{{ image.caption }}
+ + + + + + + + + + +
+
-  No results found +  No results found - - NO_SEARCH_RESULT - + NO_SEARCH_RESULT - - EMPTY_MEMORY_LIST - + EMPTY_MEMORY_LIST
-
+

LABEL_SHARE_A_MEMORY

- - +
-
- +
+
LABEL_CAPTION - - {{'MANDATORY_CAPTION' | translate}} + + {{ + "MANDATORY_CAPTION" | translate + }} -
diff --git a/frontend/src/app/walletconnect/walletconnect.component.html b/frontend/src/app/walletconnect/walletconnect.component.html new file mode 100644 index 00000000000..5121784d4fb --- /dev/null +++ b/frontend/src/app/walletconnect/walletconnect.component.html @@ -0,0 +1,154 @@ +
+
+ +
+
+ +
+

BEE Haven

+
+ +
+

+ Welcome to Bee Haven, the hive of BEE tokens! Immerse yourself in the buzz + as our generous Bee Owner shares the joy of bees with you. Embrace + their bountiful generosity, but remember, taking too many bees at once may + disrupt their harmonious abode. +

+
+ Faucet Balance: {{ juiceBalance }} | Your BEE Balance: + {{ myJuiceBalance }} +
+
+ + Enter no. of BEEs: + + + +
+
+
+ +
+
+
+ +
+
+

The Enchanted Honey Pot

+

+ Deep within the magical realm, the Enchanted Honey Pot awaits its + rightful owner. To unlock its wonders, you must trade the essence of + the buzzing kingdom - BEE tokens. Gather these mystical tokens from + the generous Bee Haven, but beware, for the Bee Owner's supply may not + be all that meets the eye. +

+
+ Contract Address: {{ deployedContractAddress }} +
+ + + + + +
+
+
+
+ + diff --git a/frontend/src/app/walletconnect/walletconnect.component.scss b/frontend/src/app/walletconnect/walletconnect.component.scss new file mode 100644 index 00000000000..07ca0c902a7 --- /dev/null +++ b/frontend/src/app/walletconnect/walletconnect.component.scss @@ -0,0 +1,219 @@ +// @import '~codemirror/lib/codemirror.css'; +// @import '~codemirror/theme/dracula'; + +.buy-nft { + width: 55%; + margin: auto; + margin-bottom: 30px; +} +.header { + display: flex; + flex-direction: row; + margin: 16px; + justify-content: center; + h2 { + margin: 2px; + } + div { + display: flex; + flex-direction: column; + align-items: center; + } + button { + color: white; + font-size: 18px; + padding: 12px 8px; + border-radius: 8px; + width: 250px; + cursor: pointer; + } +} +.faucet { + padding: 40px 80px; + &_image{ + display: flex; + align-items: center; + justify-content: center; + padding: 16px; + img{ + width: 250px; + } + } + h1 { + text-align: center; + font-weight: bold; + margin: 0px; + } + .faucet_balance { + font-size: 18px; + margin: 20px 0px; + padding: 8px; + + border: 1px solid #659F44; + border-radius: 10px; + width: 100%; + color: #659F44; + text-align: center; + } + .withdraw_inputcontainer { + width: 100%; + align-items: center; + button { + justify-self: end; + border-radius: 10px; + width: fit-content; + height: fit-content; + padding: 16px 24px; + border: none; + font-weight: 500; + color: white; + margin-top: -20px; + width: 300px; + } + } +} +.section-1 { + &_body { + display: flex; + padding: 40px 80px; + gap: 16px; + + &_left { + display: flex; + gap: 16px; + width: 75%; + + &_editor_title { + font-size: 20px; + font-weight: 500; + width: 100%; + margin-bottom: 16px; + padding: 0px 8px; + } + } + &_right { + width: 25%; + + margin: 32px 0; + display: flex; + flex-direction: column; + align-items: center; + // justify-content: center; + position: relative; + h1 { + padding: 0; + margin: 2px; + } + h5 { + text-align: center; + } + h3 { + font-weight: 600; + } + .deployedaddresstext { + margin: 10px 0px; + font-weight: 600; + word-wrap: break-word; + white-space: pre-wrap; + color: lightgreen; + } + button { + position: absolute; + bottom: 20px; + justify-self: end; + border-radius: 10px; + width: fit-content; + height: fit-content; + padding: 16px 24px; + border: none; + background-color: #463471; + cursor: pointer; + font-weight: 500; + color: white; + } + } + } +} +.section-2 { + &_body { + display: flex; + padding: 40px 80px; + gap: 16px; + &_left { + width: 35%; + img { + width: 100%; + } + } + &_right { + width: 65%; + } + .withdraw_button { + justify-self: end; + border-radius: 10px; + margin-top: 10px; + width: fit-content; + height: fit-content; + padding: 16px 24px; + border: none; + font-weight: 500; + color: white; + } + .mint_button { + justify-self: end; + border-radius: 10px; + width: fit-content; + height: fit-content; + padding: 16px 48px; + border: none; + margin-top: 32px; + font-weight: 500; + color: white; + } + .withdraw_inputcontainer { + display: flex; + align-items: center; + gap: 32px; + } + .withdraw_input { + background-color: #524a63; + padding: 4px; + border: none; + width: 150px; + margin-left: 4px; + color: white; + outline: none; + :focus { + } + } + .myjuicebalance_text { + font-size: 18px; + margin: 40px 0px; + padding: 6px; + + border: 1px solid white; + border-radius: 10px; + width: 100%; + text-align: center; + } + .juicebalance_text { + font-size: 18px; + margin-top: 20px; + padding: 6px 0px; + } + } +} +.ngx-codemirror { + width: 50%; + height: 400px; /* Adjust the height as needed */ +} + +/* Adjust the font size and other styles of the editor content */ +.CodeMirror { + font-size: 14px; + border-radius: 16px !important; + /* Add other desired styles here */ +} +.CodeMirror .cm-s-dracula .CodeMirror-wrap { + border-radius: 16px !important; +} diff --git a/frontend/src/app/walletconnect/walletconnect.component.spec.ts b/frontend/src/app/walletconnect/walletconnect.component.spec.ts new file mode 100644 index 00000000000..48ab406b21b --- /dev/null +++ b/frontend/src/app/walletconnect/walletconnect.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { WalletconnectComponent } from './walletconnect.component'; + +describe('WalletconnectComponent', () => { + let component: WalletconnectComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ WalletconnectComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(WalletconnectComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/walletconnect/walletconnect.component.ts b/frontend/src/app/walletconnect/walletconnect.component.ts new file mode 100644 index 00000000000..aa2bce35055 --- /dev/null +++ b/frontend/src/app/walletconnect/walletconnect.component.ts @@ -0,0 +1,1496 @@ +import { Component, OnInit } from "@angular/core"; +import { KeysService } from "../Services/keys.service"; + +import { getDefaultProvider, ethers, BigNumber } from "ethers"; +import { + createClient, + connect, + disconnect, + getAccount, + signMessage, + InjectedConnector, +} from "@wagmi/core"; +import { + solidityCompiler, + getCompilerVersions, +} from "@agnostico/browser-solidity-compiler"; + +const client = createClient({ + autoConnect: true, + provider: getDefaultProvider(), +}); +const vulnerableAddress = "0x7b95E1604189EFE1566278d2bD984e27614273e5"; +const nftAddress = "0x5FDDEbB5bE5d2C2dfB2c758ED86D3E6A53366107"; +const vulnerableABI = [ + { + inputs: [], + name: "receiveMoney", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "address payable", + name: "_to", + type: "address", + }, + { + internalType: "uint256", + name: "_amount", + type: "uint256", + }, + ], + name: "transfer", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + stateMutability: "payable", + type: "constructor", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, +]; +const nftABI = [ + { + inputs: [], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "approved", + type: "address", + }, + { + indexed: true, + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "operator", + type: "address", + }, + { + indexed: false, + internalType: "bool", + name: "approved", + type: "bool", + }, + ], + name: "ApprovalForAll", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: true, + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "approve", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "getApproved", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + name: "hasMinted", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "operator", + type: "address", + }, + ], + name: "isApprovedForAll", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "maxMintPerWallet", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "mintNFT", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "mintPrice", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "ownerOf", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "operator", + type: "address", + }, + { + internalType: "bool", + name: "approved", + type: "bool", + }, + ], + name: "setApprovalForAll", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes4", + name: "interfaceId", + type: "bytes4", + }, + ], + name: "supportsInterface", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "token", + outputs: [ + { + internalType: "contract IERC20", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "tokenURI", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "transferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +]; +const contractAbi = [ + { + inputs: [], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "allowance", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "approve", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [ + { + internalType: "uint8", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "subtractedValue", + type: "uint256", + }, + ], + name: "decreaseAllowance", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "addedValue", + type: "uint256", + }, + ], + name: "increaseAllowance", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "recipient", + type: "address", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "mintTokens", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "recipient", + type: "address", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "transfer", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + { + internalType: "address", + name: "recipient", + type: "address", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "transferFrom", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, +]; + +const BeeTokenAddress = "0x36435796Ca9be2bf150CE0dECc2D8Fab5C4d6E13"; + +const BeeTokenABI = [ + { + inputs: [], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "allowance", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "approve", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [ + { + internalType: "uint8", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "subtractedValue", + type: "uint256", + }, + ], + name: "decreaseAllowance", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "addedValue", + type: "uint256", + }, + ], + name: "increaseAllowance", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "recipient", + type: "address", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "mintTokens", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "recipient", + type: "address", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "transfer", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + { + internalType: "address", + name: "recipient", + type: "address", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "transferFrom", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, +]; +const BeeFaucetABI = [ + { + inputs: [], + name: "balance", + outputs: [ + { + internalType: "uint8", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getBalance", + outputs: [ + { + internalType: "uint8", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "token", + outputs: [ + { + internalType: "contract Token", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint8", + name: "amount", + type: "uint8", + }, + ], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +]; +const BeeFaucetAddress = "0x860e3616aD0E0dEDc23352891f3E10C4131EA5BC"; +const overflowAddress = "0x530252Cd4983207b481009A4aA75E158564C1125"; + +@Component({ + selector: "app-walletconnect", + templateUrl: "./walletconnect.component.html", + styleUrls: ["./walletconnect.component.scss"], +}) +export class WalletconnectComponent { + constructor(private readonly keysService: KeysService) {} + + userData: object; + session = ""; + deployedContractAddress = ""; + juiceBalance = 0; + myJuiceBalance = 0; + withdrawAmount: number = null; + successResponse = false; + mintButtonDisabled = true; + challengeSolved = false; + nftMintText = "Mint the Pot - 1000 BEE"; + vulnerableContract: string = `pragma solidity ^0.7.0; + + +interface Token { + function transfer(address recipient, uint256 amount) external returns (bool); + function balanceOf(address account) external view returns (uint256); +} + +contract VulnerableWallet { + Token public token = Token(0x19251330389F2485f4a0E16657Cd364A1F537F7E); + address public owner; + + constructor() { + owner = msg.sender; + } + + function transferFunds(address payable recipient, uint256 amount) external { + require(tx.origin == owner, "Unauthorized access"); + recipient.transfer(amount); + token.transfer(recipient, uint256(amount)); + } + + function TransferToFunds(uint8 amount) public { + require(msg.sender == owner, "Unauthorized access"); + token.transfer(msg.sender, uint256(amount)); + } + + function getBalance() public view returns (uint8) { + return balance; + } +} +`; + + code: string = `contract AttackerContract { + address public vulnerableContractAddress = address(0x7e4fcc69FfaF3177B87Ce844fD764dEB6860A364); + + + function attack() external payable { + (bool success, ) = vulnerableContractAddress.call( + abi.encodeWithSignature("transferFunds(address,uint256)", msg.sender, msg.value) + ); + + require(success, "Attack failed"); + } +} +`; + editorOptions = { + mode: "text/x-solidity", + theme: "dracula", + lineNumbers: true, + lineWrapping: true, + // ... other CodeMirror options + }; + editorDisabledOptions = { + mode: "text/x-solidity", + theme: "material", + lineNumbers: true, + lineWrapping: true, + readOnly: "nocursor", + // ... other CodeMirror options + }; + ngOnInit(): void { + this.fetchJuiceBalance(); + this.fetchMyJuiceBalance(); + this.checkNftMinted(); + } + + checkNftMinted() { + this.keysService.checkNftMinted().subscribe( + (response) => { + console.log(response.status,"res"); + this.mintButtonDisabled = response.status; + this.challengeSolved = response.status; + if(response.status){ + this.nftMintText = "Minted Successfully"; + } + }, + (error) => { + console.error(error); + this.successResponse = false; + } + ); + } + async fetchMyJuiceBalance() { + try { + const provider = new ethers.providers.Web3Provider(window.ethereum); + const signer = provider.getSigner(); + + // Replace the contract address and ABI with your Juice Token contract details + + const contract = new ethers.Contract( + BeeTokenAddress, + BeeTokenABI, + signer + ); + const userAddress = await signer.getAddress(); + const balanceBigNumber: BigNumber = await contract.balanceOf(userAddress); + console.log(balanceBigNumber); + this.myJuiceBalance = balanceBigNumber + .div(ethers.constants.WeiPerEther) + .toNumber(); + if (this.myJuiceBalance >= 1000 && !this.challengeSolved) { + this.mintButtonDisabled = false; + } + if (this.myJuiceBalance <= 1000 && !this.challengeSolved) { + this.mintButtonDisabled = true; + } + } catch (error) { + console.error("Error fetching Juice balance:", error); + } + } + async fetchJuiceBalance() { + try { + const provider = new ethers.providers.Web3Provider(window.ethereum); + const signer = provider.getSigner(); + + const contract = new ethers.Contract( + BeeFaucetAddress, + BeeFaucetABI, + signer + ); + const balance = await contract.balance(); + console.log(balance); + this.juiceBalance = balance; + } catch (error) { + console.error("Error fetching Juice balance:", error); + } + } + async compileAndDeployCode(code: string) { + try { + const provider = new ethers.providers.Web3Provider(window.ethereum); + const signer = provider.getSigner(); + console.log(provider); + console.log(signer); + const output: any = await solidityCompiler({ + version: `https://binaries.soliditylang.org/bin/soljson-v0.6.0+commit.26b70077.js`, + contractBody: code, + }); + + console.log("output", output); + const contractBytecode = + output?.contracts["Compiled_Contracts"]["AttackerContract"].evm.bytecode + .object; + const contractAbi = + output?.contracts["Compiled_Contracts"]["AttackerContract"].abi; + + const factory = new ethers.ContractFactory( + contractAbi, + contractBytecode, + signer + ); + const contract = await factory.deploy(); + + await contract.deployed(); + + console.log("Contract deployed:", contract.address); + this.deployedContractAddress = contract.address; + console.log(this.deployedContractAddress); + } catch (error) { + console.error("Error compiling/deploying contract:", error); + } + } + async handleAuth() { + const { isConnected } = getAccount(); + + if (isConnected) await disconnect(); //disconnects the web3 provider if it's already active + + const provider = await connect({ connector: new InjectedConnector() }); // enabling the web3 provider metamask + + this.userData = { + address: provider.account, + chain: provider.chain.id, + network: "evm", + }; + + this.session = "enable"; + this.fetchJuiceBalance(); + this.fetchMyJuiceBalance(); + } + async withdrawJuiceTokens(amount = this.withdrawAmount) { + try { + if (amount > 1000) { + console.log("Withdrawal amount exceeds the limit"); + return; + } + + const provider = new ethers.providers.Web3Provider(window.ethereum); + const signer = provider.getSigner(); + + const contract = new ethers.Contract( + BeeFaucetAddress, + BeeFaucetABI, + signer + ); + const tx = await contract.withdraw(amount); + await tx.wait(); + + console.log("Juice tokens withdrawn successfully"); + this.fetchJuiceBalance(); + this.fetchMyJuiceBalance(); + } catch (error) { + console.error("Error withdrawing Juice tokens:", error); + } + } + + async transferEthToContract() { + // Connect to the Ethereum network using the default provider + const provider = ethers.getDefaultProvider(); + + try { + // Create a new wallet using the private key + const provider = new ethers.providers.Web3Provider(window.ethereum); + const signer = provider.getSigner(); + // Create a new instance of the smart contract + const contract = new ethers.Contract( + vulnerableAddress, + vulnerableABI, + signer + ); + + // Set the amount to transfer (0.1 ETH) + const amount = ethers.utils.parseEther("0.1"); + + // Call the receiveMoney function on the smart contract + const transaction = await contract.receiveMoney({ value: amount }); + + // Wait for the transaction to be mined + await transaction.wait(); + + console.log("ETH transferred successfully to the smart contract wallet."); + } catch (error) { + console.error( + "Failed to transfer ETH to the smart contract wallet:", + error + ); + } + } + + async mintNFT() { + this.nftMintText = "Awaiting Approval"; + try { + // Create a provider and signer using the user's Ethereum account + const provider = new ethers.providers.Web3Provider(window.ethereum); + const signer = provider.getSigner(); + const amountToApprove = ethers.utils.parseUnits("1000", "18"); + const BeeTokenContract = new ethers.Contract( + BeeTokenAddress, + BeeTokenABI, + signer + ); + const approvalTx = await BeeTokenContract.approve( + nftAddress, + amountToApprove + ); + + await approvalTx.wait(); + this.nftMintText = "Confirm Mint..."; + + const contract = new ethers.Contract(nftAddress, nftABI, signer); + this.nftMintText = "Mint in Process..."; + + const transaction = await contract.mintNFT(); + console.log(transaction); + + // Wait for the transaction to be mined + const mintConfirmation = await transaction.wait(); + console.log(mintConfirmation); + if (mintConfirmation) { + this.nftMintText = "Successfully Minted"; + this.mintButtonDisabled = false; + + this.keysService.nftMinted().subscribe( + (response) => { + this.successResponse = response.status; + }, + (error) => { + console.error(error); + this.successResponse = false; + } + ); + } + + console.log("NFT minted successfully!"); + } catch (error) { + console.error("Error minting NFT:", error); + } + } + + async signOut() { + await disconnect(); + this.session = ""; + } +} diff --git a/frontend/src/assets/public/images/beeowner.png b/frontend/src/assets/public/images/beeowner.png new file mode 100644 index 00000000000..46f9af648be Binary files /dev/null and b/frontend/src/assets/public/images/beeowner.png differ diff --git a/frontend/src/assets/public/images/honeypot.png b/frontend/src/assets/public/images/honeypot.png new file mode 100644 index 00000000000..7893fca8b87 Binary files /dev/null and b/frontend/src/assets/public/images/honeypot.png differ diff --git a/frontend/src/assets/public/images/uploads/bee.png b/frontend/src/assets/public/images/uploads/bee.png new file mode 100644 index 00000000000..e9d8985b8fa Binary files /dev/null and b/frontend/src/assets/public/images/uploads/bee.png differ diff --git a/frontend/src/styles.scss b/frontend/src/styles.scss index 2b5fb47c82b..8cdb5fde9d2 100644 --- a/frontend/src/styles.scss +++ b/frontend/src/styles.scss @@ -211,3 +211,7 @@ $bg-hacking-instructor: rgba(0, 0, 0, 0.3); font-family: monospace; padding: 0 4px; } + +.CodeMirror{ + border-radius: 16px; +} \ No newline at end of file diff --git a/frontend/src/tsconfig.app.json b/frontend/src/tsconfig.app.json index 03d68c7500c..3aa01c4a1be 100644 --- a/frontend/src/tsconfig.app.json +++ b/frontend/src/tsconfig.app.json @@ -3,13 +3,18 @@ "compilerOptions": { "outDir": "../out-tsc/app", "module": "es2020", + "allowSyntheticDefaultImports": true, + "paths": { + "crypto": ["./node_modules/crypto-browserify"], + "stream": ["./node_modules/stream-browserify"], + "assert": ["./node_modules/assert"], + "http": ["./node_modules/stream-http"], + "https": ["./node_modules/https-browserify"], + "os": ["./node_modules/os-browserify"], + "path":["./node_modules/path-browserify"] + }, "types": [] }, - "files": [ - "main.ts", - "polyfills.ts" - ], - "include": [ - "**/*.d.ts" - ] + "files": ["main.ts", "polyfills.ts"], + "include": ["**/*.d.ts"] } diff --git a/routes/nftMint.ts b/routes/nftMint.ts new file mode 100644 index 00000000000..5b7f9183558 --- /dev/null +++ b/routes/nftMint.ts @@ -0,0 +1,27 @@ +import { Request, Response } from 'express' +import challengeUtils = require('../lib/challengeUtils') +import * as utils from '../lib/utils' + +const challenges = require('../data/datacache').challenges + +module.exports.nftMint = function nftMint () { + return (req: Request, res: Response) => { + try { + challengeUtils.solveIf(challenges.nftMintChallenge, () => { + return true + }) + res.status(200).json({ success: true, message: 'Challenge successfully solved', status: challenges.nftMintChallenge }) + } catch (error) { + res.status(500).json(utils.get(error)) + } + } +} +module.exports.nftMintCheck = function nftMintCheck () { + return (req: Request, res: Response) => { + try { + res.status(200).json({ status: challenges.nftMintChallenge.solved }) + } catch (error) { + res.status(500).json(utils.get(error)) + } + } +} diff --git a/rsn/cache.json b/rsn/cache.json index 4c431314dad..bd740958c2d 100644 --- a/rsn/cache.json +++ b/rsn/cache.json @@ -19,7 +19,15 @@ }, "adminSectionChallenge_1_correct.ts": { "added": [ - 7 + 7, + 13, + 14, + 15, + 16, + 162, + 163, + 164, + 165 ], "removed": [ 7, @@ -28,15 +36,42 @@ ] }, "adminSectionChallenge_2.ts": { - "added": [], + "added": [ + 13, + 14, + 15, + 16, + 162, + 163, + 164, + 165 + ], "removed": [] }, "adminSectionChallenge_3.ts": { - "added": [], + "added": [ + 13, + 14, + 15, + 16, + 162, + 163, + 164, + 165 + ], "removed": [] }, "adminSectionChallenge_4.ts": { - "added": [], + "added": [ + 13, + 14, + 15, + 16, + 162, + 163, + 164, + 165 + ], "removed": [] }, "changeProductChallenge_1.ts": { @@ -416,16 +451,46 @@ "removed": [] }, "scoreBoardChallenge_1_correct.ts": { - "added": [], - "removed": [] + "added": [ + 13, + 14, + 15, + 16, + 162, + 163, + 164, + 165 + ], + "removed": [ + 115 + ] }, "scoreBoardChallenge_2.ts": { - "added": [], - "removed": [] + "added": [ + 13, + 14, + 15, + 16, + 162, + 163, + 164, + 165 + ], + "removed": [ + 115 + ] }, "scoreBoardChallenge_3.ts": { "added": [ - 117 + 13, + 14, + 15, + 16, + 121, + 162, + 163, + 164, + 165 ], "removed": [] }, diff --git a/server.ts b/server.ts index 0374ad807e4..fdf583a40a6 100644 --- a/server.ts +++ b/server.ts @@ -87,6 +87,7 @@ const b2bOrder = require('./routes/b2bOrder') const showProductReviews = require('./routes/showProductReviews') const createProductReviews = require('./routes/createProductReviews') const checkKeys = require('./routes/checkKeys') +const nftMint = require('./routes/nftMint') const updateProductReviews = require('./routes/updateProductReviews') const likeProductReviews = require('./routes/likeProductReviews') const security = require('./lib/insecurity') @@ -588,6 +589,8 @@ restoreOverwrittenFilesWithOriginals().then(() => { /* Web3 API endpoints */ app.post('/rest/web3/submitKey', checkKeys.checkKeys()) app.get('/rest/web3/nftUnlocked', checkKeys.nftUnlocked()) + app.get('/rest/web3/nftMinted', nftMint.nftMint()) + app.get('/rest/web3/checkNftMinted', nftMint.nftMintCheck()) /* B2B Order API */ app.post('/b2b/v2/orders', b2bOrder())