Merge branch 'release/v8.0.0'
This commit is contained in:
commit
985148ede3
4
.gitignore
vendored
4
.gitignore
vendored
@ -42,3 +42,7 @@ webgoat-lessons/**/target
|
|||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
webgoat-server/mongo-data/*
|
webgoat-server/mongo-data/*
|
||||||
webgoat-lessons/vulnerable-components/dependency-reduced-pom.xml
|
webgoat-lessons/vulnerable-components/dependency-reduced-pom.xml
|
||||||
|
**/.sts4-cache/*
|
||||||
|
**/.vscode/*
|
||||||
|
|
||||||
|
/.sonatype
|
245
CHANGELOG.md
245
CHANGELOG.md
@ -1,245 +0,0 @@
|
|||||||
# Change Log
|
|
||||||
|
|
||||||
## [7.1](https://github.com/WebGoat/WebGoat/tree/7.1) (2016-11-18)
|
|
||||||
[Full Changelog](https://github.com/WebGoat/WebGoat/compare/7.0.1...7.1)
|
|
||||||
|
|
||||||
**Implemented enhancements:**
|
|
||||||
|
|
||||||
- i8n highlighting [\#96](https://github.com/WebGoat/WebGoat/issues/96)
|
|
||||||
- Improve uniqueness of menu item Id's [\#45](https://github.com/WebGoat/WebGoat/issues/45)
|
|
||||||
|
|
||||||
**Fixed bugs:**
|
|
||||||
|
|
||||||
- Stored XSS Lesson does not render message and attack does not fire [\#141](https://github.com/WebGoat/WebGoat/issues/141)
|
|
||||||
- Source code is not available for this lesson. [\#137](https://github.com/WebGoat/WebGoat/issues/137)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Fix lesson client side filtering [\#272](https://github.com/WebGoat/WebGoat/issues/272)
|
|
||||||
- Reset lesson does not work anymore [\#271](https://github.com/WebGoat/WebGoat/issues/271)
|
|
||||||
- Lesson plans not loading with manual build and easy-run jar \(standalone jar\) not running at all [\#268](https://github.com/WebGoat/WebGoat/issues/268)
|
|
||||||
- Unable to download webgoat jar file [\#261](https://github.com/WebGoat/WebGoat/issues/261)
|
|
||||||
- Developer edition build isn't working in its entirety [\#260](https://github.com/WebGoat/WebGoat/issues/260)
|
|
||||||
- Amazon S3 downloadable JAR is missing [\#259](https://github.com/WebGoat/WebGoat/issues/259)
|
|
||||||
- Code does not compile on dev branch [\#258](https://github.com/WebGoat/WebGoat/issues/258)
|
|
||||||
- Executable jar crashes if empty .extract folder exist [\#251](https://github.com/WebGoat/WebGoat/issues/251)
|
|
||||||
- Java Error Message in Lesson "How to Bypass a Path Based Access Control Scheme" [\#240](https://github.com/WebGoat/WebGoat/issues/240)
|
|
||||||
- developer bootstrap says git is missing when it is installed [\#236](https://github.com/WebGoat/WebGoat/issues/236)
|
|
||||||
- Application Won't Start [\#234](https://github.com/WebGoat/WebGoat/issues/234)
|
|
||||||
- Restart lesson button isn't working [\#226](https://github.com/WebGoat/WebGoat/issues/226)
|
|
||||||
- Navigation to start page is broken after login [\#218](https://github.com/WebGoat/WebGoat/issues/218)
|
|
||||||
- Links in menu missing pointer cursor [\#216](https://github.com/WebGoat/WebGoat/issues/216)
|
|
||||||
- Restart lesson button not working [\#213](https://github.com/WebGoat/WebGoat/issues/213)
|
|
||||||
- WebGoat stops at DEBUG - Exit: getEngine\(\) [\#211](https://github.com/WebGoat/WebGoat/issues/211)
|
|
||||||
- Labs: Remnant files and solved stages [\#208](https://github.com/WebGoat/WebGoat/issues/208)
|
|
||||||
- Labs: Navigating to Instructor java examples [\#206](https://github.com/WebGoat/WebGoat/issues/206)
|
|
||||||
- WebGoat 7.0 and ZAP 2.4.3 will not proxy [\#204](https://github.com/WebGoat/WebGoat/issues/204)
|
|
||||||
- Failing Build [\#201](https://github.com/WebGoat/WebGoat/issues/201)
|
|
||||||
- Missing mvn package of webgoat-container in README.MD [\#200](https://github.com/WebGoat/WebGoat/issues/200)
|
|
||||||
- Seems translation to Russian for "Congratulations. You have successfully completed this lesson." phrase is broken. [\#199](https://github.com/WebGoat/WebGoat/issues/199)
|
|
||||||
- HtmlEncoder uses static methods but must be instantiated [\#195](https://github.com/WebGoat/WebGoat/issues/195)
|
|
||||||
- webgoat-container should unpack all the lessons [\#192](https://github.com/WebGoat/WebGoat/issues/192)
|
|
||||||
- Access Control Flaws, LAB stage 3: Remove the FindProfile screen [\#186](https://github.com/WebGoat/WebGoat/issues/186)
|
|
||||||
- Injection Flaws | XPath Injection date file path issue [\#184](https://github.com/WebGoat/WebGoat/issues/184)
|
|
||||||
- hints don't appear to work on labs [\#183](https://github.com/WebGoat/WebGoat/issues/183)
|
|
||||||
- Session Management Flaws - Spoof an Authentication Cookie render issue [\#181](https://github.com/WebGoat/WebGoat/issues/181)
|
|
||||||
- Challenge - Show\* buttons show on initial lesson load [\#180](https://github.com/WebGoat/WebGoat/issues/180)
|
|
||||||
- Http Basics - minor edits and change completion state [\#178](https://github.com/WebGoat/WebGoat/issues/178)
|
|
||||||
- Lab Cross-Site Scripting Stage 1 solution [\#176](https://github.com/WebGoat/WebGoat/issues/176)
|
|
||||||
- Backdoor lesson breaks menu CSS [\#175](https://github.com/WebGoat/WebGoat/issues/175)
|
|
||||||
- Redirect localhost:8080 to localhost:8080/WebGoat [\#173](https://github.com/WebGoat/WebGoat/issues/173)
|
|
||||||
- Session Fixation link in stage 2 does not work [\#170](https://github.com/WebGoat/WebGoat/issues/170)
|
|
||||||
- A failure occurred when execute the command "sh webgoat\_developer\_bootstrap.sh" [\#145](https://github.com/WebGoat/WebGoat/issues/145)
|
|
||||||
- Copy lessons into plugin\_lessons [\#254](https://github.com/WebGoat/WebGoat/issues/254)
|
|
||||||
- WebGoat // Lesson Plan and Solution are note available [\#242](https://github.com/WebGoat/WebGoat/issues/242)
|
|
||||||
- Lab: Client side filtering - broken path [\#232](https://github.com/WebGoat/WebGoat/issues/232)
|
|
||||||
- AXIS class not found error in Web Services / WSDL Scanning [\#222](https://github.com/WebGoat/WebGoat/issues/222)
|
|
||||||
- WSDL link in SOAP Request Lesson crashing with AXIS error [\#221](https://github.com/WebGoat/WebGoat/issues/221)
|
|
||||||
- Labs: RBAC stage 1 and 3 not working [\#209](https://github.com/WebGoat/WebGoat/issues/209)
|
|
||||||
- How to create a Legacy Lesson - instruction edit [\#177](https://github.com/WebGoat/WebGoat/issues/177)
|
|
||||||
- Can't tell when WebGoat has actually started when using: webgoat\_developer\_bootstrap.sh [\#75](https://github.com/WebGoat/WebGoat/issues/75)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Add VMware fusion [\#264](https://github.com/WebGoat/WebGoat/pull/264) ([akiernan](https://github.com/akiernan))
|
|
||||||
- Remove Exception from method signature [\#257](https://github.com/WebGoat/WebGoat/pull/257) ([RubieV](https://github.com/RubieV))
|
|
||||||
- Code cleanup using @Test\(expected = Exception\) [\#256](https://github.com/WebGoat/WebGoat/pull/256) ([RubieV](https://github.com/RubieV))
|
|
||||||
- Added OWASP Labs badge [\#252](https://github.com/WebGoat/WebGoat/pull/252) ([psiinon](https://github.com/psiinon))
|
|
||||||
- updates from day 1 @AppSec EU [\#246](https://github.com/WebGoat/WebGoat/pull/246) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Update java required version as stated in webgoat/webgoat\#234 [\#243](https://github.com/WebGoat/WebGoat/pull/243) ([span](https://github.com/span))
|
|
||||||
- Updates to Dev Bootstrap [\#239](https://github.com/WebGoat/WebGoat/pull/239) ([dilshanraja](https://github.com/dilshanraja))
|
|
||||||
- Fix broken start/home link on logo [\#229](https://github.com/WebGoat/WebGoat/pull/229) ([span](https://github.com/span))
|
|
||||||
- Developer controls [\#228](https://github.com/WebGoat/WebGoat/pull/228) ([span](https://github.com/span))
|
|
||||||
- Admin should also be able to see the solution, source and lesson plan. [\#224](https://github.com/WebGoat/WebGoat/pull/224) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Fixed the classnames in the wsdd config file \(moved to different pack… [\#223](https://github.com/WebGoat/WebGoat/pull/223) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Feature/169 [\#220](https://github.com/WebGoat/WebGoat/pull/220) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Update README.MD [\#219](https://github.com/WebGoat/WebGoat/pull/219) ([muzir](https://github.com/muzir))
|
|
||||||
- Fix \#213 by changing the id of the restart button to the correct id [\#214](https://github.com/WebGoat/WebGoat/pull/214) ([span](https://github.com/span))
|
|
||||||
- Fixed \#184 [\#212](https://github.com/WebGoat/WebGoat/pull/212) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Fix shebang [\#210](https://github.com/WebGoat/WebGoat/pull/210) ([nxadm](https://github.com/nxadm))
|
|
||||||
- Enable weak authentication cookie lesson [\#207](https://github.com/WebGoat/WebGoat/pull/207) ([span](https://github.com/span))
|
|
||||||
- -- Remove raw type usage, add type check parameter. [\#205](https://github.com/WebGoat/WebGoat/pull/205) ([muzir](https://github.com/muzir))
|
|
||||||
- Update package references in readme [\#203](https://github.com/WebGoat/WebGoat/pull/203) ([span](https://github.com/span))
|
|
||||||
- Develop [\#202](https://github.com/WebGoat/WebGoat/pull/202) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Fixes \#195 by adding static initialisation of the maps [\#197](https://github.com/WebGoat/WebGoat/pull/197) ([span](https://github.com/span))
|
|
||||||
- Add stage parameter in the session to keep track of current stage [\#196](https://github.com/WebGoat/WebGoat/pull/196) ([span](https://github.com/span))
|
|
||||||
- webgoat-container should unpack all the lessons \#192 [\#193](https://github.com/WebGoat/WebGoat/pull/193) ([nbaars](https://github.com/nbaars))
|
|
||||||
|
|
||||||
## [7.0.1](https://github.com/WebGoat/WebGoat/tree/7.0.1) (2016-02-01)
|
|
||||||
**Implemented enhancements:**
|
|
||||||
|
|
||||||
- SEVERE: The web application \[/WebGoat\] appears to have started a thread named \[pool-7-thread-5\] but has failed to stop it. This is very likely to create a memory leak [\#124](https://github.com/WebGoat/WebGoat/issues/124)
|
|
||||||
- Cannot serialize session attribute [\#123](https://github.com/WebGoat/WebGoat/issues/123)
|
|
||||||
- Overview of which lessons maps to which WebGoat-Lessons project [\#107](https://github.com/WebGoat/WebGoat/issues/107)
|
|
||||||
- Remove ace js directory [\#103](https://github.com/WebGoat/WebGoat/issues/103)
|
|
||||||
- Move webgoat-container UP one directory [\#100](https://github.com/WebGoat/WebGoat/issues/100)
|
|
||||||
- Insecure login lesson has inline CSS background image is not applied [\#87](https://github.com/WebGoat/WebGoat/issues/87)
|
|
||||||
- Re-enable/update WebGoat Info link [\#26](https://github.com/WebGoat/WebGoat/issues/26)
|
|
||||||
- User Info/Logout Links [\#25](https://github.com/WebGoat/WebGoat/issues/25)
|
|
||||||
- LessonInfo Service [\#23](https://github.com/WebGoat/WebGoat/issues/23)
|
|
||||||
- Reload/Update Menu [\#22](https://github.com/WebGoat/WebGoat/issues/22)
|
|
||||||
|
|
||||||
**Fixed bugs:**
|
|
||||||
|
|
||||||
- Nightly build doesn't run [\#150](https://github.com/WebGoat/WebGoat/issues/150)
|
|
||||||
- Forced browsing lesson does not show success [\#143](https://github.com/WebGoat/WebGoat/issues/143)
|
|
||||||
- Failed to load resource: the server responded with a status of 404 \(Not Found\) [\#139](https://github.com/WebGoat/WebGoat/issues/139)
|
|
||||||
- Firefox and Edge miss one lesson in Menu [\#49](https://github.com/WebGoat/WebGoat/issues/49)
|
|
||||||
- Lesson Plan does not toggle on/off [\#46](https://github.com/WebGoat/WebGoat/issues/46)
|
|
||||||
- Clicking on 'LAB: Role Based Access Control' produces 'Invalid Session' in UI [\#44](https://github.com/WebGoat/WebGoat/issues/44)
|
|
||||||
- Lesson Loading Scrolls down page in Firefox [\#39](https://github.com/WebGoat/WebGoat/issues/39)
|
|
||||||
- WebGoat lessons do not load [\#32](https://github.com/WebGoat/WebGoat/issues/32)
|
|
||||||
- Properties are appended when loading plugins [\#29](https://github.com/WebGoat/WebGoat/issues/29)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Exceptions for all lessons in "LAB: DB SQL Injection" and "LAB: SQL Injection" [\#174](https://github.com/WebGoat/WebGoat/issues/174)
|
|
||||||
- JSP Goathills lessons imports are not valid [\#171](https://github.com/WebGoat/WebGoat/issues/171)
|
|
||||||
- update or remove http://webgoat.github.io/ [\#167](https://github.com/WebGoat/WebGoat/issues/167)
|
|
||||||
- Provide over-rideable 'submitMethod' via AbstractLesson [\#165](https://github.com/WebGoat/WebGoat/issues/165)
|
|
||||||
- Update HTTP Basics lesson [\#162](https://github.com/WebGoat/WebGoat/issues/162)
|
|
||||||
- Command Injection Issue WebGoat 7 [\#156](https://github.com/WebGoat/WebGoat/issues/156)
|
|
||||||
- XML Injection does not work [\#151](https://github.com/WebGoat/WebGoat/issues/151)
|
|
||||||
- Plan is not available for this lesson. [\#138](https://github.com/WebGoat/WebGoat/issues/138)
|
|
||||||
- Multi level login lesson works but is missing area around the form [\#135](https://github.com/WebGoat/WebGoat/issues/135)
|
|
||||||
- SEVERE: The web application \[/WebGoat\] registered the JDBC driver \[org.h2.Driver\] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered [\#134](https://github.com/WebGoat/WebGoat/issues/134)
|
|
||||||
- hints are not refreshed when switching lessons [\#133](https://github.com/WebGoat/WebGoat/issues/133)
|
|
||||||
- Sauce labs fails when running oraclejdk8 [\#118](https://github.com/WebGoat/WebGoat/issues/118)
|
|
||||||
- Logging in sometimes goes to report card and misses category-menu [\#114](https://github.com/WebGoat/WebGoat/issues/114)
|
|
||||||
- Order of elements in deployment descriptor [\#112](https://github.com/WebGoat/WebGoat/issues/112)
|
|
||||||
- The jar snapshot doesn't run [\#108](https://github.com/WebGoat/WebGoat/issues/108)
|
|
||||||
- re-enable challenge handling in LessonInfoModel [\#97](https://github.com/WebGoat/WebGoat/issues/97)
|
|
||||||
- Review and cleanup releases and builds [\#90](https://github.com/WebGoat/WebGoat/issues/90)
|
|
||||||
- Review and cleanup Installation Docs [\#89](https://github.com/WebGoat/WebGoat/issues/89)
|
|
||||||
- Ajax Security: LAB: Client Side Filtering [\#86](https://github.com/WebGoat/WebGoat/issues/86)
|
|
||||||
- Close button on about dialog does not close the dialog [\#81](https://github.com/WebGoat/WebGoat/issues/81)
|
|
||||||
- Lessons Intermittently showing up in WebGoat [\#76](https://github.com/WebGoat/WebGoat/issues/76)
|
|
||||||
- Order of buttons switch after submit [\#73](https://github.com/WebGoat/WebGoat/issues/73)
|
|
||||||
- After login, there is no default lesson [\#72](https://github.com/WebGoat/WebGoat/issues/72)
|
|
||||||
- Intermittent Startup Error [\#71](https://github.com/WebGoat/WebGoat/issues/71)
|
|
||||||
- Discover Clues in HTML lesson doesn't work [\#70](https://github.com/WebGoat/WebGoat/issues/70)
|
|
||||||
- Eclipse import error for webgoat-container [\#66](https://github.com/WebGoat/WebGoat/issues/66)
|
|
||||||
- Reflected XSS Attacks error message error [\#65](https://github.com/WebGoat/WebGoat/issues/65)
|
|
||||||
- Labs with Stages all throw exceptions [\#64](https://github.com/WebGoat/WebGoat/issues/64)
|
|
||||||
- Spelling errors in: webgoat\_developer\_bootstrap.sh [\#63](https://github.com/WebGoat/WebGoat/issues/63)
|
|
||||||
- CSRF token by-pass lesson shows stacktrace [\#60](https://github.com/WebGoat/WebGoat/issues/60)
|
|
||||||
- Http Basics lessons fails to load [\#53](https://github.com/WebGoat/WebGoat/issues/53)
|
|
||||||
- Null Pointer Exception on every page [\#47](https://github.com/WebGoat/WebGoat/issues/47)
|
|
||||||
- Create support in client-side routing for 'stages' [\#42](https://github.com/WebGoat/WebGoat/issues/42)
|
|
||||||
- Implement Loading Spinner on Menu [\#41](https://github.com/WebGoat/WebGoat/issues/41)
|
|
||||||
- Lab - DOM-based cross-site scripting: Java Source produces XSS alert [\#38](https://github.com/WebGoat/WebGoat/issues/38)
|
|
||||||
- DOM Injection Lesson - Java Source does not work [\#37](https://github.com/WebGoat/WebGoat/issues/37)
|
|
||||||
- Lesson Interdependency [\#33](https://github.com/WebGoat/WebGoat/issues/33)
|
|
||||||
- Hide menu functionality [\#28](https://github.com/WebGoat/WebGoat/issues/28)
|
|
||||||
- Consume LessonInfo Service to display title [\#24](https://github.com/WebGoat/WebGoat/issues/24)
|
|
||||||
- how to up webgoat to netbeans on mac os x. [\#14](https://github.com/WebGoat/WebGoat/issues/14)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Disable cross-site scripting lab [\#191](https://github.com/WebGoat/WebGoat/pull/191) ([span](https://github.com/span))
|
|
||||||
- Adding OSSRH Repository on Parent Pom [\#190](https://github.com/WebGoat/WebGoat/pull/190) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Setting GPG keyname as WebGoat in Parent Pom [\#189](https://github.com/WebGoat/WebGoat/pull/189) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Fixining all the javadoc issues preventing the release [\#188](https://github.com/WebGoat/WebGoat/pull/188) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Improving WebGoat Developer Bootstrap Script [\#187](https://github.com/WebGoat/WebGoat/pull/187) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- issue \#147 disabling broken lessons [\#185](https://github.com/WebGoat/WebGoat/pull/185) ([mayhew64](https://github.com/mayhew64))
|
|
||||||
- \#167 removing refrences to github.io in code [\#172](https://github.com/WebGoat/WebGoat/pull/172) ([misfir3](https://github.com/misfir3))
|
|
||||||
- \#165 support for custom submitMethod [\#166](https://github.com/WebGoat/WebGoat/pull/166) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Remove Coverity Badge from README [\#164](https://github.com/WebGoat/WebGoat/pull/164) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Forced browsing [\#163](https://github.com/WebGoat/WebGoat/pull/163) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Moving lesson utilities to common project instead of AbstractLesson [\#155](https://github.com/WebGoat/WebGoat/pull/155) ([nbaars](https://github.com/nbaars))
|
|
||||||
- \#133 hiding hint on change of lesson/loesson load [\#153](https://github.com/WebGoat/WebGoat/pull/153) ([misfir3](https://github.com/misfir3))
|
|
||||||
- changed back to compile phase, package phase breaks the war-exec.jar … [\#152](https://github.com/WebGoat/WebGoat/pull/152) ([mayhew64](https://github.com/mayhew64))
|
|
||||||
- Fixes typo in README [\#149](https://github.com/WebGoat/WebGoat/pull/149) ([aravindc26](https://github.com/aravindc26))
|
|
||||||
- \#66 Fixing jar plugin lifecycle issue [\#148](https://github.com/WebGoat/WebGoat/pull/148) ([slavP](https://github.com/slavP))
|
|
||||||
- Tidy up CSRF lessons. [\#147](https://github.com/WebGoat/WebGoat/pull/147) ([ilatypov](https://github.com/ilatypov))
|
|
||||||
- Updated pom versions and cache .m2 on travis to speed build time [\#140](https://github.com/WebGoat/WebGoat/pull/140) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Update dependency version, build number and unregister DB driver [\#136](https://github.com/WebGoat/WebGoat/pull/136) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- SEVERE: The web application \[/WebGoat\] appears to have started a thr… [\#132](https://github.com/WebGoat/WebGoat/pull/132) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Do not clean before mvn cobertura and coveralls [\#131](https://github.com/WebGoat/WebGoat/pull/131) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Cannot serialize session attribute \#123 [\#130](https://github.com/WebGoat/WebGoat/pull/130) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Maven-tomcat plugin fix and correct typo on JS file [\#129](https://github.com/WebGoat/WebGoat/pull/129) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- items ommited from menu spinner and some more clean up [\#127](https://github.com/WebGoat/WebGoat/pull/127) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Coveralls should be on Parent Pom [\#126](https://github.com/WebGoat/WebGoat/pull/126) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Adding badges for Coverity, Coveralls and Codacy [\#125](https://github.com/WebGoat/WebGoat/pull/125) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Test enable Coverity SAST [\#122](https://github.com/WebGoat/WebGoat/pull/122) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Improved README instructions for Easy Run [\#121](https://github.com/WebGoat/WebGoat/pull/121) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Copy whole target folder, not just individual file [\#120](https://github.com/WebGoat/WebGoat/pull/120) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Code cleanup and menu spinner [\#119](https://github.com/WebGoat/WebGoat/pull/119) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Logging in sometimes goes to report card and misses category-menu \#114 [\#117](https://github.com/WebGoat/WebGoat/pull/117) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Copy output and target info upload to S3 folder [\#116](https://github.com/WebGoat/WebGoat/pull/116) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Fix \#81 to activate close button in the modal footer [\#115](https://github.com/WebGoat/WebGoat/pull/115) ([span](https://github.com/span))
|
|
||||||
- Fix \#112 deployment descriptor elements in wrong order [\#113](https://github.com/WebGoat/WebGoat/pull/113) ([span](https://github.com/span))
|
|
||||||
- \#103: removing ace directory, not in use [\#111](https://github.com/WebGoat/WebGoat/pull/111) ([misfir3](https://github.com/misfir3))
|
|
||||||
- The jar snapshot doesn't run \#108 \(2\) [\#110](https://github.com/WebGoat/WebGoat/pull/110) ([nbaars](https://github.com/nbaars))
|
|
||||||
- The jar snapshot doesn't run \#108 [\#109](https://github.com/WebGoat/WebGoat/pull/109) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Removed credits from lessons [\#106](https://github.com/WebGoat/WebGoat/pull/106) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Fixed classloading issues with Goathills lessons [\#105](https://github.com/WebGoat/WebGoat/pull/105) ([nbaars](https://github.com/nbaars))
|
|
||||||
- i8n highlighting \#96 [\#102](https://github.com/WebGoat/WebGoat/pull/102) ([nbaars](https://github.com/nbaars))
|
|
||||||
- \#97, updating controls for hints, source, solution and plans on lessons [\#101](https://github.com/WebGoat/WebGoat/pull/101) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Button to force plugin reloading \#93 [\#99](https://github.com/WebGoat/WebGoat/pull/99) ([nbaars](https://github.com/nbaars))
|
|
||||||
- \#97, Hint controls for CHALLENGE Category lessons [\#98](https://github.com/WebGoat/WebGoat/pull/98) ([misfir3](https://github.com/misfir3))
|
|
||||||
- \#23, \#24 - LessonInfo Service now used for TitleView and HelpControsView [\#94](https://github.com/WebGoat/WebGoat/pull/94) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Properties are appended when loading plugins \(\#29\) [\#88](https://github.com/WebGoat/WebGoat/pull/88) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Added a lesson restart for lesson specific restart actions [\#85](https://github.com/WebGoat/WebGoat/pull/85) ([mayhew64](https://github.com/mayhew64))
|
|
||||||
- Fixing inconsistent merge issues implementing nbaars fixes [\#83](https://github.com/WebGoat/WebGoat/pull/83) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Updated contributors and sponsors [\#82](https://github.com/WebGoat/WebGoat/pull/82) ([mayhew64](https://github.com/mayhew64))
|
|
||||||
- \#72, defaulting to firstLesson on initial redirect [\#80](https://github.com/WebGoat/WebGoat/pull/80) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Intermittent Startup Error \#71 [\#79](https://github.com/WebGoat/WebGoat/pull/79) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Adding Coverity Static Code Analysis Scan integration [\#78](https://github.com/WebGoat/WebGoat/pull/78) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Pom refactoring, javadocs compliance and Integration improvements [\#77](https://github.com/WebGoat/WebGoat/pull/77) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Property files are now detected while extracting the plugin [\#74](https://github.com/WebGoat/WebGoat/pull/74) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Recent UI Fixes [\#61](https://github.com/WebGoat/WebGoat/pull/61) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Lab - DOM-based cross-site scripting: Java Source produces XSS alert \#38 [\#59](https://github.com/WebGoat/WebGoat/pull/59) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Update README.MD [\#57](https://github.com/WebGoat/WebGoat/pull/57) ([mayhew64](https://github.com/mayhew64))
|
|
||||||
- Do NOT run Integration tests on pull requests [\#56](https://github.com/WebGoat/WebGoat/pull/56) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Increase performance while extracting the plugins [\#55](https://github.com/WebGoat/WebGoat/pull/55) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Http Basics lessons fails to load \#53 [\#54](https://github.com/WebGoat/WebGoat/pull/54) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Adding headless Integration Tests with Sauce Labs [\#50](https://github.com/WebGoat/WebGoat/pull/50) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Null Pointer Exception on every page \#47 [\#48](https://github.com/WebGoat/WebGoat/pull/48) ([nbaars](https://github.com/nbaars))
|
|
||||||
- menu and routing work [\#43](https://github.com/WebGoat/WebGoat/pull/43) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Fixes for issue \#32 - lessons/menu not loading [\#40](https://github.com/WebGoat/WebGoat/pull/40) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Fixed not serializable error when stopping/starting Tomcat [\#36](https://github.com/WebGoat/WebGoat/pull/36) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Improved README, fixed copy lessons instructions, added developer bootstrap [\#35](https://github.com/WebGoat/WebGoat/pull/35) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- Improved Travis Build and Instructions on Readme [\#31](https://github.com/WebGoat/WebGoat/pull/31) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- recent modifications from my branch [\#30](https://github.com/WebGoat/WebGoat/pull/30) ([misfir3](https://github.com/misfir3))
|
|
||||||
- initial cut of paramView re-enabled [\#21](https://github.com/WebGoat/WebGoat/pull/21) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Removing doc directory which contained 6 year old stale files [\#18](https://github.com/WebGoat/WebGoat/pull/18) ([dougmorato](https://github.com/dougmorato))
|
|
||||||
- First pull request, minor fix [\#17](https://github.com/WebGoat/WebGoat/pull/17) ([silicakes](https://github.com/silicakes))
|
|
||||||
- cookie view re-enabled [\#16](https://github.com/WebGoat/WebGoat/pull/16) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Incremental UI changes [\#15](https://github.com/WebGoat/WebGoat/pull/15) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Merged changes from WebGoat-Legacy to WebGoat [\#13](https://github.com/WebGoat/WebGoat/pull/13) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Merge pull request \#48 from michaeldever/master [\#11](https://github.com/WebGoat/WebGoat/pull/11) ([nbaars](https://github.com/nbaars))
|
|
||||||
- restoring READMe.txt [\#10](https://github.com/WebGoat/WebGoat/pull/10) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Initial cut-over of backbone port [\#9](https://github.com/WebGoat/WebGoat/pull/9) ([misfir3](https://github.com/misfir3))
|
|
||||||
- Added a method so we can fetch the absolute path of a lesson [\#8](https://github.com/WebGoat/WebGoat/pull/8) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Fixed rewriting paths in the jsp/js and css resources [\#7](https://github.com/WebGoat/WebGoat/pull/7) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Classloader introduced [\#6](https://github.com/WebGoat/WebGoat/pull/6) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Instructions for manual deployment [\#5](https://github.com/WebGoat/WebGoat/pull/5) ([iammyr](https://github.com/iammyr))
|
|
||||||
- Renamed the jar file [\#4](https://github.com/WebGoat/WebGoat/pull/4) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Fixed classloading issues when a lesson contains an inner class. The plu... [\#3](https://github.com/WebGoat/WebGoat/pull/3) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Generate separate jar file to use in the lessons project [\#2](https://github.com/WebGoat/WebGoat/pull/2) ([nbaars](https://github.com/nbaars))
|
|
||||||
- Bug fix: lesson solution not showing [\#1](https://github.com/WebGoat/WebGoat/pull/1) ([nbaars](https://github.com/nbaars))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
|
@ -20,8 +20,8 @@ git flow release publish
|
|||||||
Now we can make a new release, be sure you committed all your changes.
|
Now we can make a new release, be sure you committed all your changes.
|
||||||
|
|
||||||
```
|
```
|
||||||
git tag v8.0.0.M3
|
git tag v8.0.0.M15
|
||||||
git push origin v8.0.0.M3
|
git push origin v8.0.0.M15
|
||||||
```
|
```
|
||||||
|
|
||||||
Now Travis takes over and will create the release in Github and on Docker Hub.
|
Now Travis takes over and will create the release in Github and on Docker Hub.
|
||||||
|
17
README.MD
17
README.MD
@ -4,8 +4,8 @@
|
|||||||
[](https://coveralls.io/github/WebGoat/WebGoat?branch=master)
|
[](https://coveralls.io/github/WebGoat/WebGoat?branch=master)
|
||||||
[](https://www.codacy.com/app/dm/WebGoat)
|
[](https://www.codacy.com/app/dm/WebGoat)
|
||||||
[](https://www.versioneye.com/user/projects/562da95ae346d7000e0369aa)
|
[](https://www.versioneye.com/user/projects/562da95ae346d7000e0369aa)
|
||||||
[](https://www.owasp.org/index.php/OWASP_Project_Inventory#tab=Labs_Projects)
|
[](https://www.owasp.org/index.php/OWASP_Project_Inventory#tab=Labs_Projects)
|
||||||
|
[](https://github.com/WebGoat/WebGoat/releases/latest)
|
||||||
|
|
||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
@ -40,6 +40,15 @@ docker pull webgoat/webgoat-8.0
|
|||||||
docker run -p 8080:8080 -it webgoat/webgoat-8.0 /home/webgoat/start.sh
|
docker run -p 8080:8080 -it webgoat/webgoat-8.0 /home/webgoat/start.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you want to keep the database between Docker sessions you need to map the WebGoat data directory to a
|
||||||
|
folder on the host system as follows:
|
||||||
|
|
||||||
|
```Shell
|
||||||
|
docker run -p 8080:8080 -it -v /tmp/webgoat-data:/home/webgoat/.webgoat-${VERSION} webgoat/webgoat-8.0 /home/webgoat/start.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
where `${VERSION}` is for example `v8.0.0.M14`. The data will now be stored in `/tmp/webgoat-data` on your host system.
|
||||||
|
|
||||||
Wait for the Docker container to start, and run `docker ps` to verify it's running.
|
Wait for the Docker container to start, and run `docker ps` to verify it's running.
|
||||||
|
|
||||||
- If you are using `docker-machine`, verify the machine IP using `docker-machine env`
|
- If you are using `docker-machine`, verify the machine IP using `docker-machine env`
|
||||||
@ -58,7 +67,7 @@ _Please note: this version may not be completely in sync with the develop branch
|
|||||||
|
|
||||||
## 2. Standalone
|
## 2. Standalone
|
||||||
|
|
||||||
Download the latest WebWolf release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
|
Download the latest WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
|
||||||
|
|
||||||
```Shell
|
```Shell
|
||||||
java -jar webgoat-server-<<version>>.jar
|
java -jar webgoat-server-<<version>>.jar
|
||||||
@ -121,7 +130,7 @@ server.address=x.x.x.x
|
|||||||
We supply a complete development environment using Vagrant, to run WebGoat with Vagrant you must first have Vagrant and Virtualbox installed.
|
We supply a complete development environment using Vagrant, to run WebGoat with Vagrant you must first have Vagrant and Virtualbox installed.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ cd WebGoat/webgoat-images/vagrant-users
|
$ cd WebGoat/webgoat-images/vagrant-training
|
||||||
$ vagrant up
|
$ vagrant up
|
||||||
```
|
```
|
||||||
|
|
||||||
|
35
docker-compose-postgres.yml
Normal file
35
docker-compose-postgres.yml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
version: '2.0'
|
||||||
|
|
||||||
|
services:
|
||||||
|
webgoat:
|
||||||
|
image: webgoat/webgoat-8.0
|
||||||
|
user: webgoat
|
||||||
|
environment:
|
||||||
|
- WEBWOLF_HOST=webwolf
|
||||||
|
- spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat
|
||||||
|
- spring.datasource.username=webgoat
|
||||||
|
- spring.datasource.password=webgoat
|
||||||
|
- spring.datasource.driver-class-name=org.postgresql.Driver
|
||||||
|
- spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL94Dialect
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
webwolf:
|
||||||
|
image: webgoat/webwolf
|
||||||
|
environment:
|
||||||
|
- spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat
|
||||||
|
- spring.datasource.username=webgoat
|
||||||
|
- spring.datasource.password=webgoat
|
||||||
|
- spring.datasource.driver-class-name=org.postgresql.Driver
|
||||||
|
- spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL94Dialect
|
||||||
|
ports:
|
||||||
|
- "8081:8081"
|
||||||
|
db:
|
||||||
|
container_name: webgoat_db
|
||||||
|
image: postgres:latest
|
||||||
|
environment:
|
||||||
|
- POSTGRES_PASSWORD=webgoat
|
||||||
|
- POSTGRES_USER=webgoat
|
||||||
|
- POSTGRES_DB=webgoat
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
|
@ -1,15 +1,28 @@
|
|||||||
version: '2.0'
|
version: '2.1'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
webgoat:
|
webgoat:
|
||||||
build: webgoat-server/
|
image: webgoat/webgoat-8.0
|
||||||
command: "sh /home/webgoat/start.sh"
|
environment:
|
||||||
|
- WEBWOLF_HOST=webwolf
|
||||||
|
- spring.datasource.url=jdbc:hsqldb:hsql://webgoat_db:9001/webgoat
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
webwolf:
|
|
||||||
build: webwolf/
|
|
||||||
command: "sh /home/webwolf/start.sh"
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- webgoat
|
- db
|
||||||
|
webwolf:
|
||||||
|
image: webgoat/webwolf
|
||||||
|
environment:
|
||||||
|
- spring.datasource.url=jdbc:hsqldb:hsql://webgoat_db:9001/webgoat
|
||||||
ports:
|
ports:
|
||||||
- "8081:8081"
|
- "8081:8081"
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
db:
|
||||||
|
image: blacklabelops/hsqldb
|
||||||
|
container_name: webgoat_db
|
||||||
|
environment:
|
||||||
|
- HSQLDB_TRACE=false
|
||||||
|
- HSQLDB_SILENT=true
|
||||||
|
- HSQLDB_DATABASE_NAME=webgoat
|
||||||
|
- HSQLDB_DATABASE_ALIAS=webgoat
|
||||||
|
6
pom.xml
6
pom.xml
@ -5,7 +5,7 @@
|
|||||||
<groupId>org.owasp.webgoat</groupId>
|
<groupId>org.owasp.webgoat</groupId>
|
||||||
<artifactId>webgoat-parent</artifactId>
|
<artifactId>webgoat-parent</artifactId>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<version>8.0.0.M3</version>
|
<version>v8.0.0.M15</version>
|
||||||
|
|
||||||
<name>WebGoat Parent Pom</name>
|
<name>WebGoat Parent Pom</name>
|
||||||
<description>Parent Pom for the WebGoat Project. A deliberately insecure Web Application</description>
|
<description>Parent Pom for the WebGoat Project. A deliberately insecure Web Application</description>
|
||||||
@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
<version>1.5.5.RELEASE</version>
|
<version>1.5.12.RELEASE</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<licenses>
|
<licenses>
|
||||||
@ -135,7 +135,7 @@
|
|||||||
<gatling-plugin.version>2.2.4</gatling-plugin.version>
|
<gatling-plugin.version>2.2.4</gatling-plugin.version>
|
||||||
<guava.version>18.0</guava.version>
|
<guava.version>18.0</guava.version>
|
||||||
<h2.version>1.4.190</h2.version>
|
<h2.version>1.4.190</h2.version>
|
||||||
<hsqldb.version>2.3.2</hsqldb.version>
|
<hsqldb.version>2.3.4</hsqldb.version>
|
||||||
<j2h.version>1.3.1</j2h.version>
|
<j2h.version>1.3.1</j2h.version>
|
||||||
<jackson-core.version>2.6.3</jackson-core.version>
|
<jackson-core.version>2.6.3</jackson-core.version>
|
||||||
<jackson-databind.version>2.6.3</jackson-databind.version>
|
<jackson-databind.version>2.6.3</jackson-databind.version>
|
||||||
|
@ -20,3 +20,21 @@ elif [ ! -z "${TRAVIS_TAG}" ]; then
|
|||||||
else
|
else
|
||||||
echo "Skipping releasing to DockerHub because it is a build of branch ${BRANCH}"
|
echo "Skipping releasing to DockerHub because it is a build of branch ${BRANCH}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
export REPO=webgoat/webwolf
|
||||||
|
cd ..
|
||||||
|
cd webwolf
|
||||||
|
ls target/
|
||||||
|
|
||||||
|
if [ "${BRANCH}" == "master" ] && [ ! -z "${TRAVIS_TAG}" ]; then
|
||||||
|
# If we push a tag to master this will update the LATEST Docker image and tag with the version number
|
||||||
|
docker build --build-arg webwolf_version=${TRAVIS_TAG:1} -f Dockerfile -t $REPO:latest -t $REPO:${TRAVIS_TAG} .
|
||||||
|
docker push $REPO
|
||||||
|
elif [ ! -z "${TRAVIS_TAG}" ]; then
|
||||||
|
# Creating a tag build we push it to Docker with that tag
|
||||||
|
docker build --build-arg webwolf_version=${TRAVIS_TAG:1} -f Dockerfile -t $REPO:${TRAVIS_TAG} -t $REPO:latest .
|
||||||
|
docker push $REPO
|
||||||
|
else
|
||||||
|
echo "Skipping releasing to DockerHub because it is a build of branch ${BRANCH}"
|
||||||
|
fi
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 16 KiB |
@ -10,7 +10,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp.webgoat</groupId>
|
<groupId>org.owasp.webgoat</groupId>
|
||||||
<artifactId>webgoat-parent</artifactId>
|
<artifactId>webgoat-parent</artifactId>
|
||||||
<version>8.0.0.M3</version>
|
<version>v8.0.0.M15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
|
@ -34,6 +34,9 @@ import com.google.common.collect.Maps;
|
|||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.asciidoctor.Asciidoctor;
|
import org.asciidoctor.Asciidoctor;
|
||||||
|
import org.asciidoctor.extension.JavaExtensionRegistry;
|
||||||
|
import org.owasp.webgoat.asciidoc.WebGoatVersionMacro;
|
||||||
|
import org.owasp.webgoat.asciidoc.WebWolfMacro;
|
||||||
import org.owasp.webgoat.i18n.Language;
|
import org.owasp.webgoat.i18n.Language;
|
||||||
import org.thymeleaf.TemplateProcessingParameters;
|
import org.thymeleaf.TemplateProcessingParameters;
|
||||||
import org.thymeleaf.resourceresolver.IResourceResolver;
|
import org.thymeleaf.resourceresolver.IResourceResolver;
|
||||||
@ -82,6 +85,10 @@ public class AsciiDoctorTemplateResolver extends TemplateResolver {
|
|||||||
return new ByteArrayInputStream(new byte[0]);
|
return new ByteArrayInputStream(new byte[0]);
|
||||||
} else {
|
} else {
|
||||||
StringWriter writer = new StringWriter();
|
StringWriter writer = new StringWriter();
|
||||||
|
JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry();
|
||||||
|
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class);
|
||||||
|
extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class);
|
||||||
|
|
||||||
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
|
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
|
||||||
return new ByteArrayInputStream(writer.getBuffer().toString().getBytes(UTF_8));
|
return new ByteArrayInputStream(writer.getBuffer().toString().getBytes(UTF_8));
|
||||||
}
|
}
|
||||||
|
@ -130,6 +130,7 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
|
|||||||
@Bean
|
@Bean
|
||||||
public PluginMessages pluginMessages(Messages messages, Language language) {
|
public PluginMessages pluginMessages(Messages messages, Language language) {
|
||||||
PluginMessages pluginMessages = new PluginMessages(messages, language);
|
PluginMessages pluginMessages = new PluginMessages(messages, language);
|
||||||
|
pluginMessages.setDefaultEncoding("UTF-8");
|
||||||
pluginMessages.setBasenames("i18n/WebGoatLabels");
|
pluginMessages.setBasenames("i18n/WebGoatLabels");
|
||||||
return pluginMessages;
|
return pluginMessages;
|
||||||
}
|
}
|
||||||
@ -142,6 +143,7 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
|
|||||||
@Bean
|
@Bean
|
||||||
public Messages messageSource(Language language) {
|
public Messages messageSource(Language language) {
|
||||||
Messages messages = new Messages(language);
|
Messages messages = new Messages(language);
|
||||||
|
messages.setDefaultEncoding("UTF-8");
|
||||||
messages.setBasename("classpath:i18n/messages");
|
messages.setBasename("classpath:i18n/messages");
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package org.owasp.webgoat.asciidoc;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make environment available in the asciidoc code (which you cannot inject because it is handled by the framework)
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class EnvironmentExposure implements ApplicationContextAware {
|
||||||
|
|
||||||
|
private static ApplicationContext context;
|
||||||
|
|
||||||
|
public static Environment getEnv() {
|
||||||
|
return context.getEnvironment();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
|
context = applicationContext;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package org.owasp.webgoat.asciidoc;
|
||||||
|
|
||||||
|
import org.asciidoctor.ast.AbstractBlock;
|
||||||
|
import org.asciidoctor.extension.InlineMacroProcessor;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class WebGoatVersionMacro extends InlineMacroProcessor {
|
||||||
|
|
||||||
|
public WebGoatVersionMacro(String macroName, Map<String, Object> config) {
|
||||||
|
super(macroName, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
|
||||||
|
return EnvironmentExposure.getEnv().getProperty("webgoat.build.version");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package org.owasp.webgoat.asciidoc;
|
||||||
|
|
||||||
|
import org.asciidoctor.ast.AbstractBlock;
|
||||||
|
import org.asciidoctor.extension.InlineMacroProcessor;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Usage in asciidoc:
|
||||||
|
* <p>
|
||||||
|
* webWolfLink:here[] will display a href with here as text
|
||||||
|
* webWolfLink:landing[noLink] will display the complete url, for example: http://WW_HOST:WW_PORT/landing
|
||||||
|
*/
|
||||||
|
public class WebWolfMacro extends InlineMacroProcessor {
|
||||||
|
|
||||||
|
public WebWolfMacro(String macroName, Map<String, Object> config) {
|
||||||
|
super(macroName, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
|
||||||
|
Environment env = EnvironmentExposure.getEnv();
|
||||||
|
String hostname = determineHost(env.getProperty("webwolf.host"), env.getProperty("webwolf.port"));
|
||||||
|
|
||||||
|
if (displayCompleteLinkNoFormatting(attributes)) {
|
||||||
|
return hostname + (hostname.endsWith("/") ? "" : "/") + target;
|
||||||
|
}
|
||||||
|
return "<a href=\"" + hostname + "\" target=\"_blank\">" + target + "</a>";
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean displayCompleteLinkNoFormatting(Map<String, Object> attributes) {
|
||||||
|
return attributes.values().stream().filter(a -> a.equals("noLink")).findFirst().isPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look at the remote address from received from the browser first. This way it will also work if you run
|
||||||
|
* the browser in a Docker container and WebGoat on your local machine.
|
||||||
|
*/
|
||||||
|
private String determineHost(String host, String port) {
|
||||||
|
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
|
||||||
|
String ip = request.getRemoteAddr();
|
||||||
|
String hostname = StringUtils.hasText(ip) ? ip : host;
|
||||||
|
return "http://" + hostname + ":" + port + "/WebWolf";
|
||||||
|
}
|
||||||
|
}
|
@ -55,7 +55,7 @@ public abstract class AssignmentEndpoint extends Endpoint {
|
|||||||
|
|
||||||
//// TODO: 11/13/2016 events better fit?
|
//// TODO: 11/13/2016 events better fit?
|
||||||
protected AttackResult trackProgress(AttackResult attackResult) {
|
protected AttackResult trackProgress(AttackResult attackResult) {
|
||||||
UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName());
|
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||||
if (userTracker == null) {
|
if (userTracker == null) {
|
||||||
userTracker = new UserTracker(webSession.getUserName());
|
userTracker = new UserTracker(webSession.getUserName());
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
package org.owasp.webgoat.lessons;
|
package org.owasp.webgoat.lessons;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.*;
|
||||||
import javax.persistence.Id;
|
|
||||||
import javax.persistence.OneToMany;
|
|
||||||
import javax.persistence.Transient;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,19 +35,30 @@ import java.util.List;
|
|||||||
* @version $Id: $Id
|
* @version $Id: $Id
|
||||||
* @since November 25, 2016
|
* @since November 25, 2016
|
||||||
*/
|
*/
|
||||||
@AllArgsConstructor
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Getter
|
@Getter
|
||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
@Entity
|
@Entity
|
||||||
public class Assignment {
|
public class Assignment {
|
||||||
@NonNull
|
|
||||||
@Id
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
@NonNull
|
|
||||||
private String path;
|
private String path;
|
||||||
@Transient
|
@Transient
|
||||||
private List<String> hints;
|
private List<String> hints;
|
||||||
|
|
||||||
|
private Assignment() {
|
||||||
|
//Hibernate
|
||||||
|
}
|
||||||
|
|
||||||
|
public Assignment(String name, String path) {
|
||||||
|
this(name, path, Lists.newArrayList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Assignment(String name, String path, List<String> hints) {
|
||||||
|
this.name = name;
|
||||||
|
this.path = path;
|
||||||
|
this.hints = hints;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ public enum Category {
|
|||||||
INSECURE_CONFIGURATION("Insecure Configuration", new Integer(600)),
|
INSECURE_CONFIGURATION("Insecure Configuration", new Integer(600)),
|
||||||
INSECURE_COMMUNICATION("Insecure Communication", new Integer(700)),
|
INSECURE_COMMUNICATION("Insecure Communication", new Integer(700)),
|
||||||
INSECURE_STORAGE("Insecure Storage", new Integer(800)),
|
INSECURE_STORAGE("Insecure Storage", new Integer(800)),
|
||||||
|
INSECURE_DESERIALIZATION("Insecure Deserialization", new Integer(850)),
|
||||||
REQUEST_FORGERIES("Request Forgeries", new Integer(900)),
|
REQUEST_FORGERIES("Request Forgeries", new Integer(900)),
|
||||||
VULNERABLE_COMPONENTS("Vulnerable Components - A9", new Integer(950)),
|
VULNERABLE_COMPONENTS("Vulnerable Components - A9", new Integer(950)),
|
||||||
AJAX_SECURITY("AJAX Security", new Integer(1000)),
|
AJAX_SECURITY("AJAX Security", new Integer(1000)),
|
||||||
|
@ -2,7 +2,6 @@ package org.owasp.webgoat.lessons;
|
|||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.owasp.webgoat.session.WebSession;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>LessonInfoModel class.</p>
|
* <p>LessonInfoModel class.</p>
|
||||||
|
@ -73,7 +73,7 @@ public class LessonMenuService {
|
|||||||
List<LessonMenuItem> showLeftNav() {
|
List<LessonMenuItem> showLeftNav() {
|
||||||
List<LessonMenuItem> menu = new ArrayList<>();
|
List<LessonMenuItem> menu = new ArrayList<>();
|
||||||
List<Category> categories = course.getCategories();
|
List<Category> categories = course.getCategories();
|
||||||
UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName());
|
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||||
|
|
||||||
for (Category category : categories) {
|
for (Category category : categories) {
|
||||||
LessonMenuItem categoryItem = new LessonMenuItem();
|
LessonMenuItem categoryItem = new LessonMenuItem();
|
||||||
|
@ -40,17 +40,19 @@ public class LessonProgressService {
|
|||||||
@RequestMapping(value = "/service/lessonprogress.mvc", produces = "application/json")
|
@RequestMapping(value = "/service/lessonprogress.mvc", produces = "application/json")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public Map getLessonInfo() {
|
public Map getLessonInfo() {
|
||||||
UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName());
|
|
||||||
LessonTracker lessonTracker = userTracker.getLessonTracker(webSession.getCurrentLesson());
|
|
||||||
Map json = Maps.newHashMap();
|
Map json = Maps.newHashMap();
|
||||||
String successMessage = "";
|
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||||
boolean lessonCompleted = false;
|
if (webSession.getCurrentLesson() != null) {
|
||||||
if (lessonTracker != null) {
|
LessonTracker lessonTracker = userTracker.getLessonTracker(webSession.getCurrentLesson());
|
||||||
lessonCompleted = lessonTracker.isLessonSolved();
|
String successMessage = "";
|
||||||
successMessage = "LessonCompleted"; //@todo we still use this??
|
boolean lessonCompleted = false;
|
||||||
|
if (lessonTracker != null) {
|
||||||
|
lessonCompleted = lessonTracker.isLessonSolved();
|
||||||
|
successMessage = "LessonCompleted"; //@todo we still use this??
|
||||||
|
}
|
||||||
|
json.put("lessonCompleted", lessonCompleted);
|
||||||
|
json.put("successMessage", successMessage);
|
||||||
}
|
}
|
||||||
json.put("lessonCompleted", lessonCompleted);
|
|
||||||
json.put("successMessage", successMessage);
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +65,7 @@ public class LessonProgressService {
|
|||||||
@RequestMapping(value = "/service/lessonoverview.mvc", produces = "application/json")
|
@RequestMapping(value = "/service/lessonoverview.mvc", produces = "application/json")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public List<LessonOverview> lessonOverview() {
|
public List<LessonOverview> lessonOverview() {
|
||||||
UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName());
|
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||||
AbstractLesson currentLesson = webSession.getCurrentLesson();
|
AbstractLesson currentLesson = webSession.getCurrentLesson();
|
||||||
List<LessonOverview> result = Lists.newArrayList();
|
List<LessonOverview> result = Lists.newArrayList();
|
||||||
if ( currentLesson != null ) {
|
if ( currentLesson != null ) {
|
||||||
|
@ -32,6 +32,7 @@ import com.google.common.collect.Lists;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.owasp.webgoat.i18n.PluginMessages;
|
||||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||||
import org.owasp.webgoat.session.Course;
|
import org.owasp.webgoat.session.Course;
|
||||||
import org.owasp.webgoat.session.WebSession;
|
import org.owasp.webgoat.session.WebSession;
|
||||||
@ -57,6 +58,7 @@ public class ReportCardService {
|
|||||||
private final WebSession webSession;
|
private final WebSession webSession;
|
||||||
private final UserTrackerRepository userTrackerRepository;
|
private final UserTrackerRepository userTrackerRepository;
|
||||||
private final Course course;
|
private final Course course;
|
||||||
|
private final PluginMessages pluginMessages;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Endpoint which generates the report card for the current use to show the stats on the solved lessons
|
* Endpoint which generates the report card for the current use to show the stats on the solved lessons
|
||||||
@ -64,7 +66,7 @@ public class ReportCardService {
|
|||||||
@GetMapping(path = "/service/reportcard.mvc", produces = "application/json")
|
@GetMapping(path = "/service/reportcard.mvc", produces = "application/json")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public ReportCard reportCard() {
|
public ReportCard reportCard() {
|
||||||
UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName());
|
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||||
List<AbstractLesson> lessons = course.getLessons();
|
List<AbstractLesson> lessons = course.getLessons();
|
||||||
ReportCard reportCard = new ReportCard();
|
ReportCard reportCard = new ReportCard();
|
||||||
reportCard.setTotalNumberOfLessons(course.getTotalOfLessons());
|
reportCard.setTotalNumberOfLessons(course.getTotalOfLessons());
|
||||||
@ -74,7 +76,7 @@ public class ReportCardService {
|
|||||||
for (AbstractLesson lesson : lessons) {
|
for (AbstractLesson lesson : lessons) {
|
||||||
LessonTracker lessonTracker = userTracker.getLessonTracker(lesson);
|
LessonTracker lessonTracker = userTracker.getLessonTracker(lesson);
|
||||||
LessonStatistics lessonStatistics = new LessonStatistics();
|
LessonStatistics lessonStatistics = new LessonStatistics();
|
||||||
lessonStatistics.setName(lesson.getTitle());
|
lessonStatistics.setName(pluginMessages.getMessage(lesson.getTitle()));
|
||||||
lessonStatistics.setNumberOfAttempts(lessonTracker.getNumberOfAttempts());
|
lessonStatistics.setNumberOfAttempts(lessonTracker.getNumberOfAttempts());
|
||||||
lessonStatistics.setSolved(lessonTracker.isLessonSolved());
|
lessonStatistics.setSolved(lessonTracker.isLessonSolved());
|
||||||
reportCard.lessonStatistics.add(lessonStatistics);
|
reportCard.lessonStatistics.add(lessonStatistics);
|
||||||
|
@ -59,7 +59,7 @@ public class RestartLessonService {
|
|||||||
AbstractLesson al = webSession.getCurrentLesson();
|
AbstractLesson al = webSession.getCurrentLesson();
|
||||||
log.debug("Restarting lesson: " + al);
|
log.debug("Restarting lesson: " + al);
|
||||||
|
|
||||||
UserTracker userTracker = userTrackerRepository.findOne(webSession.getUserName());
|
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||||
userTracker.reset(al);
|
userTracker.reset(al);
|
||||||
userTrackerRepository.save(userTracker);
|
userTrackerRepository.save(userTracker);
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,39 @@ public class CreateDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of the Method
|
||||||
|
*
|
||||||
|
* @param connection Description of the Parameter
|
||||||
|
* @throws SQLException Description of the Exception
|
||||||
|
*/
|
||||||
|
private void createJWTKeys(Connection connection) throws SQLException {
|
||||||
|
Statement statement = connection.createStatement();
|
||||||
|
|
||||||
|
// Drop servers table
|
||||||
|
try {
|
||||||
|
String dropTable = "DROP TABLE jwt_keys";
|
||||||
|
statement.executeUpdate(dropTable);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
System.out.println("Info - Could not drop jwtkeys table");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the new table
|
||||||
|
try {
|
||||||
|
String createTableStatement = "CREATE TABLE jwt_keys"
|
||||||
|
+ " (" + "id varchar(20),"
|
||||||
|
+ "key varchar(20))";
|
||||||
|
statement.executeUpdate(createTableStatement);
|
||||||
|
|
||||||
|
String insertData1 = "INSERT INTO jwt_keys VALUES ('webgoat_key', 'qwertyqwerty1234')";
|
||||||
|
String insertData2 = "INSERT INTO jwt_keys VALUES ('webwolf_key', 'doesnotreallymatter')";
|
||||||
|
statement.executeUpdate(insertData1);
|
||||||
|
statement.executeUpdate(insertData2);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
System.out.println("Error creating product table " + e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description of the Method
|
* Description of the Method
|
||||||
@ -975,6 +1008,7 @@ public class CreateDB {
|
|||||||
createTanTable(connection);
|
createTanTable(connection);
|
||||||
createMFEImagesTable(connection);
|
createMFEImagesTable(connection);
|
||||||
createModifyWithSQLLessonTable(connection);
|
createModifyWithSQLLessonTable(connection);
|
||||||
|
createJWTKeys(connection);
|
||||||
System.out.println("Success: creating tables.");
|
System.out.println("Success: creating tables.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,13 +47,16 @@ import java.util.stream.Collectors;
|
|||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
public class LessonTracker {
|
public class LessonTracker {
|
||||||
@Getter
|
|
||||||
@Id
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
@Getter
|
||||||
private String lessonName;
|
private String lessonName;
|
||||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||||
private final Set<Assignment> solvedAssignments = Sets.newHashSet();
|
private final Set<Assignment> solvedAssignments = Sets.newHashSet();
|
||||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||||
private final List<Assignment> allAssignments = Lists.newArrayList();
|
private final Set<Assignment> allAssignments = Sets.newHashSet();
|
||||||
@Getter
|
@Getter
|
||||||
private int numberOfAttempts = 0;
|
private int numberOfAttempts = 0;
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ public class Scoreboard {
|
|||||||
List<WebGoatUser> allUsers = userRepository.findAll();
|
List<WebGoatUser> allUsers = userRepository.findAll();
|
||||||
List<Ranking> rankings = Lists.newArrayList();
|
List<Ranking> rankings = Lists.newArrayList();
|
||||||
for (WebGoatUser user : allUsers) {
|
for (WebGoatUser user : allUsers) {
|
||||||
UserTracker userTracker = userTrackerRepository.findOne(user.getUsername());
|
UserTracker userTracker = userTrackerRepository.findByUser(user.getUsername());
|
||||||
rankings.add(new Ranking(user.getUsername(), challengesSolved(userTracker)));
|
rankings.add(new Ranking(user.getUsername(), challengesSolved(userTracker)));
|
||||||
}
|
}
|
||||||
return rankings;
|
return rankings;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
package org.owasp.webgoat.users;
|
package org.owasp.webgoat.users;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||||
import org.owasp.webgoat.lessons.Assignment;
|
import org.owasp.webgoat.lessons.Assignment;
|
||||||
@ -10,6 +11,7 @@ import javax.persistence.*;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
@ -48,9 +50,12 @@ import java.util.stream.Collectors;
|
|||||||
public class UserTracker {
|
public class UserTracker {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
@Column(name = "username")
|
||||||
private String user;
|
private String user;
|
||||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||||
private List<LessonTracker> lessonTrackers = Lists.newArrayList();
|
private Set<LessonTracker> lessonTrackers = Sets.newHashSet();
|
||||||
|
|
||||||
private UserTracker() {}
|
private UserTracker() {}
|
||||||
|
|
||||||
|
@ -8,5 +8,6 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
|||||||
*/
|
*/
|
||||||
public interface UserTrackerRepository extends JpaRepository<UserTracker, String> {
|
public interface UserTrackerRepository extends JpaRepository<UserTracker, String> {
|
||||||
|
|
||||||
|
UserTracker findByUser(String user);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,16 @@ server.error.path=/error.html
|
|||||||
server.session.timeout=600
|
server.session.timeout=600
|
||||||
server.contextPath=/WebGoat
|
server.contextPath=/WebGoat
|
||||||
server.port=8080
|
server.port=8080
|
||||||
|
server.address=127.0.0.1
|
||||||
|
|
||||||
spring.datasource.url=jdbc:hsqldb:file:${webgoat.server.directory}/data/webgoat
|
spring.datasource.url=jdbc:hsqldb:hsql://localhost:9001/webgoat
|
||||||
spring.jpa.hibernate.ddl-auto=update
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect
|
||||||
|
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
|
||||||
|
|
||||||
|
|
||||||
logging.level.org.springframework=WARN
|
logging.level.org.springframework=INFO
|
||||||
logging.level.org.springframework.boot.devtools=WARN
|
logging.level.org.springframework.boot.devtools=INFO
|
||||||
logging.level.org.owasp=DEBUG
|
logging.level.org.owasp=DEBUG
|
||||||
logging.level.org.owasp.webgoat=TRACE
|
logging.level.org.owasp.webgoat=TRACE
|
||||||
|
|
||||||
@ -19,9 +22,10 @@ security.enable-csrf=false
|
|||||||
spring.resources.cache-period=0
|
spring.resources.cache-period=0
|
||||||
spring.thymeleaf.cache=false
|
spring.thymeleaf.cache=false
|
||||||
|
|
||||||
|
webgoat.start.hsqldb=true
|
||||||
webgoat.clean=false
|
webgoat.clean=false
|
||||||
webgoat.server.directory=${user.home}/.webgoat/
|
webgoat.server.directory=${user.home}/.webgoat-${webgoat.build.version}/
|
||||||
webgoat.user.directory=${user.home}/.webgoat/
|
webgoat.user.directory=${user.home}/.webgoat-${webgoat.build.version}/
|
||||||
webgoat.build.version=@project.version@
|
webgoat.build.version=@project.version@
|
||||||
webgoat.build.number=@build.number@
|
webgoat.build.number=@build.number@
|
||||||
webgoat.email=webgoat@owasp.org
|
webgoat.email=webgoat@owasp.org
|
||||||
@ -35,7 +39,7 @@ webgoat.default.language=en
|
|||||||
webwolf.host=${WEBWOLF_HOST:localhost}
|
webwolf.host=${WEBWOLF_HOST:localhost}
|
||||||
webwolf.port=${WEBWOLF_PORT:8081}
|
webwolf.port=${WEBWOLF_PORT:8081}
|
||||||
webwolf.url=http://${webwolf.host}:${webwolf.port}/WebWolf
|
webwolf.url=http://${webwolf.host}:${webwolf.port}/WebWolf
|
||||||
webworf.url.landingpage=http://${webwolf.host}:${webwolf.port}/landing
|
webwolf.url.landingpage=http://${webwolf.host}:${webwolf.port}/landing
|
||||||
webwolf.url.mail=http://${webwolf.host}:${webwolf.port}/mail
|
webwolf.url.mail=http://${webwolf.host}:${webwolf.port}/mail
|
||||||
|
|
||||||
spring.jackson.serialization.indent_output=true
|
spring.jackson.serialization.indent_output=true
|
||||||
|
@ -1066,6 +1066,7 @@ span.show-next-page, span.show-prev-page {
|
|||||||
|
|
||||||
/* ATTACK DISPLAY */
|
/* ATTACK DISPLAY */
|
||||||
.attack-container {
|
.attack-container {
|
||||||
|
position: relative;
|
||||||
background-color: #f1f1f1;
|
background-color: #f1f1f1;
|
||||||
border: 2px solid #a66;
|
border: 2px solid #a66;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
@ -1151,3 +1152,15 @@ div.captured-flag {
|
|||||||
width: 1268px;
|
width: 1268px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
position:relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.webwolf-enabled {
|
||||||
|
position:absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 25px;
|
||||||
|
width: 42px;
|
||||||
|
height: 47px;
|
||||||
|
}
|
@ -73,6 +73,7 @@ define(['jquery',
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.loadLesson = function(name,pageNum) {
|
this.loadLesson = function(name,pageNum) {
|
||||||
|
|
||||||
if (this.name === name) {
|
if (this.name === name) {
|
||||||
this.listenToOnce(this.lessonHintView, 'hints:showButton', this.onShowHintsButton);
|
this.listenToOnce(this.lessonHintView, 'hints:showButton', this.onShowHintsButton);
|
||||||
this.listenTo(this.lessonHintView, 'hints:hideButton', this.onHideHintsButton);
|
this.listenTo(this.lessonHintView, 'hints:hideButton', this.onHideHintsButton);
|
||||||
@ -83,15 +84,15 @@ define(['jquery',
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pageNum && !this.name) {
|
||||||
|
//placeholder
|
||||||
|
}
|
||||||
|
|
||||||
this.helpsLoaded = {};
|
this.helpsLoaded = {};
|
||||||
if (typeof(name) === 'undefined' || name === null) {
|
if (typeof(name) === 'undefined' || name === null) {
|
||||||
//TODO: implement lesson not found or return to welcome page?
|
//TODO: implement lesson not found or return to welcome page?
|
||||||
}
|
}
|
||||||
this.lessonContent.loadData({'name':name});
|
this.lessonContent.loadData({'name':name});
|
||||||
// this.planView = {};
|
|
||||||
// this.solutionView = {};
|
|
||||||
// this.sourceView = {};
|
|
||||||
// this.lessonHintView = {};
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -124,15 +125,8 @@ define(['jquery',
|
|||||||
this.helpControlsView = null;
|
this.helpControlsView = null;
|
||||||
this.lessonContentView.model = this.lessonContent;
|
this.lessonContentView.model = this.lessonContent;
|
||||||
this.lessonContentView.render();
|
this.lessonContentView.render();
|
||||||
|
//TODO: consider moving hintView as child of lessonContentView ...
|
||||||
//this.planView = new PlanView();
|
this.createLessonHintView();
|
||||||
//this.solutionView = new SolutionView();
|
|
||||||
//this.sourceView = new SourceView();
|
|
||||||
if (this.lessonHintView) {
|
|
||||||
this.lessonHintView.stopListening();
|
|
||||||
this.lessonHintView = null;
|
|
||||||
}
|
|
||||||
this.lessonHintView = new HintView();
|
|
||||||
|
|
||||||
//TODO: instantiate model with values (not sure why was not working before)
|
//TODO: instantiate model with values (not sure why was not working before)
|
||||||
var paramModel = new ParamModel({});
|
var paramModel = new ParamModel({});
|
||||||
@ -148,40 +142,23 @@ define(['jquery',
|
|||||||
this.lessonProgressModel.completed();
|
this.lessonProgressModel.completed();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.createLessonHintView = function () {
|
||||||
|
if (this.lessonHintView) {
|
||||||
|
this.lessonHintView.stopListening();
|
||||||
|
this.lessonHintView = null;
|
||||||
|
}
|
||||||
|
this.lessonHintView = new HintView();
|
||||||
|
}
|
||||||
|
|
||||||
this.addCurHelpState = function (curHelp) {
|
this.addCurHelpState = function (curHelp) {
|
||||||
this.helpsLoaded[curHelp.helpElement] = curHelp.value;
|
this.helpsLoaded[curHelp.helpElement] = curHelp.value;
|
||||||
};
|
};
|
||||||
|
|
||||||
// this.hideShowHelps = function(showHelp) {
|
|
||||||
// var showId = '#lesson-' + showHelp + '-row';
|
|
||||||
// var contentId = '#lesson-' + showHelp + '-content';
|
|
||||||
// $('.lesson-help').not(showId).hide();
|
|
||||||
// if (!showId) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($(showId).is(':visible')) {
|
|
||||||
// $(showId).hide();
|
|
||||||
// return;
|
|
||||||
// } else {
|
|
||||||
// //TODO: move individual .html operations into individual help views
|
|
||||||
// switch(showHelp) {
|
|
||||||
// case 'plan':
|
|
||||||
// $(contentId).html(this.planView.model.get('content'));
|
|
||||||
// break;
|
|
||||||
// case 'solution':
|
|
||||||
// $(showId).html(this.solutionView.model.get('content'));
|
|
||||||
// break;
|
|
||||||
// case 'source':
|
|
||||||
// $(contentId).html('<pre>' + this.sourceView.model.get('content') + '</pre>');
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// $(showId).show();
|
|
||||||
// GoatUtils.scrollToHelp()
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
this.showHintsView = function() {
|
this.showHintsView = function() {
|
||||||
|
if (!this.lessonHintView) {
|
||||||
|
this.createLessonHintView();
|
||||||
|
}
|
||||||
|
//
|
||||||
this.lessonHintView.render();
|
this.lessonHintView.render();
|
||||||
if (this.lessonHintView.getHintsCount > 0) {
|
if (this.lessonHintView.getHintsCount > 0) {
|
||||||
this.helpControlsView.showHintsButton();
|
this.helpControlsView.showHintsButton();
|
||||||
|
@ -1,29 +1,33 @@
|
|||||||
define(['jquery',
|
define(['jquery',
|
||||||
'underscore',
|
'underscore',
|
||||||
'backbone',
|
'backbone',
|
||||||
'goatApp/model/MenuModel'],
|
'goatApp/model/MenuModel'],
|
||||||
function($,_,Backbone,MenuModel) {
|
function ($, _, Backbone, MenuModel) {
|
||||||
|
|
||||||
return Backbone.Collection.extend({
|
return Backbone.Collection.extend({
|
||||||
model: MenuModel,
|
model: MenuModel,
|
||||||
url:'service/lessonmenu.mvc',
|
url: 'service/lessonmenu.mvc',
|
||||||
initialize: function () {
|
|
||||||
var self = this;
|
|
||||||
this.fetch();
|
|
||||||
},
|
|
||||||
|
|
||||||
onDataLoaded: function() {
|
initialize: function () {
|
||||||
this.trigger('menuData:loaded');
|
var self = this;
|
||||||
},
|
this.fetch();
|
||||||
|
setInterval(function () {
|
||||||
|
this.fetch()
|
||||||
|
}.bind(this), 5000);
|
||||||
|
},
|
||||||
|
|
||||||
fetch: function() {
|
onDataLoaded: function () {
|
||||||
var self=this;
|
this.trigger('menuData:loaded');
|
||||||
Backbone.Collection.prototype.fetch.apply(this,arguments).then(
|
},
|
||||||
function(data) {
|
|
||||||
this.models = data;
|
fetch: function () {
|
||||||
self.onDataLoaded();
|
var self = this;
|
||||||
}
|
Backbone.Collection.prototype.fetch.apply(this, arguments).then(
|
||||||
);
|
function (data) {
|
||||||
}
|
this.models = data;
|
||||||
});
|
self.onDataLoaded();
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
@ -67,7 +67,7 @@ define(['jquery',
|
|||||||
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
|
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
//devs leave stuff like this in all the time
|
//devs leave stuff like this in all the time
|
||||||
console.log('phone home said ' + data);
|
console.log('phone home said ' + JSON.stringify(data));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,9 @@ define(['jquery',
|
|||||||
self.navToPage(page);
|
self.navToPage(page);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
setInterval(function () {
|
||||||
|
this.updatePagination();
|
||||||
|
}.bind(this), 5000);
|
||||||
},
|
},
|
||||||
|
|
||||||
findPage: function(assignment) {
|
findPage: function(assignment) {
|
||||||
@ -56,11 +59,13 @@ define(['jquery',
|
|||||||
var currentPage = (!isNaN(startPageNum) && startPageNum && startPageNum < this.$contentPages) ? startPageNum : 0;
|
var currentPage = (!isNaN(startPageNum) && startPageNum && startPageNum < this.$contentPages) ? startPageNum : 0;
|
||||||
//init views & pagination
|
//init views & pagination
|
||||||
this.showCurContentPage(currentPage);
|
this.showCurContentPage(currentPage);
|
||||||
this.paginationControlView = new PaginationControlView(this.$contentPages,this.model.get('lessonUrl'));
|
this.paginationControlView = new PaginationControlView(this.$contentPages,this.model.get('lessonUrl'),startPageNum);
|
||||||
},
|
},
|
||||||
|
|
||||||
updatePagination: function() {
|
updatePagination: function() {
|
||||||
this.paginationControlView.updateCollection();
|
if ( this.paginationControlView != undefined ) {
|
||||||
|
this.paginationControlView.updateCollection();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getCurrentPage: function () {
|
getCurrentPage: function () {
|
||||||
@ -85,6 +90,8 @@ define(['jquery',
|
|||||||
var prepareDataFunctionName = $(curForm).attr('prepareData');
|
var prepareDataFunctionName = $(curForm).attr('prepareData');
|
||||||
var callbackFunctionName = $(curForm).attr('callback');
|
var callbackFunctionName = $(curForm).attr('callback');
|
||||||
var submitData = (typeof webgoat.customjs[prepareDataFunctionName] === 'function') ? webgoat.customjs[prepareDataFunctionName]() : $(curForm).serialize();
|
var submitData = (typeof webgoat.customjs[prepareDataFunctionName] === 'function') ? webgoat.customjs[prepareDataFunctionName]() : $(curForm).serialize();
|
||||||
|
var additionalHeadersFunctionName = $(curForm).attr('additionalHeaders');
|
||||||
|
var additionalHeaders = (typeof webgoat.customjs[additionalHeadersFunctionName] === 'function') ? webgoat.customjs[additionalHeadersFunctionName]() : function() {};
|
||||||
var successCallBackFunctionName = $(curForm).attr('successCallback');
|
var successCallBackFunctionName = $(curForm).attr('successCallback');
|
||||||
var failureCallbackFunctionName = $(curForm).attr('failureCallback');
|
var failureCallbackFunctionName = $(curForm).attr('failureCallback');
|
||||||
var callbackFunction = (typeof webgoat.customjs[callbackFunctionName] === 'function') ? webgoat.customjs[callbackFunctionName] : function() {};
|
var callbackFunction = (typeof webgoat.customjs[callbackFunctionName] === 'function') ? webgoat.customjs[callbackFunctionName] : function() {};
|
||||||
@ -99,6 +106,7 @@ define(['jquery',
|
|||||||
$.ajax({
|
$.ajax({
|
||||||
//data:submitData,
|
//data:submitData,
|
||||||
url:formUrl,
|
url:formUrl,
|
||||||
|
headers: additionalHeaders,
|
||||||
method:formMethod,
|
method:formMethod,
|
||||||
contentType:contentType,
|
contentType:contentType,
|
||||||
data: submitData,
|
data: submitData,
|
||||||
@ -146,14 +154,23 @@ define(['jquery',
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
removeSlashesFromJSON: function(str) {
|
||||||
|
// slashes are leftover escapes from JSON serialization by server
|
||||||
|
// for every two char sequence starting with backslash,
|
||||||
|
// replace them in the text with second char only
|
||||||
|
return str.replace(/\\(.)/g, "$1");
|
||||||
|
},
|
||||||
|
|
||||||
renderFeedback: function(feedback) {
|
renderFeedback: function(feedback) {
|
||||||
this.$curFeedback.html(polyglot.t(feedback) || "");
|
var s = this.removeSlashesFromJSON(feedback);
|
||||||
|
this.$curFeedback.html(polyglot.t(s) || "");
|
||||||
this.$curFeedback.show(400)
|
this.$curFeedback.show(400)
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
renderOutput: function(output) {
|
renderOutput: function(output) {
|
||||||
this.$curOutput.html(polyglot.t(output) || "");
|
var s = this.removeSlashesFromJSON(output);
|
||||||
|
this.$curOutput.html(polyglot.t(s) || "");
|
||||||
this.$curOutput.show(400)
|
this.$curOutput.show(400)
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -173,13 +190,19 @@ define(['jquery',
|
|||||||
return endpoints;
|
return endpoints;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onNavToPage: function(pageNum) {
|
||||||
|
var assignmentPaths = this.findAssigmentEndpointsOnPage(pageNum);
|
||||||
|
this.trigger('endpoints:filtered',assignmentPaths);
|
||||||
|
},
|
||||||
|
|
||||||
navToPage: function (pageNum) {
|
navToPage: function (pageNum) {
|
||||||
this.paginationControlView.setCurrentPage(pageNum);//provides validation
|
this.paginationControlView.setCurrentPage(pageNum);//provides validation
|
||||||
this.showCurContentPage(this.paginationControlView.currentPage);
|
this.showCurContentPage(this.paginationControlView.currentPage);
|
||||||
this.paginationControlView.render();
|
this.paginationControlView.render();
|
||||||
this.paginationControlView.hideShowNavButtons();
|
this.paginationControlView.hideShowNavButtons();
|
||||||
var assignmentPaths = this.findAssigmentEndpointsOnPage(pageNum);
|
this.onNavToPage(pageNum);
|
||||||
this.trigger('endpoints:filtered',assignmentPaths);
|
//var assignmentPaths = this.findAssigmentEndpointsOnPage(pageNum);
|
||||||
|
//this.trigger('endpoints:filtered',assignmentPaths);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* for testing */
|
/* for testing */
|
||||||
|
@ -12,14 +12,14 @@ define(['jquery',
|
|||||||
template: PaginationTemplate,
|
template: PaginationTemplate,
|
||||||
el: '#lesson-page-controls',
|
el: '#lesson-page-controls',
|
||||||
|
|
||||||
initialize: function ($contentPages,baseLessonUrl) {
|
initialize: function ($contentPages,baseLessonUrl,initPageNum) {
|
||||||
this.$contentPages = $contentPages;
|
this.$contentPages = $contentPages;
|
||||||
this.collection = new LessonOverviewCollection();
|
this.collection = new LessonOverviewCollection();
|
||||||
this.listenTo(this.collection, 'reset', this.render);
|
this.listenTo(this.collection, 'reset', this.render);
|
||||||
this.numPages = this.$contentPages.length;
|
this.numPages = this.$contentPages.length;
|
||||||
this.baseUrl = baseLessonUrl;
|
this.baseUrl = baseLessonUrl;
|
||||||
this.collection.fetch({reset:true});
|
this.collection.fetch({reset:true});
|
||||||
this.initPagination();
|
this.initPagination(initPageNum);
|
||||||
//this.render();
|
//this.render();
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -117,9 +117,9 @@ define(['jquery',
|
|||||||
$('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-right.show-next-page').hide();
|
$('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-right.show-next-page').hide();
|
||||||
},
|
},
|
||||||
|
|
||||||
initPagination: function() {
|
initPagination: function(initPageNum) {
|
||||||
//track pagination state in this view ... start at 0
|
//track pagination state in this view ... start at 0 .. unless a pageNum was provided
|
||||||
this.currentPage = 0;
|
this.currentPage = !initPageNum ? 0 : initPageNum;
|
||||||
},
|
},
|
||||||
|
|
||||||
setCurrentPage: function (pageNum) {
|
setCurrentPage: function (pageNum) {
|
||||||
|
@ -30,7 +30,7 @@ require.config({
|
|||||||
shim: {
|
shim: {
|
||||||
"jqueryui": {
|
"jqueryui": {
|
||||||
exports:"$",
|
exports:"$",
|
||||||
deps: ['jquery']
|
deps: ['libs/jquery-2.1.4.min']
|
||||||
},
|
},
|
||||||
underscore: {
|
underscore: {
|
||||||
exports: "_"
|
exports: "_"
|
||||||
|
@ -76,24 +76,25 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li role="presentation" class="divider"></li>
|
<li role="presentation" class="divider"></li>
|
||||||
<li role="presentation" class="disabled"><a role="menuitem" tabindex="-1" href="#"
|
<li role="presentation" class="disabled"><a role="menuitem" tabindex="-1" href="#">
|
||||||
th:text="#{version}">Version: <span
|
<span th:text="#{version}">Version:</span><span>: </span>
|
||||||
th:text="${@environment.getProperty('webgoat.build.version')}"></span></a>
|
<span th:text="${@environment.getProperty('webgoat.build.version')}"></span></a>
|
||||||
</li>
|
</li>
|
||||||
<li role="presentation" class="disabled"><a role="menuitem" tabindex="-1" href="#"
|
<li role="presentation" class="disabled"><a role="menuitem" tabindex="-1" href="#">
|
||||||
th:text="#{build}">Build:
|
<span th:text="#{build}">Build:</span><span>: </span>
|
||||||
<span th:text="${@environment.getProperty('webgoat.build.number')}"></span></a></li>
|
<span th:text="${@environment.getProperty('webgoat.build.number')}"></span></a></li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div style="display:inline" id="settings">
|
<div style="display:inline" id="settings">
|
||||||
<!--<button type="button" id="admin-button" class="btn btn-default right_nav_button" title="Administrator">-->
|
<!--<button type="button" id="admin-button" class="btn btn-default right_nav_button" title="Administrator">-->
|
||||||
<!--<i class="fa fa-cog"></i>-->
|
<!--<i class="fa fa-cog"></i>-->
|
||||||
<!--</button>-->
|
<!--</button>-->
|
||||||
<button type="button" id="report-card-button" class="btn btn-default right_nav_button button-up"
|
<a href="#reportCard">
|
||||||
th:title="#{report.card}">
|
<button type="button" id="report-card-button" class="btn btn-default right_nav_button button-up"
|
||||||
<a href="#reportCard"><i class="fa fa-bar-chart-o"></i></a>
|
th:title="#{report.card}">
|
||||||
</button>
|
<i class="fa fa-bar-chart-o"></i>
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
<!--<button type="button" id="user-management" class="btn btn-default right_nav_button"-->
|
<!--<button type="button" id="user-management" class="btn btn-default right_nav_button"-->
|
||||||
<!--title="User management">-->
|
<!--title="User management">-->
|
||||||
<!--<i class="fa fa-users"></i>-->
|
<!--<i class="fa fa-users"></i>-->
|
||||||
|
@ -62,7 +62,7 @@ public class AssignmentEndpointTest {
|
|||||||
|
|
||||||
public void init(AssignmentEndpoint a) {
|
public void init(AssignmentEndpoint a) {
|
||||||
messages.setBasenames("classpath:/i18n/messages", "classpath:/i18n/WebGoatLabels");
|
messages.setBasenames("classpath:/i18n/messages", "classpath:/i18n/WebGoatLabels");
|
||||||
when(userTrackerRepository.findOne(anyString())).thenReturn(userTracker);
|
when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
|
||||||
ReflectionTestUtils.setField(a, "userTrackerRepository", userTrackerRepository);
|
ReflectionTestUtils.setField(a, "userTrackerRepository", userTrackerRepository);
|
||||||
ReflectionTestUtils.setField(a, "userSessionData", userSessionData);
|
ReflectionTestUtils.setField(a, "userSessionData", userSessionData);
|
||||||
ReflectionTestUtils.setField(a, "webSession", webSession);
|
ReflectionTestUtils.setField(a, "webSession", webSession);
|
||||||
|
@ -63,7 +63,7 @@ public class LessonMenuServiceTest {
|
|||||||
when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1, l2));
|
when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1, l2));
|
||||||
when(course.getCategories()).thenReturn(Lists.newArrayList(Category.ACCESS_CONTROL));
|
when(course.getCategories()).thenReturn(Lists.newArrayList(Category.ACCESS_CONTROL));
|
||||||
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
|
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
|
||||||
when(userTrackerRepository.findOne(anyString())).thenReturn(userTracker);
|
when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
|
||||||
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.get(URL_LESSONMENU_MVC))
|
mockMvc.perform(MockMvcRequestBuilders.get(URL_LESSONMENU_MVC))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
@ -81,7 +81,7 @@ public class LessonMenuServiceTest {
|
|||||||
when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1));
|
when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1));
|
||||||
when(course.getCategories()).thenReturn(Lists.newArrayList(Category.ACCESS_CONTROL));
|
when(course.getCategories()).thenReturn(Lists.newArrayList(Category.ACCESS_CONTROL));
|
||||||
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
|
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
|
||||||
when(userTrackerRepository.findOne(anyString())).thenReturn(userTracker);
|
when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
|
||||||
|
|
||||||
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.get(URL_LESSONMENU_MVC))
|
mockMvc.perform(MockMvcRequestBuilders.get(URL_LESSONMENU_MVC))
|
||||||
|
@ -72,7 +72,7 @@ public class LessonProgressServiceTest {
|
|||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
Assignment assignment = new Assignment("test", "test");
|
Assignment assignment = new Assignment("test", "test");
|
||||||
when(userTrackerRepository.findOne(anyString())).thenReturn(userTracker);
|
when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
|
||||||
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
|
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
|
||||||
when(websession.getCurrentLesson()).thenReturn(lesson);
|
when(websession.getCurrentLesson()).thenReturn(lesson);
|
||||||
when(lessonTracker.getLessonOverview()).thenReturn(Maps.newHashMap(assignment, true));
|
when(lessonTracker.getLessonOverview()).thenReturn(Maps.newHashMap(assignment, true));
|
||||||
|
@ -6,6 +6,7 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.runners.MockitoJUnitRunner;
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
import org.owasp.webgoat.i18n.PluginMessages;
|
||||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||||
import org.owasp.webgoat.session.Course;
|
import org.owasp.webgoat.session.Course;
|
||||||
import org.owasp.webgoat.session.WebSession;
|
import org.owasp.webgoat.session.WebSession;
|
||||||
@ -40,10 +41,13 @@ public class ReportCardServiceTest {
|
|||||||
private UserTrackerRepository userTrackerRepository;
|
private UserTrackerRepository userTrackerRepository;
|
||||||
@Mock
|
@Mock
|
||||||
private WebSession websession;
|
private WebSession websession;
|
||||||
|
@Mock
|
||||||
|
private PluginMessages pluginMessages;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
this.mockMvc = standaloneSetup(new ReportCardService(websession, userTrackerRepository, course)).build();
|
this.mockMvc = standaloneSetup(new ReportCardService(websession, userTrackerRepository, course, pluginMessages)).build();
|
||||||
|
when(pluginMessages.getMessage(anyString())).thenReturn("Test");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -53,7 +57,7 @@ public class ReportCardServiceTest {
|
|||||||
when(course.getTotalOfLessons()).thenReturn(1);
|
when(course.getTotalOfLessons()).thenReturn(1);
|
||||||
when(course.getTotalOfAssignments()).thenReturn(10);
|
when(course.getTotalOfAssignments()).thenReturn(10);
|
||||||
when(course.getLessons()).thenReturn(Lists.newArrayList(lesson));
|
when(course.getLessons()).thenReturn(Lists.newArrayList(lesson));
|
||||||
when(userTrackerRepository.findOne(anyString())).thenReturn(userTracker);
|
when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
|
||||||
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
|
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
|
||||||
mockMvc.perform(MockMvcRequestBuilders.get("/service/reportcard.mvc"))
|
mockMvc.perform(MockMvcRequestBuilders.get("/service/reportcard.mvc"))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
|
@ -62,7 +62,7 @@ public class UserTrackerRepositoryTest {
|
|||||||
|
|
||||||
userTrackerRepository.save(userTracker);
|
userTrackerRepository.save(userTracker);
|
||||||
|
|
||||||
userTracker = userTrackerRepository.findOne("test");
|
userTracker = userTrackerRepository.findByUser("test");
|
||||||
Assertions.assertThat(userTracker.getLessonTracker("test")).isNotNull();
|
Assertions.assertThat(userTracker.getLessonTracker("test")).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ public class UserTrackerRepositoryTest {
|
|||||||
|
|
||||||
userTrackerRepository.saveAndFlush(userTracker);
|
userTrackerRepository.saveAndFlush(userTracker);
|
||||||
|
|
||||||
userTracker = userTrackerRepository.findOne("test");
|
userTracker = userTrackerRepository.findByUser("test");
|
||||||
Assertions.assertThat(userTracker.numberOfAssignmentsSolved()).isEqualTo(1);
|
Assertions.assertThat(userTracker.numberOfAssignmentsSolved()).isEqualTo(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ public class UserTrackerRepositoryTest {
|
|||||||
userTracker.assignmentFailed(lesson);
|
userTracker.assignmentFailed(lesson);
|
||||||
userTrackerRepository.saveAndFlush(userTracker);
|
userTrackerRepository.saveAndFlush(userTracker);
|
||||||
|
|
||||||
userTracker = userTrackerRepository.findOne("test");
|
userTracker = userTrackerRepository.findByUser("test");
|
||||||
userTracker.assignmentFailed(lesson);
|
userTracker.assignmentFailed(lesson);
|
||||||
userTracker.assignmentFailed(lesson);
|
userTracker.assignmentFailed(lesson);
|
||||||
userTrackerRepository.saveAndFlush(userTracker);
|
userTrackerRepository.saveAndFlush(userTracker);
|
||||||
|
@ -1 +1,15 @@
|
|||||||
<configuration />
|
<configuration />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Enable below if you want to debug a unit test and see why the controller fails the configuration above is there
|
||||||
|
to keep the Travis build going otherwise it fails with too much logging.
|
||||||
|
//TODO we should use a different Spring profile for Travis
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<configuration>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||||
|
<logger name="org.springframework.web" level="DEBUG"/>
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
-->
|
32
webgoat-images/vagrant-developers/Vagrantfile
vendored
32
webgoat-images/vagrant-developers/Vagrantfile
vendored
@ -1,32 +0,0 @@
|
|||||||
Vagrant.configure(2) do |config|
|
|
||||||
config.vm.box = "boxcutter/ubuntu1604-desktop"
|
|
||||||
|
|
||||||
|
|
||||||
config.vm.provider "virtualbox" do |vb|
|
|
||||||
vb.gui = true
|
|
||||||
vb.memory = "4096"
|
|
||||||
vb.cpus = 2
|
|
||||||
vb.name = "WebGoat-Development"
|
|
||||||
vb.customize ["modifyvm", :id, "--nictype1", "virtio"]
|
|
||||||
end
|
|
||||||
|
|
||||||
config.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'"
|
|
||||||
|
|
||||||
config.vm.provision 'shell' do |s|
|
|
||||||
s.path = '../vagrant_provision.sh'
|
|
||||||
s.privileged = true
|
|
||||||
end
|
|
||||||
|
|
||||||
config.vm.provision :shell, privileged:false, inline: <<-SHELL
|
|
||||||
echo -e "Cloning the WebGoat container repository"
|
|
||||||
git clone -b master https://github.com/WebGoat/WebGoat.git
|
|
||||||
echo -e "Cloning the WebGoat Lessons repository"
|
|
||||||
git clone -b master https://github.com/WebGoat/WebGoat-Lessons.git
|
|
||||||
SHELL
|
|
||||||
|
|
||||||
config.vm.provision 'shell' do |s|
|
|
||||||
s.inline = "echo Finished provisioning, login with user vagrant pass vagrant"
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
8
webgoat-images/vagrant-training/Vagrantfile
vendored
8
webgoat-images/vagrant-training/Vagrantfile
vendored
@ -19,17 +19,17 @@ Vagrant.configure(2) do |config|
|
|||||||
end
|
end
|
||||||
|
|
||||||
config.vm.provision "shell", inline: <<-SHELL
|
config.vm.provision "shell", inline: <<-SHELL
|
||||||
wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.M5/webgoat-server-8.0.0.M6.jar
|
wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.RELEASE/webgoat-server-8.0.0.RELEASE.jar
|
||||||
wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.M5/webwolf-8.0.0.M6.jar
|
wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.RELEASE/webwolf-8.0.0.RELEASE.jar
|
||||||
sudo add-apt-repository ppa:openjdk-r/ppa
|
sudo add-apt-repository ppa:openjdk-r/ppa
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install openjdk-8-jre -y
|
sudo apt-get install openjdk-8-jre -y
|
||||||
SHELL
|
SHELL
|
||||||
|
|
||||||
config.vm.provision "shell", run: "always", privileged: false, inline: <<-SHELL
|
config.vm.provision "shell", run: "always", privileged: false, inline: <<-SHELL
|
||||||
java -jar webgoat-server-8.0.0.M6.jar &
|
java -jar webgoat-server-8.0.0.RELEASE.jar &
|
||||||
sleep 40s
|
sleep 40s
|
||||||
java -jar webwolf-8.0.0.M6.jar
|
java -jar webwolf-8.0.0.RELEASE.jar
|
||||||
SHELL
|
SHELL
|
||||||
|
|
||||||
end
|
end
|
||||||
|
48
webgoat-images/vagrant-users/Vagrantfile
vendored
48
webgoat-images/vagrant-users/Vagrantfile
vendored
@ -1,48 +0,0 @@
|
|||||||
#For now use the same as for developers but start WebGoat
|
|
||||||
#In the future we can add Docker as well and then Vagrant can start the
|
|
||||||
#Docker container or Chef which setups the Tomcat
|
|
||||||
|
|
||||||
Vagrant.configure(2) do |config|
|
|
||||||
config.vm.box = "boxcutter/ubuntu1604-desktop"
|
|
||||||
config.vm.network :forwarded_port, guest: 8080, host: 9999
|
|
||||||
config.vm.provider "virtualbox" do |vb|
|
|
||||||
vb.gui = false
|
|
||||||
vb.memory = "2048"
|
|
||||||
vb.cpus = 2
|
|
||||||
vb.name = "WebGoat-Users"
|
|
||||||
vb.customize ["modifyvm", :id, "--nictype1", "virtio"]
|
|
||||||
end
|
|
||||||
config.vm.provider "vmware_fusion" do |vf|
|
|
||||||
vf.gui = false
|
|
||||||
vf.vmx["memsize"] = 4096
|
|
||||||
vf.vmx["numvcpus"] = 2
|
|
||||||
vf.vmx["displayname"] = "WebGoat-Users"
|
|
||||||
end
|
|
||||||
|
|
||||||
config.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'"
|
|
||||||
|
|
||||||
config.vm.provision 'shell' do |s|
|
|
||||||
s.path = '../vagrant_provision.sh'
|
|
||||||
s.privileged = true
|
|
||||||
end
|
|
||||||
|
|
||||||
config.vm.provision :shell, inline: <<-SHELL
|
|
||||||
echo -e "Cloning the WebGoat container repository"
|
|
||||||
git clone -b master https://github.com/WebGoat/WebGoat.git
|
|
||||||
echo -e "Cloning the WebGoat Lessons repository"
|
|
||||||
git clone -b master https://github.com/WebGoat/WebGoat-Lessons.git
|
|
||||||
echo -e "Compiling and installing the WebGoat Container lesson server....."
|
|
||||||
mvn -q -DskipTests -file WebGoat/pom.xml clean compile install
|
|
||||||
echo -e "Compiling and installing the WebGoat Lessons $COL_RESET"
|
|
||||||
mvn -q -DskipTests -file WebGoat-Lessons/pom.xml package
|
|
||||||
echo -e "Copying the compiled lessons jars into the container so we can start the lesson server with some base lessons"
|
|
||||||
cp -fa ./WebGoat-Lessons/target/plugins/*.jar ./WebGoat/webgoat-container/src/main/webapp/plugin_lessons/
|
|
||||||
nohup mvn -q -DskipTests -file WebGoat/pom.xml -pl webgoat-container tomcat7:run-war 0<&- &>/dev/null &
|
|
||||||
SHELL
|
|
||||||
|
|
||||||
config.vm.provision 'shell' do |s|
|
|
||||||
s.inline = "echo Finished provisioning, open a browser and browse to http://localhost:9999/WebGoat/"
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "Setting locale..."
|
|
||||||
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
|
|
||||||
|
|
||||||
sudo kill -9 $(lsof -t /var/lib/dpkg/lock) || true
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y git
|
|
||||||
|
|
||||||
echo "Installing required packages..."
|
|
||||||
sudo apt-get install -y -q build-essential autotools-dev automake pkg-config expect
|
|
||||||
|
|
||||||
|
|
||||||
## Chrome
|
|
||||||
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
|
|
||||||
sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y google-chrome-stable
|
|
||||||
|
|
||||||
## Java 8
|
|
||||||
echo "Provisioning Java 8..."
|
|
||||||
mkdir -p /home/vagrant/java
|
|
||||||
cd /home/vagrant/java
|
|
||||||
test -f /tmp/jdk-8-linux-x64.tar.gz || curl -q -L --cookie "oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u144-b01/090f390dda5b47b9b721c7dfaa008135/jdk-8u144-linux-x64.tar.gz -o /tmp/jdk-8-linux-x64.tar.gz
|
|
||||||
|
|
||||||
sudo mkdir -p /usr/lib/jvm
|
|
||||||
sudo tar zxf /tmp/jdk-8-linux-x64.tar.gz -C /usr/lib/jvm
|
|
||||||
|
|
||||||
sudo update-alternatives --install "/usr/bin/java" "java" "/usr/lib/jvm/jdk1.8.0_144/bin/java" 1
|
|
||||||
sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/lib/jvm/jdk1.8.0_144/bin/javac" 1
|
|
||||||
sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/lib/jvm/jdk1.8.0_144/bin/javaws" 1
|
|
||||||
|
|
||||||
sudo chmod a+x /usr/bin/java
|
|
||||||
sudo chmod a+x /usr/bin/javac
|
|
||||||
sudo chmod a+x /usr/bin/javaws
|
|
||||||
sudo chown -R root:root /usr/lib/jvm/jdk1.8.0_144
|
|
||||||
|
|
||||||
echo "export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_144" >> /home/vagrant/.bashrc
|
|
||||||
|
|
||||||
## Maven
|
|
||||||
echo "Installing Maven.."
|
|
||||||
sudo apt-get install -y maven
|
|
||||||
|
|
||||||
## ZAP
|
|
||||||
echo "Provisioning ZAP..."
|
|
||||||
cd /home/vagrant
|
|
||||||
mkdir tools
|
|
||||||
cd tools
|
|
||||||
wget https://github.com/zaproxy/zaproxy/releases/download/2.5.0/ZAP_2.5.0_Linux.tar.gz
|
|
||||||
tar xvfx ZAP_2.5.0_Linux.tar.gz
|
|
||||||
rm -rf ZAP_2.5.0_Linux.tar.gz
|
|
||||||
|
|
||||||
## IntelliJ
|
|
||||||
cd /home/vagrant/tools
|
|
||||||
wget https://download.jetbrains.com/idea/ideaIC-2016.1.4.tar.gz
|
|
||||||
tar xvfz ideaIC-2016.1.4.tar.gz
|
|
||||||
rm -rf ideaIC-2016.1.4.tar.gz
|
|
||||||
|
|
||||||
## Eclipse
|
|
||||||
sudo apt-get -y install eclipse
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp.webgoat.lesson</groupId>
|
<groupId>org.owasp.webgoat.lesson</groupId>
|
||||||
<artifactId>webgoat-lessons-parent</artifactId>
|
<artifactId>webgoat-lessons-parent</artifactId>
|
||||||
<version>8.0.0.M3</version>
|
<version>v8.0.0.M15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
== Authentication Bpasses
|
== Authentication Bypasses
|
||||||
|
|
||||||
Authentication Bypasses happen in many ways, but usually take advantage of some flaw in the configuration or logic. Tampering to achieve the right conditions.
|
Authentication Bypasses happen in many ways, but usually take advantage of some flaw in the configuration or logic. Tampering to achieve the right conditions.
|
||||||
|
|
||||||
@ -12,4 +12,4 @@ Sometimes, if an attacker doesn't know the correct value of a parameter, they ma
|
|||||||
|
|
||||||
=== Forced Browsing
|
=== Forced Browsing
|
||||||
|
|
||||||
If an area of a site is not protected properly by configuation, that area of the site may be accessed by guessing/brute-forcing.
|
If an area of a site is not protected properly by configuration, that area of the site may be accessed by guessing/brute-forcing.
|
||||||
|
@ -6,6 +6,6 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp.webgoat.lesson</groupId>
|
<groupId>org.owasp.webgoat.lesson</groupId>
|
||||||
<artifactId>webgoat-lessons-parent</artifactId>
|
<artifactId>webgoat-lessons-parent</artifactId>
|
||||||
<version>8.0.0.M3</version>
|
<version>v8.0.0.M15</version>
|
||||||
</parent>
|
</parent>
|
||||||
</project>
|
</project>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp.webgoat.lesson</groupId>
|
<groupId>org.owasp.webgoat.lesson</groupId>
|
||||||
<artifactId>webgoat-lessons-parent</artifactId>
|
<artifactId>webgoat-lessons-parent</artifactId>
|
||||||
<version>8.0.0.M3</version>
|
<version>v8.0.0.M15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +46,6 @@ public class Flag extends Endpoint {
|
|||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void initFlags() {
|
public void initFlags() {
|
||||||
IntStream.range(1, 10).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString()));
|
IntStream.range(1, 10).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString()));
|
||||||
FLAGS.entrySet().stream().forEach(e -> log.debug("Flag {} {}", e.getKey(), e.getValue()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -10,11 +10,8 @@ public interface SolutionConstants {
|
|||||||
|
|
||||||
//TODO should be random generated when starting the server
|
//TODO should be random generated when starting the server
|
||||||
String PASSWORD = "!!webgoat_admin_1234!!";
|
String PASSWORD = "!!webgoat_admin_1234!!";
|
||||||
String SUPER_COUPON_CODE = "get_it_for_free";
|
|
||||||
String PASSWORD_TOM = "thisisasecretfortomonly";
|
String PASSWORD_TOM = "thisisasecretfortomonly";
|
||||||
String PASSWORD_LARRY = "larryknows";
|
String PASSWORD_LARRY = "larryknows";
|
||||||
String JWT_PASSWORD = "victory";
|
String JWT_PASSWORD = "victory";
|
||||||
String ADMIN_PASSWORD_LINK = "375afe1104f4a487a73823c50a9292a2";
|
String ADMIN_PASSWORD_LINK = "375afe1104f4a487a73823c50a9292a2";
|
||||||
String PASSWORD_TOM_9 = "somethingVeryRandomWhichNoOneWillEverTypeInAsPasswordForTom";
|
|
||||||
String TOM_EMAIL = "tom@webgoat-cloud.org";
|
|
||||||
}
|
}
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
package org.owasp.webgoat.plugin.challenge9;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import org.owasp.webgoat.lessons.Category;
|
|
||||||
import org.owasp.webgoat.lessons.NewLesson;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author nbaars
|
|
||||||
* @since 3/21/17.
|
|
||||||
*/
|
|
||||||
public class Challenge9 extends NewLesson {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Category getDefaultCategory() {
|
|
||||||
return Category.CHALLENGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getHints() {
|
|
||||||
return Lists.newArrayList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer getDefaultRanking() {
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTitle() {
|
|
||||||
return "challenge9.title";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return "Challenge9";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,112 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
|
|
||||||
<html xmlns:th="http://www.thymeleaf.org">
|
|
||||||
|
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
|
||||||
<div class="adoc-content" th:replace="doc:Challenge_2.adoc"></div>
|
|
||||||
<link rel="stylesheet" type="text/css" th:href="@{/lesson_css/challenge2.css}"/>
|
|
||||||
<script th:src="@{/lesson_js/challenge2.js}" language="JavaScript"></script>
|
|
||||||
<div class="attack-container">
|
|
||||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
|
||||||
|
|
||||||
<div class="container-fluid">
|
|
||||||
<form class="attack-form" accept-charset="UNKNOWN"
|
|
||||||
method="POST" name="form"
|
|
||||||
action="/WebGoat/challenge/2"
|
|
||||||
enctype="application/json;charset=UTF-8">
|
|
||||||
|
|
||||||
<input id="discount" type="hidden" value="0"/>
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
<div class="col-xs-3 item-photo">
|
|
||||||
<img style="max-width:100%;" th:src="@{/images/samsung-black.jpg}"/>
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-5" style="border:0px solid gray">
|
|
||||||
<h3>Samsung Galaxy S8</h3>
|
|
||||||
<h5 style="color:#337ab7"><a href="http://www.samsung.com">Samsung</a> ·
|
|
||||||
<small style="color:#337ab7">(124421 reviews)</small>
|
|
||||||
</h5>
|
|
||||||
|
|
||||||
<h6 class="title-price">
|
|
||||||
<small>PRICE</small>
|
|
||||||
</h6>
|
|
||||||
<h3 style="margin-top:0px;"><span>US $</span><span id="price">899</span></h3>
|
|
||||||
|
|
||||||
<div class="section">
|
|
||||||
<h6 class="title-attr" style="margin-top:15px;">
|
|
||||||
<small>COLOR</small>
|
|
||||||
</h6>
|
|
||||||
<div>
|
|
||||||
<div class="attr" style="width:25px;background:lightgrey;"></div>
|
|
||||||
<div class="attr" style="width:25px;background:black;"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="section" style="padding-bottom:5px;">
|
|
||||||
<h6 class="title-attr">
|
|
||||||
<small>CAPACITY</small>
|
|
||||||
</h6>
|
|
||||||
<div>
|
|
||||||
<div class="attr2">64 GB</div>
|
|
||||||
<div class="attr2">128 GB</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="section" style="padding-bottom:5px;">
|
|
||||||
<h6 class="title-attr">
|
|
||||||
<small>QUANTITY</small>
|
|
||||||
</h6>
|
|
||||||
<div>
|
|
||||||
<div class="btn-minus"><span class="glyphicon glyphicon-minus"></span></div>
|
|
||||||
<input class="quantity" value="1"/>
|
|
||||||
<div class="btn-plus"><span class="glyphicon glyphicon-plus"></span></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section" style="padding-bottom:5px;">
|
|
||||||
<h6 class="title-attr">
|
|
||||||
<small>CHECKOUT CODE</small>
|
|
||||||
</h6>
|
|
||||||
<!--
|
|
||||||
Checkout code: webgoat, owasp, owasp-webgoat
|
|
||||||
-->
|
|
||||||
<input name="checkoutCode" class="checkoutCode" value=""/>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section" style="padding-bottom:20px;">
|
|
||||||
<button type="submit" class="btn btn-success"><span style="margin-right:20px"
|
|
||||||
class="glyphicon glyphicon-shopping-cart"
|
|
||||||
aria-hidden="true"></span>Buy
|
|
||||||
</button>
|
|
||||||
<h6><a href="#"><span class="glyphicon glyphicon-heart-empty"
|
|
||||||
style="cursor:pointer;"></span>
|
|
||||||
Like</a></h6>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="input-group">
|
|
||||||
<div class="input-group-addon"><i class="fa fa-flag-checkered" aria-hidden="true"
|
|
||||||
style="font-size:20px"></i></div>
|
|
||||||
<input type="text" class="form-control" id="flag" name="flag"
|
|
||||||
placeholder="a7179f89-906b-4fec-9d99-f15b796e7208"/>
|
|
||||||
</div>
|
|
||||||
<div class="input-group" style="margin-top: 10px">
|
|
||||||
<button type="submit" class="btn btn-primary">Submit flag</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<div class="attack-feedback"></div>
|
|
||||||
<div class="attack-output"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,109 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html xmlns:th="http://www.thymeleaf.org">
|
|
||||||
|
|
||||||
|
|
||||||
<div class="lesson-page-wrapper">
|
|
||||||
<div class="adoc-content" th:replace="doc:Challenge_9.adoc"></div>
|
|
||||||
<script th:src="@{/lesson_js/challenge9.js}" language="JavaScript"></script>
|
|
||||||
|
|
||||||
<div class="attack-container">
|
|
||||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
|
||||||
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<h4 style="border-bottom: 1px solid #c5c5c5;">
|
|
||||||
<i class="glyphicon glyphicon-user"></i>
|
|
||||||
Account Access
|
|
||||||
</h4>
|
|
||||||
<div style="padding: 20px;" id="form-login">
|
|
||||||
<form id="login-form" class="attack-form" accept-charset="UNKNOWN"
|
|
||||||
method="POST" name="form"
|
|
||||||
action="/WebGoat/challenge/9/login"
|
|
||||||
enctype="application/json;charset=UTF-8" role="form">
|
|
||||||
<fieldset>
|
|
||||||
<div class="form-group input-group">
|
|
||||||
<span class="input-group-addon"> @ </span>
|
|
||||||
<input class="form-control" placeholder="Email" name="email" type="email"
|
|
||||||
required="" autofocus=""/>
|
|
||||||
</div>
|
|
||||||
<div class="form-group input-group">
|
|
||||||
<span class="input-group-addon">
|
|
||||||
<i class="glyphicon glyphicon-lock">
|
|
||||||
</i>
|
|
||||||
</span>
|
|
||||||
<input class="form-control" placeholder="Password" name="password" type="password"
|
|
||||||
value="" required=""/>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<button type="submit" class="btn btn-primary btn-block">
|
|
||||||
Access
|
|
||||||
</button>
|
|
||||||
<p class="help-block">
|
|
||||||
<a class="pull-right text-muted" href="#" id="login">
|
|
||||||
<small>Forgot your password?</small>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div style="display: none;" id="form-login">
|
|
||||||
<h4 class="">
|
|
||||||
Forgot your password?
|
|
||||||
</h4>
|
|
||||||
<form id="login-form" class="attack-form" accept-charset="UNKNOWN"
|
|
||||||
method="POST" name="form"
|
|
||||||
action="/WebGoat/challenge/9/create-password-reset-link"
|
|
||||||
enctype="application/json;charset=UTF-8" role="form">
|
|
||||||
<fieldset>
|
|
||||||
<span class="help-block">
|
|
||||||
Email address you use to log in to your account
|
|
||||||
<br/>
|
|
||||||
We'll send you an email with instructions to choose a new password.
|
|
||||||
</span>
|
|
||||||
<div class="form-group input-group">
|
|
||||||
<span class="input-group-addon">
|
|
||||||
@
|
|
||||||
</span>
|
|
||||||
<input class="form-control" placeholder="Email" name="email" type="email"
|
|
||||||
required=""/>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn btn-primary btn-block" id="btn-login">
|
|
||||||
Continue
|
|
||||||
</button>
|
|
||||||
<p class="help-block">
|
|
||||||
<a class="text-muted" href="#" id="forgot">
|
|
||||||
<small>Account Access</small>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</fieldset>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="input-group">
|
|
||||||
<div class="input-group-addon"><i class="fa fa-flag-checkered" aria-hidden="true"
|
|
||||||
style="font-size:20px"></i></div>
|
|
||||||
<input type="text" class="form-control" id="flag" name="flag"
|
|
||||||
placeholder="a7179f89-906b-4fec-9d99-f15b796e7208"/>
|
|
||||||
</div>
|
|
||||||
<div class="input-group" style="margin-top: 10px">
|
|
||||||
<button type="submit" class="btn btn-primary">Submit flag</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<div class="attack-feedback"></div>
|
|
||||||
<div class="attack-output"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</html>
|
|
@ -22,8 +22,7 @@ challenge.flag.incorrect=Sorry this is not the correct flag, please try again.
|
|||||||
|
|
||||||
ip.address.unknown=IP address unknown, e-mail has been sent.
|
ip.address.unknown=IP address unknown, e-mail has been sent.
|
||||||
|
|
||||||
login_failed=Login failed
|
|
||||||
login_failed.tom=Sorry only Tom can login at the moment
|
|
||||||
|
|
||||||
required4=Missing username or password, please specify both.
|
required4=Missing username or password, please specify both.
|
||||||
user.not.larry=Please try to log in as Larry not {0}.
|
user.not.larry=Please try to log in as Larry not {0}.
|
@ -1,10 +0,0 @@
|
|||||||
$(document).ready(function() {
|
|
||||||
$('#login').click(function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
$('div#form-login').toggle('500');
|
|
||||||
});
|
|
||||||
$('#forgot').click(function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
$('div#form-login').toggle('500');
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,3 +0,0 @@
|
|||||||
Tom always resets his password immediately after receiving the email with the link.
|
|
||||||
Try to reset the password of Tom (tom@webgoat-cloud.org) to your own choice and login as Tom with
|
|
||||||
that password.
|
|
@ -1,49 +0,0 @@
|
|||||||
package org.owasp.webgoat.plugin.challenge2;
|
|
||||||
|
|
||||||
import org.hamcrest.CoreMatchers;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.runners.MockitoJUnitRunner;
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpointTest;
|
|
||||||
import org.owasp.webgoat.plugin.Flag;
|
|
||||||
import org.owasp.webgoat.plugin.SolutionConstants;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
|
||||||
|
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
|
||||||
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author nbaars
|
|
||||||
* @since 5/2/17.
|
|
||||||
*/
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
|
||||||
public class Assignment2Test extends AssignmentEndpointTest {
|
|
||||||
|
|
||||||
private MockMvc mockMvc;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setup() {
|
|
||||||
Assignment2 assignment2 = new Assignment2();
|
|
||||||
init(assignment2);
|
|
||||||
new Flag().initFlags();
|
|
||||||
this.mockMvc = standaloneSetup(assignment2).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void success() throws Exception {
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.post("/challenge/2")
|
|
||||||
.param("checkoutCode", SolutionConstants.SUPER_COUPON_CODE))
|
|
||||||
.andExpect(jsonPath("$.feedback", CoreMatchers.containsString("flag: " + Flag.FLAGS.get(2))))
|
|
||||||
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void wrongCouponCode() throws Exception {
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.post("/challenge/2")
|
|
||||||
.param("checkoutCode", "test"))
|
|
||||||
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.not.solved"))))
|
|
||||||
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp.webgoat.lesson</groupId>
|
<groupId>org.owasp.webgoat.lesson</groupId>
|
||||||
<artifactId>webgoat-lessons-parent</artifactId>
|
<artifactId>webgoat-lessons-parent</artifactId>
|
||||||
<version>8.0.0.M3</version>
|
<version>v8.0.0.M15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -56,7 +56,7 @@ public class ClientSideFiltering extends NewLesson {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return "Client side filtering";
|
return "client.side.filtering.title";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package org.owasp.webgoat.plugin.challenge2;
|
package org.owasp.webgoat.plugin;
|
||||||
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
import org.owasp.webgoat.assignments.AssignmentPath;
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.plugin.Flag;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
@ -11,22 +11,23 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static org.owasp.webgoat.plugin.SolutionConstants.SUPER_COUPON_CODE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author nbaars
|
* @author nbaars
|
||||||
* @since 4/6/17.
|
* @since 4/6/17.
|
||||||
*/
|
*/
|
||||||
@AssignmentPath("/challenge/2")
|
@AssignmentPath("/clientSideFiltering/getItForFree")
|
||||||
public class Assignment2 extends AssignmentEndpoint {
|
@AssignmentHints({"client.side.filtering.free.hint1", "client.side.filtering.free.hint2", "client.side.filtering.free.hint3"})
|
||||||
|
public class ClientSideFilteringFreeAssignment extends AssignmentEndpoint {
|
||||||
|
|
||||||
|
public static final String SUPER_COUPON_CODE = "get_it_for_free";
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.POST)
|
@RequestMapping(method = RequestMethod.POST)
|
||||||
public
|
public
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
AttackResult completed(@RequestParam String checkoutCode) throws IOException {
|
AttackResult completed(@RequestParam String checkoutCode) {
|
||||||
if (SUPER_COUPON_CODE.equals(checkoutCode)) {
|
if (SUPER_COUPON_CODE.equals(checkoutCode)) {
|
||||||
return success().feedback("challenge.solved").feedbackArgs(Flag.FLAGS.get(2)).build();
|
return trackProgress(success().build());
|
||||||
}
|
}
|
||||||
return failed().build();
|
return trackProgress(failed().build());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package org.owasp.webgoat.plugin.challenge2;
|
package org.owasp.webgoat.plugin;
|
||||||
|
|
||||||
import com.beust.jcommander.internal.Lists;
|
import com.beust.jcommander.internal.Lists;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@ -12,21 +12,21 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static org.owasp.webgoat.plugin.SolutionConstants.SUPER_COUPON_CODE;
|
import static org.owasp.webgoat.plugin.ClientSideFilteringFreeAssignment.SUPER_COUPON_CODE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author nbaars
|
* @author nbaars
|
||||||
* @since 4/6/17.
|
* @since 4/6/17.
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("challenge-store")
|
@RequestMapping("/clientSideFiltering/challenge-store")
|
||||||
public class ShopEndpoint {
|
public class ShopEndpoint {
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
private class CheckoutCodes {
|
private class CheckoutCodes {
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private List<CheckoutCode> codes = Lists.newArrayList();
|
private List<CheckoutCode> codes;
|
||||||
|
|
||||||
public Optional<CheckoutCode> get(String code) {
|
public Optional<CheckoutCode> get(String code) {
|
||||||
return codes.stream().filter(c -> c.getCode().equals(code)).findFirst();
|
return codes.stream().filter(c -> c.getCode().equals(code)).findFirst();
|
@ -73,7 +73,96 @@
|
|||||||
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
|
<!-- ... of course, you can move them if you want to, but that will not look consistent to other lessons -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="lesson-page-wrapper">
|
||||||
|
<div class="adoc-content" th:replace="doc:ClientSideFiltering_final.adoc"></div>
|
||||||
|
<link rel="stylesheet" type="text/css" th:href="@{/lesson_css/clientSideFilteringFree.css}"/>
|
||||||
|
<script th:src="@{/lesson_js/clientSideFilteringFree.js}" language="JavaScript"></script>
|
||||||
|
<div class="attack-container">
|
||||||
|
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<form class="attack-form" accept-charset="UNKNOWN"
|
||||||
|
method="POST" name="form"
|
||||||
|
action="/WebGoat/clientSideFiltering/getItForFree"
|
||||||
|
enctype="application/json;charset=UTF-8">
|
||||||
|
|
||||||
|
<input id="discount" type="hidden" value="0"/>
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="col-xs-3 item-photo">
|
||||||
|
<img style="max-width:100%;" th:src="@{/images/samsung-black.jpg}"/>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-5" style="border:0px solid gray">
|
||||||
|
<h3>Samsung Galaxy S8</h3>
|
||||||
|
<h5 style="color:#337ab7"><a href="http://www.samsung.com">Samsung</a> ·
|
||||||
|
<small style="color:#337ab7">(124421 reviews)</small>
|
||||||
|
</h5>
|
||||||
|
|
||||||
|
<h6 class="title-price">
|
||||||
|
<small>PRICE</small>
|
||||||
|
</h6>
|
||||||
|
<h3 style="margin-top:0px;"><span>US $</span><span id="price">899</span></h3>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<h6 class="title-attr" style="margin-top:15px;">
|
||||||
|
<small>COLOR</small>
|
||||||
|
</h6>
|
||||||
|
<div>
|
||||||
|
<div class="attr" style="width:25px;background:lightgrey;"></div>
|
||||||
|
<div class="attr" style="width:25px;background:black;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="section" style="padding-bottom:5px;">
|
||||||
|
<h6 class="title-attr">
|
||||||
|
<small>CAPACITY</small>
|
||||||
|
</h6>
|
||||||
|
<div>
|
||||||
|
<div class="attr2">64 GB</div>
|
||||||
|
<div class="attr2">128 GB</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="section" style="padding-bottom:5px;">
|
||||||
|
<h6 class="title-attr">
|
||||||
|
<small>QUANTITY</small>
|
||||||
|
</h6>
|
||||||
|
<div>
|
||||||
|
<div class="btn-minus"><span class="glyphicon glyphicon-minus"></span></div>
|
||||||
|
<input class="quantity" value="1"/>
|
||||||
|
<div class="btn-plus"><span class="glyphicon glyphicon-plus"></span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section" style="padding-bottom:5px;">
|
||||||
|
<h6 class="title-attr">
|
||||||
|
<small>CHECKOUT CODE</small>
|
||||||
|
</h6>
|
||||||
|
<!--
|
||||||
|
Checkout code: webgoat, owasp, owasp-webgoat
|
||||||
|
-->
|
||||||
|
<input name="checkoutCode" class="checkoutCode" value=""/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section" style="padding-bottom:20px;">
|
||||||
|
<button type="submit" class="btn btn-success"><span style="margin-right:20px"
|
||||||
|
class="glyphicon glyphicon-shopping-cart"
|
||||||
|
aria-hidden="true"></span>Buy
|
||||||
|
</button>
|
||||||
|
<h6><a href="#"><span class="glyphicon glyphicon-heart-empty"
|
||||||
|
style="cursor:pointer;"></span>
|
||||||
|
Like</a></h6>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<div class="attack-feedback"></div>
|
||||||
|
<div class="attack-output"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
client.side.filtering.title=Client side filtering
|
||||||
ClientSideFilteringSelectUser=Select user:
|
ClientSideFilteringSelectUser=Select user:
|
||||||
ClientSideFilteringUserID=User ID
|
ClientSideFilteringUserID=User ID
|
||||||
ClientSideFilteringFirstName=First Name
|
ClientSideFilteringFirstName=First Name
|
||||||
@ -25,3 +26,7 @@ ClientSideFilteringHint10=Stage 2: Your filter operator should look something li
|
|||||||
ClientSideFilteringInstructions1=STAGE 1: You are logged in as Moe Stooge, CSO of Goat Hills Financial. You have access to everyone in the company's information, except the CEO, . Or at least you shouldn't have access to the CEO's information. For this exercise, examine the contents of the page to see what extra information you can find.
|
ClientSideFilteringInstructions1=STAGE 1: You are logged in as Moe Stooge, CSO of Goat Hills Financial. You have access to everyone in the company's information, except the CEO, . Or at least you shouldn't have access to the CEO's information. For this exercise, examine the contents of the page to see what extra information you can find.
|
||||||
ClientSideFilteringInstructions2=STAGE 2: Now, fix the problem. Modify the server to only return results that Moe Stooge is allowed to see.
|
ClientSideFilteringInstructions2=STAGE 2: Now, fix the problem. Modify the server to only return results that Moe Stooge is allowed to see.
|
||||||
ClientSideFiltering.incorrect=This is not the salary from Neville Bartholomew...
|
ClientSideFiltering.incorrect=This is not the salary from Neville Bartholomew...
|
||||||
|
|
||||||
|
client.side.filtering.free.hint1=Look through the webpage inspect the sources etc
|
||||||
|
client.side.filtering.free.hint2=Try to see the flow of request from the page to the backend
|
||||||
|
client.side.fiterling.free.hint3=One of the responses contains the answer
|
||||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
@ -38,7 +38,7 @@ $(document).ready(function () {
|
|||||||
})
|
})
|
||||||
$(".checkoutCode").on("blur", function () {
|
$(".checkoutCode").on("blur", function () {
|
||||||
var checkoutCode = $(".checkoutCode").val();
|
var checkoutCode = $(".checkoutCode").val();
|
||||||
$.get("challenge-store/coupons/" + checkoutCode, function (result, status) {
|
$.get("clientSideFiltering/challenge-store/coupons/" + checkoutCode, function (result, status) {
|
||||||
var discount = result.discount;
|
var discount = result.discount;
|
||||||
if (discount > 0) {
|
if (discount > 0) {
|
||||||
$('#discount').text(discount);
|
$('#discount').text(discount);
|
@ -0,0 +1,49 @@
|
|||||||
|
package org.owasp.webgoat.plugin;
|
||||||
|
|
||||||
|
import org.hamcrest.CoreMatchers;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
import org.owasp.webgoat.plugins.LessonTest;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||||
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.owasp.webgoat.plugin.ClientSideFilteringFreeAssignment.SUPER_COUPON_CODE;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author nbaars
|
||||||
|
* @since 5/2/17.
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
public class ClientSideFilteringFreeAssignmentTest extends LessonTest {
|
||||||
|
|
||||||
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
ClientSideFiltering clientSideFiltering = new ClientSideFiltering();
|
||||||
|
when(webSession.getCurrentLesson()).thenReturn(clientSideFiltering);
|
||||||
|
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
|
||||||
|
when(webSession.getUserName()).thenReturn("unit-test");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void success() throws Exception {
|
||||||
|
mockMvc.perform(MockMvcRequestBuilders.post("/clientSideFiltering/getItForFree")
|
||||||
|
.param("checkoutCode", SUPER_COUPON_CODE))
|
||||||
|
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void wrongCouponCode() throws Exception {
|
||||||
|
mockMvc.perform(MockMvcRequestBuilders.post("/clientSideFiltering/getItForFree")
|
||||||
|
.param("checkoutCode", "test"))
|
||||||
|
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.not.solved"))))
|
||||||
|
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package org.owasp.webgoat.plugin.challenge2;
|
package org.owasp.webgoat.plugin;
|
||||||
|
|
||||||
import org.hamcrest.CoreMatchers;
|
import org.hamcrest.CoreMatchers;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@ -9,7 +9,7 @@ import org.springframework.test.web.servlet.MockMvc;
|
|||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.owasp.webgoat.plugin.SolutionConstants.SUPER_COUPON_CODE;
|
import static org.owasp.webgoat.plugin.ClientSideFilteringFreeAssignment.SUPER_COUPON_CODE;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
|
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
|
||||||
|
|
||||||
@ -30,28 +30,28 @@ public class ShopEndpointTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSuperCoupon() throws Exception {
|
public void getSuperCoupon() throws Exception {
|
||||||
mockMvc.perform(MockMvcRequestBuilders.get("/challenge-store/coupons/" + SUPER_COUPON_CODE))
|
mockMvc.perform(MockMvcRequestBuilders.get("/clientSideFiltering/challenge-store/coupons/" + SUPER_COUPON_CODE))
|
||||||
.andExpect(jsonPath("$.code", CoreMatchers.is(SUPER_COUPON_CODE)))
|
.andExpect(jsonPath("$.code", CoreMatchers.is(SUPER_COUPON_CODE)))
|
||||||
.andExpect(jsonPath("$.discount", CoreMatchers.is(100)));
|
.andExpect(jsonPath("$.discount", CoreMatchers.is(100)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getCoupon() throws Exception {
|
public void getCoupon() throws Exception {
|
||||||
mockMvc.perform(MockMvcRequestBuilders.get("/challenge-store/coupons/webgoat"))
|
mockMvc.perform(MockMvcRequestBuilders.get("/clientSideFiltering/challenge-store/coupons/webgoat"))
|
||||||
.andExpect(jsonPath("$.code", CoreMatchers.is("webgoat")))
|
.andExpect(jsonPath("$.code", CoreMatchers.is("webgoat")))
|
||||||
.andExpect(jsonPath("$.discount", CoreMatchers.is(25)));
|
.andExpect(jsonPath("$.discount", CoreMatchers.is(25)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void askForUnknownCouponCode() throws Exception {
|
public void askForUnknownCouponCode() throws Exception {
|
||||||
mockMvc.perform(MockMvcRequestBuilders.get("/challenge-store/coupons/does-not-exists"))
|
mockMvc.perform(MockMvcRequestBuilders.get("/clientSideFiltering/challenge-store/coupons/does-not-exists"))
|
||||||
.andExpect(jsonPath("$.code", CoreMatchers.is("no")))
|
.andExpect(jsonPath("$.code", CoreMatchers.is("no")))
|
||||||
.andExpect(jsonPath("$.discount", CoreMatchers.is(0)));
|
.andExpect(jsonPath("$.discount", CoreMatchers.is(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void fetchAllTheCouponsShouldContainGetItForFree() throws Exception {
|
public void fetchAllTheCouponsShouldContainGetItForFree() throws Exception {
|
||||||
mockMvc.perform(MockMvcRequestBuilders.get("/challenge-store/coupons/"))
|
mockMvc.perform(MockMvcRequestBuilders.get("/clientSideFiltering/challenge-store/coupons/"))
|
||||||
.andExpect(jsonPath("$.codes[3].code", is("get_it_for_free")));
|
.andExpect(jsonPath("$.codes[3].code", is("get_it_for_free")));
|
||||||
}
|
}
|
||||||
|
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp.webgoat.lesson</groupId>
|
<groupId>org.owasp.webgoat.lesson</groupId>
|
||||||
<artifactId>webgoat-lessons-parent</artifactId>
|
<artifactId>webgoat-lessons-parent</artifactId>
|
||||||
<version>8.0.0.M3</version>
|
<version>v8.0.0.M15</version>
|
||||||
</parent>
|
</parent>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
@ -60,7 +60,7 @@ public class CrossSiteScripting extends NewLesson {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return "Cross Site Scripting";
|
return "xss.title";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -64,7 +64,7 @@ public class CrossSiteScriptingLesson5a extends AssignmentEndpoint {
|
|||||||
userSessionData.setValue("xss-reflected1-complete",(Object)"false");
|
userSessionData.setValue("xss-reflected1-complete",(Object)"false");
|
||||||
StringBuffer cart = new StringBuffer();
|
StringBuffer cart = new StringBuffer();
|
||||||
cart.append("Thank you for shopping at WebGoat. <br />You're support is appreciated<hr />");
|
cart.append("Thank you for shopping at WebGoat. <br />You're support is appreciated<hr />");
|
||||||
cart.append("<p>We have chaged credit card:" + field1 + "<br />");
|
cart.append("<p>We have charged credit card:" + field1 + "<br />");
|
||||||
cart.append( " ------------------- <br />");
|
cart.append( " ------------------- <br />");
|
||||||
cart.append( " $" + totalSale);
|
cart.append( " $" + totalSale);
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
# XSS success, failure messages and hints
|
# XSS success, failure messages and hints
|
||||||
|
xss.title=Cross Site Scripting
|
||||||
xss-reflected-5a-success=well done, but alerts aren't very impressive are they? Please continue.
|
xss-reflected-5a-success=well done, but alerts aren't very impressive are they? Please continue.
|
||||||
xss-reflected-5a-failure=Try again. We do want to see this specific javascript (in case you are trying to do something more fancy)
|
xss-reflected-5a-failure=Try again. We do want to see this specific javascript (in case you are trying to do something more fancy)
|
||||||
xss-reflected-5b-success=Correct ... because <ul><li>The script was not triggered by the URL/QueryString</li><li>Even if you use the attack URL in a new tab, it won't execute (becuase of response type). Try it if you like.</li></ul>
|
xss-reflected-5b-success=Correct ... because <ul><li>The script was not triggered by the URL/QueryString</li><li>Even if you use the attack URL in a new tab, it won't execute (becuase of response type). Try it if you like.</li></ul>
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
|
|
||||||
=== Why?
|
=== Why?
|
||||||
Hopefully we've covered that by now. Bottom line, you don't want someone else's code running in the context of your users and their logged-in seession
|
Hopefully we've covered that by now. Bottom line, you don't want someone else's code running in the context of your users and their logged-in session
|
||||||
|
|
||||||
=== What to encode?
|
=== What to encode?
|
||||||
The basic premise of defending against XSS is *output endoding* any untrusted input that goes to the screen.
|
The basic premise of defending against XSS is *output encoding* any untrusted input that goes to the screen.
|
||||||
That may be changing with more sophisticated attacks, but is still the best defense we currently have. *AND* ... *context matters*
|
That may be changing with more sophisticated attacks, but is still the best defense we currently have. *AND* ... *context matters*
|
||||||
|
|
||||||
Another word on 'untrusted input'. If in doubt, treat everything (even data you populated in your DB as untrusted).
|
Another word on 'untrusted input'. If in doubt, treat everything (even data you populated in your DB as untrusted).
|
||||||
|
@ -33,8 +33,10 @@ import org.mockito.runners.MockitoJUnitRunner;
|
|||||||
import org.owasp.webgoat.assignments.AssignmentEndpointTest;
|
import org.owasp.webgoat.assignments.AssignmentEndpointTest;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
import org.springframework.test.web.servlet.ResultActions;
|
import org.springframework.test.web.servlet.ResultActions;
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
@ -80,13 +82,13 @@ public class StoredXssCommentsTest extends AssignmentEndpointTest {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
//Ensures it is vulnerable
|
//Ensures it is vulnerable
|
||||||
// @Test
|
@Test
|
||||||
// public void isNotEncoded() throws Exception {
|
public void isNotEncoded() throws Exception {
|
||||||
// //do get to get comments after posting xss payload
|
//do get to get comments after posting xss payload
|
||||||
// ResultActions taintedResults = mockMvc.perform(MockMvcRequestBuilders.get("/CrossSiteScripting/stored-xss"));
|
ResultActions taintedResults = mockMvc.perform(MockMvcRequestBuilders.get("/CrossSiteScripting/stored-xss"));
|
||||||
// taintedResults.andExpect(jsonPath("$[0].text",CoreMatchers.is(CoreMatchers.containsString("<script>console.warn('unit test me')</script>"))));
|
MvcResult mvcResult = taintedResults.andReturn();
|
||||||
// }
|
assert(mvcResult.getResponse().getContentAsString().contains("<script>console.warn"));
|
||||||
|
}
|
||||||
|
|
||||||
//Could be used to test an encoding solution ... commented out so build will pass. Uncommenting will fail build, but leaving in as positive Security Unit Test
|
//Could be used to test an encoding solution ... commented out so build will pass. Uncommenting will fail build, but leaving in as positive Security Unit Test
|
||||||
// @Test
|
// @Test
|
||||||
|
@ -6,6 +6,6 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp.webgoat.lesson</groupId>
|
<groupId>org.owasp.webgoat.lesson</groupId>
|
||||||
<artifactId>webgoat-lessons-parent</artifactId>
|
<artifactId>webgoat-lessons-parent</artifactId>
|
||||||
<version>8.0.0.M3</version>
|
<version>v8.0.0.M15</version>
|
||||||
</parent>
|
</parent>
|
||||||
</project>
|
</project>
|
@ -6,30 +6,31 @@ import org.owasp.webgoat.assignments.AssignmentPath;
|
|||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.session.UserSessionData;
|
import org.owasp.webgoat.session.UserSessionData;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by jason on 9/29/17.
|
* Created by jason on 9/29/17.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@AssignmentPath("/csrf/confirm-flag-1")
|
@AssignmentPath("/csrf/confirm-flag-1")
|
||||||
@AssignmentHints({"csrf-get.hint1","csrf-get.hint2","csrf-get.hint3","csrf-get.hint4"})
|
@AssignmentHints({"csrf-get.hint1", "csrf-get.hint2", "csrf-get.hint3", "csrf-get.hint4"})
|
||||||
public class CSRFConfirmFlag1 extends AssignmentEndpoint {
|
public class CSRFConfirmFlag1 extends AssignmentEndpoint {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
UserSessionData userSessionData;
|
UserSessionData userSessionData;
|
||||||
|
|
||||||
@PostMapping(produces = {"application/json"})
|
@PostMapping(produces = {"application/json"})
|
||||||
public @ResponseBody AttackResult completed(String confirmFlagVal) {
|
public @ResponseBody
|
||||||
|
AttackResult completed(String confirmFlagVal) {
|
||||||
|
|
||||||
if (confirmFlagVal.equals(userSessionData.getValue("csrf-get-success").toString())) {
|
Object userSessionDataStr = userSessionData.getValue("csrf-get-success");
|
||||||
return success().feedback("csrf-get-null-referer.success").output("Correct, the flag was " + userSessionData.getValue("csrf-get-success")).build();
|
if (userSessionDataStr != null && confirmFlagVal.equals(userSessionDataStr.toString())) {
|
||||||
|
return trackProgress(
|
||||||
|
success().feedback("csrf-get-null-referer.success").output("Correct, the flag was " + userSessionData.getValue("csrf-get-success")).build()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return failed().feedback("").build();
|
return trackProgress(failed().build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ public class CSRFFeedback extends AssignmentEndpoint {
|
|||||||
try {
|
try {
|
||||||
objectMapper.readValue(feedback.getBytes(), Map.class);
|
objectMapper.readValue(feedback.getBytes(), Map.class);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
return failed().feedback(ExceptionUtils.getStackTrace(e)).build();
|
return failed().feedback(ExceptionUtils.getStackTrace(e)).build();
|
||||||
}
|
}
|
||||||
boolean correctCSRF = requestContainsWebGoatCookie(request.getCookies()) && request.getContentType().equals(MediaType.TEXT_PLAIN_VALUE);
|
boolean correctCSRF = requestContainsWebGoatCookie(request.getCookies()) && request.getContentType().equals(MediaType.TEXT_PLAIN_VALUE);
|
||||||
correctCSRF &= hostOrRefererDifferentHost(request);
|
correctCSRF &= hostOrRefererDifferentHost(request);
|
||||||
@ -64,8 +64,12 @@ public class CSRFFeedback extends AssignmentEndpoint {
|
|||||||
|
|
||||||
private boolean hostOrRefererDifferentHost(HttpServletRequest request) {
|
private boolean hostOrRefererDifferentHost(HttpServletRequest request) {
|
||||||
String referer = request.getHeader("referer");
|
String referer = request.getHeader("referer");
|
||||||
String host = request.getHeader("host");
|
String origin = request.getHeader("origin");
|
||||||
return !StringUtils.contains(referer, host);
|
if (referer != null) {
|
||||||
|
return !referer.contains(origin);
|
||||||
|
} else {
|
||||||
|
return true; //this case referer is null or origin does not matter we cannot compare so we return true which should of course be false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean requestContainsWebGoatCookie(Cookie[] cookies) {
|
private boolean requestContainsWebGoatCookie(Cookie[] cookies) {
|
||||||
|
@ -31,7 +31,7 @@ public class CSRFGetFlag extends Endpoint {
|
|||||||
@ResponseBody
|
@ResponseBody
|
||||||
public Map<String, Object> invoke(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
public Map<String, Object> invoke(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
|
||||||
Map<String,Object> response = new HashMap<>();
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
|
||||||
String host = (req.getHeader("host") == null) ? "NULL" : req.getHeader("host");
|
String host = (req.getHeader("host") == null) ? "NULL" : req.getHeader("host");
|
||||||
// String origin = (req.getHeader("origin") == null) ? "NULL" : req.getHeader("origin");
|
// String origin = (req.getHeader("origin") == null) ? "NULL" : req.getHeader("origin");
|
||||||
@ -40,22 +40,32 @@ public class CSRFGetFlag extends Endpoint {
|
|||||||
String referer = (req.getHeader("referer") == null) ? "NULL" : req.getHeader("referer");
|
String referer = (req.getHeader("referer") == null) ? "NULL" : req.getHeader("referer");
|
||||||
String[] refererArr = referer.split("/");
|
String[] refererArr = referer.split("/");
|
||||||
|
|
||||||
if (referer.equals("NULL") && req.getParameter("csrf").equals("true")) {
|
|
||||||
Random random = new Random();
|
|
||||||
userSessionData.setValue("csrf-get-success", random.nextInt(65536));
|
if (referer.equals("NULL")) {
|
||||||
response.put("success",true);
|
if (req.getParameter("csrf").equals("true")) {
|
||||||
response.put("message",pluginMessages.getMessage("csrf-get-null-referer.success"));
|
Random random = new Random();
|
||||||
response.put("flag",userSessionData.getValue("csrf-get-success"));
|
userSessionData.setValue("csrf-get-success", random.nextInt(65536));
|
||||||
} else if (refererArr[2].equals(host)) {
|
response.put("success", true);
|
||||||
|
response.put("message", pluginMessages.getMessage("csrf-get-null-referer.success"));
|
||||||
|
response.put("flag", userSessionData.getValue("csrf-get-success"));
|
||||||
|
} else {
|
||||||
|
Random random = new Random();
|
||||||
|
userSessionData.setValue("csrf-get-success", random.nextInt(65536));
|
||||||
|
response.put("success", true);
|
||||||
|
response.put("message", pluginMessages.getMessage("csrf-get-other-referer.success"));
|
||||||
|
response.put("flag", userSessionData.getValue("csrf-get-success"));
|
||||||
|
}
|
||||||
|
} else if (refererArr[2].equals(host)) {
|
||||||
response.put("success", false);
|
response.put("success", false);
|
||||||
response.put("message", "Appears the request came from the original host");
|
response.put("message", "Appears the request came from the original host");
|
||||||
response.put("flag", null);
|
response.put("flag", null);
|
||||||
} else {
|
} else {
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
userSessionData.setValue("csrf-get-success", random.nextInt(65536));
|
userSessionData.setValue("csrf-get-success", random.nextInt(65536));
|
||||||
response.put("success",true);
|
response.put("success", true);
|
||||||
response.put("message",pluginMessages.getMessage("csrf-get-other-referer.success"));
|
response.put("message", pluginMessages.getMessage("csrf-get-other-referer.success"));
|
||||||
response.put("flag",userSessionData.getValue("csrf-get-success"));
|
response.put("flag", userSessionData.getValue("csrf-get-success"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
package org.owasp.webgoat.plugin;
|
|
||||||
|
|
||||||
import org.owasp.webgoat.assignments.Endpoint;
|
|
||||||
import org.owasp.webgoat.i18n.PluginMessages;
|
|
||||||
import org.owasp.webgoat.session.UserSessionData;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by jason on 9/30/17.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class CSRFGetXhrFlag extends Endpoint {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
UserSessionData userSessionData;
|
|
||||||
@Autowired
|
|
||||||
private PluginMessages pluginMessages;
|
|
||||||
|
|
||||||
@RequestMapping(produces = {"application/json"}, method = RequestMethod.GET)
|
|
||||||
@ResponseBody
|
|
||||||
public Map<String, Object> invoke(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
|
||||||
|
|
||||||
Map<String,Object> response = new HashMap<>();
|
|
||||||
|
|
||||||
String host = (req.getHeader("host") == null) ? "NULL" : req.getHeader("host");
|
|
||||||
// String origin = (req.getHeader("origin") == null) ? "NULL" : req.getHeader("origin");
|
|
||||||
// Integer serverPort = (req.getServerPort() < 1) ? 0 : req.getServerPort();
|
|
||||||
// String serverName = (req.getServerName() == null) ? "NULL" : req.getServerName();
|
|
||||||
String referer = (req.getHeader("referer") == null) ? "NULL" : req.getHeader("referer");
|
|
||||||
String[] refererArr = referer.split("/");
|
|
||||||
|
|
||||||
if (referer.equals("NULL") && req.getParameter("csrf").equals("true")) {
|
|
||||||
Random random = new Random();
|
|
||||||
userSessionData.setValue("csrf-get-success", random.nextInt(65536));
|
|
||||||
response.put("success",true);
|
|
||||||
response.put("message",pluginMessages.getMessage("csrf-get-null-referer.success"));
|
|
||||||
response.put("flag",userSessionData.getValue("csrf-get-success"));
|
|
||||||
} else if (refererArr[2].equals(host)) {
|
|
||||||
response.put("success", false);
|
|
||||||
response.put("message", "Appears the request came from the original host");
|
|
||||||
response.put("flag", null);
|
|
||||||
} else {
|
|
||||||
Random random = new Random();
|
|
||||||
userSessionData.setValue("csrf-get-success", random.nextInt(65536));
|
|
||||||
response.put("success",true);
|
|
||||||
response.put("message",pluginMessages.getMessage("csrf-get-other-referer.success"));
|
|
||||||
response.put("flag",userSessionData.getValue("csrf-get-success"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPath() {
|
|
||||||
return "/csrf/get-xhr-flag";
|
|
||||||
}
|
|
||||||
}
|
|
@ -33,7 +33,7 @@ public class CSRFLogin extends AssignmentEndpoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void markAssignmentSolvedWithRealUser(String username) {
|
private void markAssignmentSolvedWithRealUser(String username) {
|
||||||
UserTracker userTracker = userTrackerRepository.findOne(username);
|
UserTracker userTracker = userTrackerRepository.findByUser(username);
|
||||||
userTracker.assignmentSolved(getWebSession().getCurrentLesson(), this.getClass().getSimpleName());
|
userTracker.assignmentSolved(getWebSession().getCurrentLesson(), this.getClass().getSimpleName());
|
||||||
userTrackerRepository.save(userTracker);
|
userTrackerRepository.save(userTracker);
|
||||||
}
|
}
|
||||||
|
@ -115,22 +115,13 @@ public class ForgedReviews extends AssignmentEndpoint {
|
|||||||
userReviews.put(webSession.getUserName(), reviews);
|
userReviews.put(webSession.getUserName(), reviews);
|
||||||
//short-circuit
|
//short-circuit
|
||||||
if (validateReq == null || !validateReq.equals(weakAntiCSRF)) {
|
if (validateReq == null || !validateReq.equals(weakAntiCSRF)) {
|
||||||
return failed().feedback("csrf-you-forgot-something").build();
|
return trackProgress(failed().feedback("csrf-you-forgot-something").build());
|
||||||
}
|
}
|
||||||
//we have the spoofed files
|
//we have the spoofed files
|
||||||
if (referer != "NULL" && refererArr[2].equals(host) ) {
|
if (referer != "NULL" && refererArr[2].equals(host) ) {
|
||||||
return (failed().feedback("csrf-same-host").build());
|
return trackProgress(failed().feedback("csrf-same-host").build());
|
||||||
} else {
|
} else {
|
||||||
return (success().feedback("csrf-review.success").build()); //feedback("xss-stored-comment-failure")
|
return trackProgress(success().feedback("csrf-review.success").build()); //feedback("xss-stored-comment-failure")
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Review parseJson(String comment) {
|
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
|
||||||
try {
|
|
||||||
return mapper.readValue(comment, Review.class);
|
|
||||||
} catch (IOException e) {
|
|
||||||
return new Review();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
<form accept-charset="UNKNOWN" id="basic-csrf-get"
|
<form accept-charset="UNKNOWN" id="basic-csrf-get"
|
||||||
method="GET" name="form1"
|
method="GET" name="form1"
|
||||||
|
target="_blank"
|
||||||
successCallback=""
|
successCallback=""
|
||||||
action="/WebGoat/csrf/basic-get-flag"
|
action="/WebGoat/csrf/basic-get-flag"
|
||||||
enctype="application/json;charset=UTF-8">
|
enctype="application/json;charset=UTF-8">
|
||||||
@ -26,10 +27,12 @@
|
|||||||
<div class="adoc-content" th:replace="doc:CSRF_Basic_Get-1.adoc"></div>
|
<div class="adoc-content" th:replace="doc:CSRF_Basic_Get-1.adoc"></div>
|
||||||
|
|
||||||
<div class="attack-container">
|
<div class="attack-container">
|
||||||
|
<img th:src="@{/images/wolf-enabled.png}" class="webwolf-enabled"/>
|
||||||
<div class="assignment-success">
|
<div class="assignment-success">
|
||||||
<i class="fa fa-2 fa-check hidden" aria-hidden="true">
|
<i class="fa fa-2 fa-check hidden" aria-hidden="true">
|
||||||
</i>
|
</i>
|
||||||
</div>
|
</div>
|
||||||
|
<br/>
|
||||||
<form class="attack-form" accept-charset="UNKNOWN" id="confirm-flag-1"
|
<form class="attack-form" accept-charset="UNKNOWN" id="confirm-flag-1"
|
||||||
method="POST" name="form2"
|
method="POST" name="form2"
|
||||||
successCallback=""
|
successCallback=""
|
||||||
@ -40,7 +43,10 @@
|
|||||||
<input type="text" length="6" name="confirmFlagVal" value=""/>
|
<input type="text" length="6" name="confirmFlagVal" value=""/>
|
||||||
|
|
||||||
<input name="submit" value="Submit" type="submit"/>
|
<input name="submit" value="Submit" type="submit"/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="attack-feedback"></div>
|
<div class="attack-feedback"></div>
|
||||||
@ -56,9 +62,9 @@
|
|||||||
<link rel="stylesheet" type="text/css" th:href="@{/lesson_css/reviews.css}"/>
|
<link rel="stylesheet" type="text/css" th:href="@{/lesson_css/reviews.css}"/>
|
||||||
<script th:src="@{/lesson_js/csrf-review.js}" language="JavaScript"></script>
|
<script th:src="@{/lesson_js/csrf-review.js}" language="JavaScript"></script>
|
||||||
|
|
||||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
|
||||||
|
|
||||||
<div class="attack-container">
|
<div class="attack-container">
|
||||||
|
<img th:src="@{/images/wolf-enabled.png}" class="webwolf-enabled"/>
|
||||||
|
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="panel post">
|
<div class="panel post">
|
||||||
<div class="post-heading">
|
<div class="post-heading">
|
||||||
@ -133,65 +139,71 @@
|
|||||||
padding: 7px;
|
padding: 7px;
|
||||||
margin-top:7px;
|
margin-top:7px;
|
||||||
padding:5px;">
|
padding:5px;">
|
||||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
<div class="attack-container">
|
||||||
<div class="container-fluid">
|
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||||
<div class="row">
|
<div class="container-fluid">
|
||||||
<div class="col-md-8">
|
<div class="row">
|
||||||
<div class="well well-sm">
|
<div class="col-md-8">
|
||||||
<form class="attack-form" accept-charset="UNKNOWN" id="csrf-feedback"
|
<div class="well well-sm">
|
||||||
method="POST"
|
<form class="attack-form" accept-charset="UNKNOWN" id="csrf-feedback"
|
||||||
prepareData="feedback"
|
method="POST"
|
||||||
action="/WebGoat/csrf/feedback/message"
|
prepareData="feedback"
|
||||||
contentType="application/json">
|
action="/WebGoat/csrf/feedback/message"
|
||||||
<div class="row">
|
contentType="application/json">
|
||||||
<div class="col-md-6">
|
<div class="row">
|
||||||
<div class="form-group">
|
<div class="col-md-6">
|
||||||
<label for="name">
|
<div class="form-group">
|
||||||
Name</label>
|
<label for="name">
|
||||||
<input type="text" class="form-control" name="name" id="name"
|
Name</label>
|
||||||
placeholder="Enter name"
|
<input type="text" class="form-control" name="name" id="name"
|
||||||
required="required"/>
|
placeholder="Enter name"
|
||||||
</div>
|
required="required"/>
|
||||||
<div class="form-group">
|
</div>
|
||||||
<label for="email">
|
<div class="form-group">
|
||||||
Email Address</label>
|
<label for="email">
|
||||||
<div class="input-group">
|
Email Address</label>
|
||||||
|
<div class="input-group">
|
||||||
<span class="input-group-addon"><span class="glyphicon glyphicon-envelope"></span>
|
<span class="input-group-addon"><span class="glyphicon glyphicon-envelope"></span>
|
||||||
</span>
|
</span>
|
||||||
<input type="email" name="email" class="form-control" id="email"
|
<input type="email" name="email" class="form-control" id="email"
|
||||||
placeholder="Enter email"
|
placeholder="Enter email"
|
||||||
required="required"/></div>
|
required="required"/></div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="subject">
|
||||||
|
Subject</label>
|
||||||
|
<select id="subject" name="subject" class="form-control"
|
||||||
|
required="required">
|
||||||
|
<option value="na" selected="">Choose One:</option>
|
||||||
|
<option value="service">General Customer Service</option>
|
||||||
|
<option value="suggestions">Suggestions</option>
|
||||||
|
<option value="product">Product Support</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="col-md-6">
|
||||||
<label for="subject">
|
<div class="form-group">
|
||||||
Subject</label>
|
<label for="name">
|
||||||
<select id="subject" name="subject" class="form-control" required="required">
|
Message</label>
|
||||||
<option value="na" selected="">Choose One:</option>
|
<textarea name="message" id="message" class="form-control" rows="9"
|
||||||
<option value="service">General Customer Service</option>
|
cols="25"
|
||||||
<option value="suggestions">Suggestions</option>
|
required="required"
|
||||||
<option value="product">Product Support</option>
|
placeholder="Message"></textarea>
|
||||||
</select>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
<button class="btn btn-primary pull-right" id="btnContactUs">
|
||||||
|
Send Message
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
</form>
|
||||||
<div class="form-group">
|
</div>
|
||||||
<label for="name">
|
|
||||||
Message</label>
|
|
||||||
<textarea name="message" id="message" class="form-control" rows="9" cols="25"
|
|
||||||
required="required"
|
|
||||||
placeholder="Message"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-12">
|
|
||||||
<button class="btn btn-primary pull-right" id="btnContactUs">
|
|
||||||
Send Message
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="attack-feedback"></div>
|
||||||
|
<div class="attack-output"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -211,7 +223,6 @@
|
|||||||
<input name="submit" value="Submit" type="submit"/>
|
<input name="submit" value="Submit" type="submit"/>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="attack-feedback"></div>
|
<div class="attack-feedback"></div>
|
||||||
<div class="attack-output"></div>
|
<div class="attack-output"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,11 +8,11 @@ In this assignment you need to achieve to POST the following JSON message to our
|
|||||||
|
|
||||||
[source]
|
[source]
|
||||||
----
|
----
|
||||||
POST /csrf/feedback HTTP/1.1
|
POST /csrf/feedback/message HTTP/1.1
|
||||||
|
|
||||||
{
|
{
|
||||||
"name" : "WebGoat",
|
"name" : "WebGoat",
|
||||||
"email" : "webgoat@webgoat.org"
|
"email" : "webgoat@webgoat.org",
|
||||||
"content" : "WebGoat is the best!!"
|
"content" : "WebGoat is the best!!"
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
@ -13,9 +13,14 @@ match and this will ensure the server the request is running on the same domain.
|
|||||||
|
|
||||||
Remember the session cookie should always be defined with http-only flag.
|
Remember the session cookie should always be defined with http-only flag.
|
||||||
|
|
||||||
Another effective defense can be to add a custom request header to each call. This will work if all the interactions
|
== Custom headers not safe
|
||||||
|
|
||||||
|
Another defense can be to add a custom request header to each call. This will work if all the interactions
|
||||||
with the server are performed with JavaScript. On the server side you only need to check the presence of this header
|
with the server are performed with JavaScript. On the server side you only need to check the presence of this header
|
||||||
if this header is not present deny the request.
|
if this header is not present deny the request.
|
||||||
|
Some frameworks offer this implementation by default however researcer Alex Infuhr found out that this can be bypassed
|
||||||
|
as well. You can read about: http://insert-blogspot.nl/2018/05/adobe-reader-pdf-client-side-request.html?m=1[Adobe Reader PDF - Client Side Request Injection]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,7 +4,20 @@ The impact is limited only by what the logged in user can do (if the site/functi
|
|||||||
The areas that are really prone to CSRF attacks are IoT devices and 'smart' appliances. Sadly, many consumer-grade routers
|
The areas that are really prone to CSRF attacks are IoT devices and 'smart' appliances. Sadly, many consumer-grade routers
|
||||||
have also proven vulnerable to CSRF.
|
have also proven vulnerable to CSRF.
|
||||||
|
|
||||||
== CSRF Solution
|
== CSRF solutions
|
||||||
|
|
||||||
|
=== Same site cookie attribute
|
||||||
|
|
||||||
|
This is a new extension which modern browsers support which limits the scope of the cookie such that it will only be
|
||||||
|
attached to requests if those requests are 'same-site'
|
||||||
|
For example requests for `http://webgoat.org/something` will attach same-site cookies if the request is initiated from
|
||||||
|
`webgoat.org`.
|
||||||
|
There are two modes, strict and lax. The first one does not allow cross site request, this means when you are on
|
||||||
|
github.com and you want to like it through Facebook (and Facebook specifies same-site as strict) you will be
|
||||||
|
redirected to the login page, because the browser does not attach the cookie for Facebook.
|
||||||
|
More information can be found here: www.sjoerdlangkemper.nl/2016/04/14/preventin-csrf-with-samesite-cookie-attribute/
|
||||||
|
|
||||||
|
=== Other protections
|
||||||
|
|
||||||
Fortunately, many (web) application frameworks now come with built in support to handle CSRF attacks. For example, Spring and
|
Fortunately, many (web) application frameworks now come with built in support to handle CSRF attacks. For example, Spring and
|
||||||
Tomcat have this on by default. As long as you don't turn it off (like it is in WebGoat), you should be safe from CSRF attacks.
|
Tomcat have this on by default. As long as you don't turn it off (like it is in WebGoat), you should be safe from CSRF attacks.
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
A lot of web applications implement no protection against CSRF they are somehow protected by the fact that
|
A lot of web applications implement no protection against CSRF they are somehow protected by the fact that
|
||||||
they only work with `application/json` as content type. The only way to make a request with this content-type from the
|
they only work with `application/json` as content type. The only way to make a request with this content-type from the
|
||||||
browser is with a XHR request. Before the browser can make such a request a preflight request will be made towards
|
browser is with a XHR request. Before the browser can make such a request a preflight request will be made towards
|
||||||
the server (remember the CSRF request will be cross origin). If the preflight response does not allow the cross origin
|
the server (remember the CSRF request will be cross origin). If the pre-flight response does not allow the cross origin
|
||||||
request the browser will not make the call.
|
request the browser will not make the call.
|
||||||
|
|
||||||
To make a long answer short: this is *not* a valid protection against CSRF.
|
To make a long answer short: this is *not* a valid protection against CSRF.
|
||||||
|
@ -46,13 +46,10 @@ public class CSRFFeedbackTest extends LessonTest {
|
|||||||
mockMvc.perform(post("/csrf/feedback/message")
|
mockMvc.perform(post("/csrf/feedback/message")
|
||||||
.contentType(MediaType.TEXT_PLAIN)
|
.contentType(MediaType.TEXT_PLAIN)
|
||||||
.cookie(new Cookie("JSESSIONID", "test"))
|
.cookie(new Cookie("JSESSIONID", "test"))
|
||||||
.header("host", "localhost:8080")
|
.header("origin", "localhost:8080")
|
||||||
.header("referer", "webgoat.org")
|
.header("referer", "webgoat.org")
|
||||||
.content("{\"name\": \"Test\", \"email\": \"test1233@dfssdf.de\", \"subject\": \"service\", \"message\":\"dsaffd\"}"))
|
.content("{\"name\": \"Test\", \"email\": \"test1233@dfssdf.de\", \"subject\": \"service\", \"message\":\"dsaffd\"}"))
|
||||||
.andExpect(jsonPath("lessonCompleted", is(true)))
|
.andExpect(jsonPath("lessonCompleted", is(true)))
|
||||||
.andExpect(jsonPath("feedback", StringContains.containsString("the flag is: ")));
|
.andExpect(jsonPath("feedback", StringContains.containsString("the flag is: ")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp.webgoat.lesson</groupId>
|
<groupId>org.owasp.webgoat.lesson</groupId>
|
||||||
<artifactId>webgoat-lessons-parent</artifactId>
|
<artifactId>webgoat-lessons-parent</artifactId>
|
||||||
<version>8.0.0.M3</version>
|
<version>v8.0.0.M15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp.webgoat.lesson</groupId>
|
<groupId>org.owasp.webgoat.lesson</groupId>
|
||||||
<artifactId>webgoat-lessons-parent</artifactId>
|
<artifactId>webgoat-lessons-parent</artifactId>
|
||||||
<version>8.0.0.M3</version>
|
<version>v8.0.0.M15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -8,6 +8,7 @@ http-basics.hints.http_basic_quiz.1=Turn on Show Parameters or other features
|
|||||||
http-basics.hints.http_basic_quiz.2=Try to intercept the request with <a href='https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project' title='Link to ZAP'>OWASP ZAP</a>
|
http-basics.hints.http_basic_quiz.2=Try to intercept the request with <a href='https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project' title='Link to ZAP'>OWASP ZAP</a>
|
||||||
|
|
||||||
|
|
||||||
|
http-basics.empty=Try again, name cannot be empty.
|
||||||
http-basics.reversed=The server has reversed your name: {0}
|
http-basics.reversed=The server has reversed your name: {0}
|
||||||
|
|
||||||
http-basics.close=Try again: but this time enter a value before hitting go.
|
http-basics.close=Try again: but this time enter a value before hitting go.
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
Enter your name in the input field below and press "Go!" to submit. The server will accept the request, reverse the input and display it back to the user, illustrating the basics of handling an HTTP request.
|
Enter your name in the input field below and press "Go!" to submit. The server will accept the request, reverse the
|
||||||
|
input and display it back to the user, illustrating the basics of handling an HTTP request.
|
||||||
The user should become familiar with the features of WebGoat by manipulating the above buttons to view hints, show the HTTP request parameters, the HTTP request cookies, and the Java source code. You may also try using OWASP ZAP Attack Proxy to see the HTTP data.
|
|
||||||
|
|
||||||
== Try It!
|
== Try It!
|
||||||
|
|
||||||
Enter your name in the input field below and press "Go!" to submit. The server will accept the request, reverse the input and display it back to the user, illustrating the basics of handling an HTTP request.
|
Enter your name in the input field below and press "Go!" to submit. The server will accept the request, reverse the input
|
||||||
|
and display it back to the user, illustrating the basics of handling an HTTP request.
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.owasp.webgoat.lesson</groupId>
|
<groupId>org.owasp.webgoat.lesson</groupId>
|
||||||
<artifactId>webgoat-lessons-parent</artifactId>
|
<artifactId>webgoat-lessons-parent</artifactId>
|
||||||
<version>8.0.0.M3</version>
|
<version>v8.0.0.M15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -48,7 +48,7 @@ public class HttpBasicsInterceptRequest extends AssignmentEndpoint {
|
|||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET)
|
@RequestMapping(method = RequestMethod.GET)
|
||||||
public @ResponseBody
|
public @ResponseBody
|
||||||
AttackResult completed(HttpServletRequest request) throws IOException {
|
AttackResult completed(HttpServletRequest request) {
|
||||||
String header = null;
|
String header = null;
|
||||||
String param = null;
|
String param = null;
|
||||||
if (request != null && (header = request.getHeader("x-request-intercepted")) != null
|
if (request != null && (header = request.getHeader("x-request-intercepted")) != null
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
== HTTP Proxy Overview
|
== HTTP Proxy Overview
|
||||||
|
|
||||||
Many times proxies are used as a way of accessing otherwise blocked content. A user might connect to server A, which relays content from server B
|
Many times proxies are used as a way of accessing otherwise blocked content. A user might connect to server A, which relays content from server B
|
||||||
... Because Server B is blocked wihtin the user's network. That's not the use case we will be dealing with here, but the concept is the same.
|
... Because Server B is blocked within the user's network. That's not the use case we will be dealing with here, but the concept is the same.
|
||||||
HTTP Proxies receive requests from a client and relay them. They also typically record them. They act as a man-in-the-middle (keep that in mind if you decide to
|
HTTP Proxies receive requests from a client and relay them. They also typically record them. They act as a man-in-the-middle (keep that in mind if you decide to
|
||||||
use a proxy server to connect to some other system that is otherwise blocked). We won't get into HTTP vs HTTPS just yet, but that's an important topic in
|
use a proxy server to connect to some other system that is otherwise blocked). We won't get into HTTP vs HTTPS just yet, but that's an important topic in
|
||||||
relationship to proxies.
|
relationship to proxies.
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user