Keeping Our Phones Safe: MobSF for Easy App Checks

Hey everyone! 📱💡 Wondering about the safety of the apps we use daily? I found something awesome that’s been a game-changer for me – it’s called the Mobile Security Framework, or MobSF.

Getting into it is pretty simple. To give any Android app a health check, first, grab its APK from a spot like https://apkpure.com/. Next, let MobSF take a look at it. This tool is genius; it checks apps in static and dynamic ways.

But here’s the cool part I didn’t mention before: static mode gives the app a security score and a tracking score (which is super handy by itself) and lets us download the Java code. That means we can see exactly what’s going on inside the app, making it easier to understand how it handles our data and if it respects our privacy.

Check out their GitHub page: https://github.com/MobSF/Mobile-Security-Framework-MobSF.

I ran it in Docker, and it was really straightforward. If anyone needs help, I’m happy to assist!

Let’s make keeping our digital lives secure a part of our routine, like locking our front doors. And hey, learning something new in the process is always a bonus. Stay safe and stay curious!

One data abstraction design approach

Our design approach should structured into four stages (typically applied cyclically): definition of the public interface, usage scenarios, test specification, and finally, implementation.

The design approach I describe is highly practical and low-level, involving the creation of model classes and the necessary TDD tests. This work is essential for transitioning smoothly into the development phase.

Public interface

This involves precisely identifying the public operations, understanding what they should expect or assume upon invocation (REQUIRES), identifying what they alter (MODIFIES), and specifying what outcomes they yield (EFFECTS).

For example, imagine we are designing a Microwave object. One of the operations to define in the public interface could be: “setting the cooking time.”

By specifying ‘REQUIRES,’ we define the method’s invariant, indicating the conditions that must be met for the method to function as expected. Any input value that does not fulfill these conditions falls outside our scope of responsibility for the resulting behavior, underscoring the importance of adhering to these preconditions for correct operation.

Flowchart

In the cases where the method has some complicated logic, we can add in the design a flowchart with the expected behavior.

This example is very simple, but it can be all the complex it needs the funcionality, and can have call to another objects or the same object methods.

Usage scenarios

It involves reviewing all the potential uses of your abstraction, which could lead to introducing new operations that need to be outlined.

What does that mean in practice?

Usage scenarios entail building a class with a main method to test the functionality. This hands-on approach helps determine if more methods are needed by directly assessing how well the current setup meets the intended use cases.

Test specification

This means writing a comprehensive and detailed test suite for each operation before implementing it.

Test-driven design involves writing tests after your specifications and implementing your code until the tests pass.

This testing is the best way to ensure that your implementation adheres closely to its intended specifications. The developer should continue refining the implementation until the test passes.

It is prudent to provide the development team with initially failing tests, as it aligns with the Test-Driven Development (TDD) methodology. This practice enhances the efficiency of the development process and ensures the functionality delivered is robust and aligns with the specified requirements.

Calculating Test Cases from Method Effects

We will create a test for each clause of the EFFECTS or we can create a test for each branch of the flowchart if it exists, for example:

Following the EFFECTS:

We will do a test for any branch: sunny and a person in the desert, sunny and a person in the city is not sunny.

We will combine these two branches for each possible input, one value inside ranges (negative, 0), (0, 15), (15, 25), (25, higger).

We will combine these two branches with the boundary limits, too: 0, 15, and 25.

Total: 3 branches x (4 + 3) => 21 cases to test.

Conclusion

To conclude, by providing the development team with a project that includes an abstract object, its public methods outlining the invariants, the object it modifies, and its effects, as well as flowcharts depicting the desired behavior and tests that must be passed before development is considered complete, we ensure that the development is delivered with higher quality and more swiftly.

Nuria

Exploring Damn Vulnerable Web Application (DVWA): A Powerful Tool for Cybersecurity Education


In the realm of cybersecurity education, practical experience is highly important. Understanding how vulnerabilities work and how attackers exploit them is crucial for developing effective defense strategies. In this blog post, we will explore Damn Vulnerable Web Application (DVWA), an exceptional tool designed for learning and practicing cybersecurity skills.

DVWA Objectives

DVWA is a deliberately vulnerable web application created to aid cybersecurity education. Its main objectives include:

  1. Providing a platform for practical learning: DVWA offers a secure environment where users can explore common vulnerabilities in web applications and practice exploitation techniques without causing harm to real-world systems.
  2. Demonstrating real-world scenarios: By simulating real-world scenarios, DVWA helps users understand the implications of security vulnerabilities and the potential consequences of their exploitation.
  3. Improving practical skills: Through interactive challenges, DVWA encourages users to develop practical skills to identify, exploit, and mitigate vulnerabilities in web applications, such as SQL injection, cross-site scripting (XSS), and more.

How to Install DVWA with Docker

The easiest way to install DVWA is through Docker. Follow these steps to set it up:

  1. Install Docker on your system following your platform-specific instructions.
  2. Download the DVWA project: https://github.com/digininja/DVWA
  3. Once the image is downloaded, create and run a Docker container using the following command:
   docker run --rm -it -p 80:80 vulnerables/web-dvwa

Important: As stated in the readme: Damn Vulnerable Web Application is highly vulnerable! Do not upload it to the public html folder of your hosting provider or any server exposed to the Internet, as they will be compromised.

This will start a DVWA container and run it on port 80 of your local machine.

Open your web browser and access http://localhost/setup.php to begin using DVWA.

    The first thing to do is click on Setup DVWA and then click Create / Reset database.

    Once this is done, you can log in with admin-password.

    Once inside, you will see the vulnerabilities you can practice with on the left side. Before starting, choose the security level:

    1. Low security: At the lowest security level, DVWA exposes basic vulnerabilities, making it ideal for beginners. Users can familiarize themselves with concepts like SQL injection, XSS, and command injection in a controlled environment.
    2. Medium security: The medium security level introduces additional challenges, requiring users to apply more advanced techniques to exploit vulnerabilities. It serves as a stepping stone for users to hone their skills and tackle more complex scenarios.
    3. High security: At the highest security level, DVWA implements stricter security measures, making vulnerabilities more difficult to exploit. Users must employ advanced evasion techniques and bypass security controls to succeed.

    Exploring Vulnerabilities

    One of DVWA’s notable features is its transparency in revealing the underlying code for each vulnerability. Users can quickly inspect the source code associated with a vulnerability, gaining insights into how it operates and understanding potential attack vectors.

    The source code for medium security:

    In this example, we can see that the client sends a POST request with the user ID in the body. What we can do is intercept the request and add more code to be processed in the query.

    Speaking of intercepting the request, I have to recommend Burp Suite, which is a security testing toolkit designed to assess the security of web applications by detecting and exploiting vulnerabilities.

    To do that, open Burp Suite, go to Proxy, activate Interceptor, and then open your browser. This will launch a Chromium browser where you can navigate to the page you want to intercept requests from.

    When we submit the User ID, we can see the body intercepted:

    Then, we change: id=1&Submit=Submit for id=1 union select user,password — &Submit=Submit

    And we get as a result the users, and in the last result, the database name: dvwa.

    I hope the tools I’ve shown you today are useful.

    Nuria.

    Robustness in Java: Exceptions and Assertions


    In software development, robustness is indispensable for creating reliable and efficient applications. Java, one of the most widely used programming languages, offers various tools to help achieve this goal. Two of the most powerful are exceptions and assertions, though their ability to improve code quality is often underestimated. In this post, we’ll explore how these tools can be employed for error detection and as integral parts of a proactive strategy for building robust software.

    Using Exceptions Beyond Error Handling

    Traditionally, exceptions in Java have been seen as a way to handle errors during program execution. However, their utility goes beyond merely capturing unexpected errors. Exceptions can effectively manage situations that, while not necessarily catastrophic errors, represent non-ideal or unexpected conditions in business logic.

    Practical Example: Adding Workers to Courses

    Consider a method addWorkerToCourse(Worker worker, Course course) designed to enroll workers in training courses within a company. Instead of performing prior checks or returning a boolean value indicating the operation’s success, this method can throw an exception if the worker does not meet the course requirements:

    public void addWorkerToCourse(Worker worker, Course course) throws RequirementsNotMetException {
        if (!meetsRequirements(worker, course)) {
            throw new RequirementsNotMetException("The worker does not meet the course requirements");
        }
        // Logic to add the worker to the course
    }
    

    This approach has several advantages. First, it simplifies error handling by centralizing validation within the method. Second, it enhances code readability, clarifying what conditions can prevent the operation from being successfully completed. Finally, it facilitates code reuse, as any method calling addWorkerToCourse must handle the exception, ensuring that necessary validations are not overlooked.

    Assertions to Ensure Code Quality

    Assertions are another underutilized tool in Java. Although they are executed only during development and testing (unless explicitly enabled in production), they are extremely useful for verifying that the program’s state is as expected at various execution points.

    State Verification with Assertions

    Imagine a scenario where we modify the value of a variable through a series of operations. We can use an assertion to verify that the final value is different from the initial one, helping us detect logical or state errors that might otherwise go unnoticed:

    int valueBefore = getValue();
    performOperationThatModifiesValue();
    assert getValue() != valueBefore : "The value should have changed after performing the operation";
    

    This type of check ensures that our assumptions about the program’s state are correct, crucial for preventing subtle, hard-to-track errors. Additionally, assertions during the development phase allow us to identify and correct problems before the code reaches production.

    This is especially valuable in the case of private methods, where direct unit testing may not be feasible. Assertions provide a mechanism to validate the behavior of these methods, ensuring that they function as intended, even without direct test coverage.

    The Importance of Testing Exception Throwing

    A crucial part of writing robust software is ensuring exceptions are thrown under the appropriate circumstances. This involves properly handling exceptions when they occur and verifying through unit tests that these exceptions are thrown as we expect. These tests ensure that our error-handling logic works correctly under specific conditions.

    Testing Exceptions with JUnit

    Suppose we have a method that throws a RequirementsNotMetException if a worker does not meet the requirements to be added to a course, as discussed earlier. We want to write tests that verify this exception is correctly thrown.

    Example: Test Fails if Exception Is Not Thrown

    In this example, we expect the test to fail if the code inside the try block executes without throwing the expected exception:

    @Test
    public void testAddingWorkerToCourseWithUnmetRequirements() {
        try {
            Course course = new Course(...); // Configure course
            Worker worker = new Worker(...); // Configure worker without necessary requirements
            addWorkerToCourse(worker, course);
            fail("It was not expected to reach this line of code");
        } catch (RequirementsNotMetException e) {
            System.out.println("great");
        }
    }
    

    This test verifies that the method addWorkerToCourse throws a RequirementsNotMetException when trying to add a worker who does not meet the necessary requirements. If the exception is not thrown, the test will fail due to the call to fail().

    Example: Test Fails if Exception Is Thrown

    In this example, we expect the test to fail if the code inside the try block executes throwing the exception:

    @Test
    public void testAddingWorkerToCourseWithUnmetRequirements() {
        try {
            Course course = new Course(...); // Configure course
            Worker worker = new Worker(...); // Configure worker with necessary requirements
            addWorkerToCourse(worker, course);
        } catch (RequirementsNotMetException e) {
            fail("I was not expecting exception");
        }
    }
    

    Both examples illustrate how to effectively test the throwing of exceptions in Java, ensuring that our application behaves as expected under adverse conditions. This type of testing complements our error-handing strategy and is essential to building reliable and robust software.

    Conclusion

    Exceptions and assertions are essential tools in any Java developer’s arsenal. Used correctly, they help manage errors effectively and promote writing that is cleaner, more readable, and, above all, robust code. By integrating these practices into our projects, along with a rigorous approach to exception testing, we can significantly improve the quality and reliability of our code.