-
Notifications
You must be signed in to change notification settings - Fork 48
Add contact feedback form with security flows and CAPTCHA (Kaptcha, CVE-2019-16335) #72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,20 @@ | ||
| eclipse.preferences.version=1 | ||
| org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore | ||
| org.eclipse.jdt.core.compiler.annotation.nonnull=javax.annotation.Nonnull | ||
| org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=javax.annotation.ParametersAreNonnullByDefault | ||
| org.eclipse.jdt.core.compiler.annotation.nullable=javax.annotation.Nullable | ||
| org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled | ||
| org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull | ||
| org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault | ||
| org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable | ||
| org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled | ||
| org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 | ||
| org.eclipse.jdt.core.compiler.compliance=17 | ||
| org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled | ||
| org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning | ||
| org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning | ||
| org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error | ||
| org.eclipse.jdt.core.compiler.problem.nullReference=warning | ||
| org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning | ||
| org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error | ||
| org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore | ||
| org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning | ||
| org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore | ||
| org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore | ||
| org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled | ||
| org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled | ||
| org.eclipse.jdt.core.compiler.processAnnotations=enabled | ||
| org.eclipse.jdt.core.compiler.release=disabled | ||
| org.eclipse.jdt.core.compiler.source=17 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| package demo.security.servlet; | ||
|
|
||
| import com.google.code.kaptcha.Producer; | ||
| import com.google.code.kaptcha.util.Config; | ||
| import javax.imageio.ImageIO; | ||
| import javax.servlet.ServletException; | ||
| import javax.servlet.annotation.WebServlet; | ||
| import javax.servlet.http.HttpServlet; | ||
| import javax.servlet.http.HttpServletRequest; | ||
| import javax.servlet.http.HttpServletResponse; | ||
| import javax.servlet.http.HttpSession; | ||
| import java.awt.image.BufferedImage; | ||
| import java.io.IOException; | ||
| import java.util.Properties; | ||
|
|
||
| @WebServlet("/captcha-image") | ||
| public class CaptchaImageServlet extends HttpServlet { | ||
| private Producer kaptchaProducer; | ||
|
|
||
| @Override | ||
| public void init() throws ServletException { | ||
| Properties props = new Properties(); | ||
| props.put("kaptcha.textproducer.char.length", "5"); | ||
| Config config = new Config(props); | ||
| kaptchaProducer = config.getProducerImpl(); | ||
| } | ||
|
|
||
| @Override | ||
| protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||
| String capText = kaptchaProducer.createText(); | ||
| HttpSession session = request.getSession(); | ||
| session.setAttribute("contactFeedbackCaptcha", capText); | ||
| BufferedImage bi = kaptchaProducer.createImage(capText); | ||
| response.setContentType("image/png"); | ||
| ImageIO.write(bi, "png", response.getOutputStream()); | ||
Check noticeCode scanning / SonarQube Exceptions should not be thrown from servlet methods
<!--SONAR_ISSUE_KEY:3661edae-ea3c-4c2d-a444-e0845192dac1-->Handle the following exception that could be thrown by "getOutputStream": IOException. <p>See more on <a href="https://nautilus.sonarqube.org/project/issues?id=demo%3Ajava-security&branch=feature%2Fcontact-feedback-form&issues=3661edae-ea3c-4c2d-a444-e0845192dac1&open=3661edae-ea3c-4c2d-a444-e0845192dac1">SonarQube</a></p>
Check noticeCode scanning / SonarQube Exceptions should not be thrown from servlet methods Low
Handle the following exception that could be thrown by "write": IOException. See more on SonarQube
Check noticeCode scanning / SonarQube Exceptions should not be thrown from servlet methods Low
Handle the following exception that could be thrown by "getOutputStream": IOException. See more on SonarQube
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| package demo.security.servlet; | ||
|
|
||
| import javax.servlet.ServletException; | ||
| import javax.servlet.annotation.WebServlet; | ||
| import javax.servlet.http.HttpServlet; | ||
| import javax.servlet.http.HttpServletRequest; | ||
| import javax.servlet.http.HttpServletResponse; | ||
| import java.io.IOException; | ||
| import java.io.PrintWriter; | ||
| import java.util.ArrayList; | ||
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| @WebServlet("/contact-feedback") | ||
| public class ContactFeedbackServlet extends HttpServlet { | ||
| private static final List<Map<String, String>> FEEDBACKS = new ArrayList<>(); | ||
|
|
||
| @Override | ||
| protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||
| String name = request.getParameter("name"); | ||
| String email = request.getParameter("email"); | ||
| String category = request.getParameter("category"); | ||
| String feedback = request.getParameter("feedback"); | ||
| String captcha = request.getParameter("captcha"); | ||
| String captchaExpected = (String) request.getSession().getAttribute("contactFeedbackCaptcha"); | ||
| response.setContentType("text/html"); | ||
| PrintWriter out = response.getWriter(); | ||
Check noticeCode scanning / SonarQube Exceptions should not be thrown from servlet methods
<!--SONAR_ISSUE_KEY:40d77173-aa40-425e-97ac-c005cda4008f-->Handle the following exception that could be thrown by "getWriter": IOException. <p>See more on <a href="https://nautilus.sonarqube.org/project/issues?id=demo%3Ajava-security&branch=feature%2Fcontact-feedback-form&issues=40d77173-aa40-425e-97ac-c005cda4008f&open=40d77173-aa40-425e-97ac-c005cda4008f">SonarQube</a></p>
|
||
| if (captchaExpected == null || captcha == null || !captchaExpected.equalsIgnoreCase(captcha)) { | ||
| out.println("<html><body><h2>CAPTCHA validation failed!</h2><a href='contact-feedback.jsp'>Back</a></body></html>"); | ||
| return; | ||
| } | ||
| Map<String, String> entry = new HashMap<>(); | ||
| entry.put("name", name); | ||
| entry.put("email", email); | ||
| entry.put("category", category); | ||
| entry.put("feedback", feedback); | ||
| FEEDBACKS.add(entry); | ||
| out.println("<html><body><h2>Thank you for your feedback!</h2><a href='contact-feedback.jsp'>Back</a></body></html>"); | ||
| } | ||
|
|
||
| @Override | ||
| protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||
| String email = request.getParameter("email"); | ||
| String category = request.getParameter("category"); | ||
| response.setContentType("text/html"); | ||
| PrintWriter out = response.getWriter(); | ||
Check noticeCode scanning / SonarQube Exceptions should not be thrown from servlet methods
<!--SONAR_ISSUE_KEY:6ebe0823-14f9-40d3-9d34-1f3b8e98c316-->Handle the following exception that could be thrown by "getWriter": IOException. <p>See more on <a href="https://nautilus.sonarqube.org/project/issues?id=demo%3Ajava-security&branch=feature%2Fcontact-feedback-form&issues=6ebe0823-14f9-40d3-9d34-1f3b8e98c316&open=6ebe0823-14f9-40d3-9d34-1f3b8e98c316">SonarQube</a></p>
|
||
| out.println("<html><body><h2>Feedback Results</h2>"); | ||
| for (Map<String, String> fb : FEEDBACKS) { | ||
| if ((email != null && !email.isEmpty() && email.equals(fb.get("email"))) || | ||
| (category != null && !category.isEmpty() && category.equals(fb.get("category")))) { | ||
| out.println("<div><b>Name:</b> " + fb.get("name") + "<br><b>Email:</b> " + fb.get("email") + "<br><b>Category:</b> " + fb.get("category") + "<br><b>Feedback:</b> " + fb.get("feedback") + "</div><hr>"); | ||
| } | ||
| } | ||
| out.println("<a href='contact-feedback.jsp'>Back</a></body></html>"); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| <!-- | ||
| This JSP renders a CAPTCHA image and input field for the contact feedback form. | ||
| The CAPTCHA will use an obsolete library in a later step. | ||
| --> | ||
| <div class="form-group"> | ||
| <label for="captcha">CAPTCHA:</label> | ||
| <img src="captcha-image" alt="CAPTCHA" /> | ||
| <input type="text" id="captcha" name="captcha" required> | ||
| </div> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <title>Contact Feedback Form</title> | ||
| <style> | ||
| body { | ||
| font-family: Arial, sans-serif; | ||
| max-width: 600px; | ||
| margin: 50px auto; | ||
| padding: 20px; | ||
| } | ||
| .form-group { | ||
| margin-bottom: 15px; | ||
| } | ||
| label { | ||
| display: block; | ||
| margin-bottom: 5px; | ||
| font-weight: bold; | ||
| } | ||
| input[type="text"], input[type="email"], textarea, select { | ||
| width: 100%; | ||
| padding: 8px; | ||
| border: 1px solid #ccc; | ||
| border-radius: 4px; | ||
| } | ||
| textarea { | ||
| height: 100px; | ||
| resize: vertical; | ||
| } | ||
| button { | ||
| background-color: #4CAF50; | ||
| color: white; | ||
| padding: 10px 20px; | ||
| border: none; | ||
| border-radius: 4px; | ||
| cursor: pointer; | ||
| font-size: 16px; | ||
| } | ||
| button:hover { | ||
| background-color: #45a049; | ||
| } | ||
| .search-section { | ||
| margin-top: 40px; | ||
| padding-top: 20px; | ||
| border-top: 2px solid #ccc; | ||
| } | ||
| </style> | ||
| </head> | ||
| <body> | ||
| <h1>Contact Feedback Form</h1> | ||
| <form action="contact-feedback" method="post"> | ||
| <div class="form-group"> | ||
| <label for="name">Name:</label> | ||
| <input type="text" id="name" name="name" required> | ||
| </div> | ||
| <div class="form-group"> | ||
| <label for="email">Email:</label> | ||
| <input type="email" id="email" name="email" required> | ||
| </div> | ||
| <div class="form-group"> | ||
| <label for="category">Category:</label> | ||
| <select id="category" name="category" required> | ||
| <option value="">Select a category</option> | ||
| <option value="General">General</option> | ||
| <option value="Technical">Technical</option> | ||
| <option value="Billing">Billing</option> | ||
| <option value="Feature Request">Feature Request</option> | ||
| <option value="Bug Report">Bug Report</option> | ||
| </select> | ||
| </div> | ||
| <div class="form-group"> | ||
| <label for="feedback">Feedback:</label> | ||
| <textarea id="feedback" name="feedback" required></textarea> | ||
| </div> | ||
| <%@ include file="captcha.jsp" %> | ||
| <button type="submit">Submit Feedback</button> | ||
| </form> | ||
| <div class="search-section"> | ||
| <h2>Search Feedback</h2> | ||
| <h3>Search by Email</h3> | ||
| <form action="contact-feedback" method="get"> | ||
| <div class="form-group"> | ||
| <label for="search-email">Email:</label> | ||
| <input type="text" id="search-email" name="email"> | ||
| </div> | ||
| <button type="submit">Search by Email</button> | ||
| </form> | ||
| <h3>Search by Category</h3> | ||
| <form action="contact-feedback" method="get"> | ||
| <div class="form-group"> | ||
| <label for="search-category">Category:</label> | ||
| <input type="text" id="search-category" name="category"> | ||
| </div> | ||
| <button type="submit">Search by Category</button> | ||
| </form> | ||
| </div> | ||
| </body> | ||
| </html> |
Check notice
Code scanning / SonarQube
Exceptions should not be thrown from servlet methods