You are on page 1of 11

51.

503 - Secure Software Engineering

To prevent Payment Tampering attacks, developers should implement proper


security measures such as:
1. HTTPS: Implementing HTTPS (TLS/SSL) for web transactions can ensure
that the communication between the client and server is encrypted and
secure. This can prevent attackers from intercepting and modifying payment
requests.
2. Input validation and sanitization: Implement proper input validation and
sanitization techniques to prevent modification of payment parameters. This
can prevent attackers from injecting malicious code or changing payment
parameters.
3. Implement secure payment gateways: Use secure payment gateways that
implement authentication and authorization measures to ensure that only
authorised users can access the payment gateway.
4. Implement access controls: Implement access controls to ensure that only
authorised users can access payment-related data and transactions. This can
prevent unauthorised modifications to payment-related data.

60
51.503 - Secure Software Engineering

7. Model Checking
LTL (Linear Temporal Logic) model checking is a formal verification technique used
to ensure that a system meets a given specification expressed in LTL formula. In
LTL, a formula is made up of temporal operators that allow for the expression of
properties that hold over time. In LTL model checking, the function under verification
is modelled as a transition function consisting of a set of states and transitions
between them. The LTL formula is then expressed as a set of properties that must
hold for the function in all possible executions.

The model checker verifies the function against the LTL formula by exhaustively
exploring all possible states and transitions. The model checker checks if the system
satisfies the LTL formula by evaluating it against each possible execution of the
system. If the model checker exhaustively explores all possible executions and the
LTL formula holds for all of them, the system is considered to be verified.

We selected the function “updateItem()” in “views.py”, as shown below, to perform


model checking.

def updateItem(request):
data = json.loads(request.body)
productId = data['productId']
action = data['action']
print('Action:', action)
print('Product:', productId)

customer = request.user.customer
product = Product.objects.get(id=productId)
order, created = Order.objects.get_or_create(customer=customer,
complete=False)

orderItem, created = OrderItem.objects.get_or_create(order=order,


product=product)

if action == 'add':
orderItem.quantity = (orderItem.quantity + 1)
elif action == 'remove':
orderItem.quantity = (orderItem.quantity - 1)

orderItem.save()

if orderItem.quantity <= 0:
orderItem.delete()

61
51.503 - Secure Software Engineering

return JsonResponse('Item was added', safe=False)

To create a formal model of the function, we used a formal modelling language,


Promela, which can be used with the Spin model checker. The formal model should
represent the behaviour of the function in a precise and unambiguous way. The
derived formal model based on the function is as shown below.

mtype ADD, REMOVE;


bool run_done = false;
byte quantity = 0;

active proctype t() {


do
:: atomic {
ADD -> quantity = quantity + 1;
}
:: atomic {
REMOVE -> quantity = quantity - 1;
if
:: quantity < 0 -> quantity = 0;
:: else -> skip;
fi;
}
od;
run_done = true;
}

ltl p1 { [] (run_done -> quantity >= 0) }


ltl p2 { [] ((quantity <= 0) -> ([] (quantity == 0))) }
ltl p3 { [] ((quantity > 0) -> ([] (quantity >= 0))) }

init {
run t();
}

The code defines a simple function that has two types of messages - ADD and
REMOVE. It consists of a single process named "t" that executes an infinite loop and
waits for these messages. When it receives an ADD message, it increments the
quantity variable and prints a message that shows the new quantity. Similarly, when
it receives a REMOVE message, it decrements the quantity variable and prints a

62
51.503 - Secure Software Engineering

message showing the new quantity. The ADD and REMOVE statements are atomic,
meaning they cannot be interrupted by other processes. If the value of quantity
becomes negative after decrementing, it is reset to 0. This is similar to the function
updateItem()

The system has three LTL properties that check whether the conditions are satisfied.

1) p1 { [] (run_done -> quantity >= 0) }: Checks that when process "t" has
completed executing (i.e., run_done is true), the quantity variable is always
greater than or equal to 0. This property ensures that the system always
terminates with a non-negative quantity value.
2) p2 { [] ((quantity <= 0) -> ([] (quantity == 0))) }: Checks that if the quantity
variable ever becomes less than or equal to 0, it will eventually become 0.
This property ensures that the system eventually reaches a state where the
quantity is 0, in case the quantity goes negative due to an unexpected event.
3) p3 { [] ((quantity > 0) -> ([] (quantity >= 0))) }: Checks that if the quantity
variable ever becomes greater than 0, it will always remain greater than or
equal to 0. This property ensures that the system never allows the quantity
variable to become negative.

To check the properties, we used the Spin model checker. The model was saved as
proj.pml and we executed the Spin model checker on the model i.e. “spin -a
proj.xml”. This would result in the generation of “pan.c” where we compiled it using
the command “gcc -o proj pan.c” which would create an executable named “proj”, as
shown in Figure 7.2.

Figure 7.1.: Generation of executable “proj”


Three separate commands were then executed to determine if the respective
properties were satisfied
- ./proj -a -N p1
- ./proj -a -N p2

63
51.503 - Secure Software Engineering

- ./proj -a -N p3

For each LTL formula, a full state space search to check if the formula is satisfied or
violated by the function described in the Promela code was performed. The output
includes various statistics about the search process, such as the number of states
explored and the amount of memory used.

In all three cases, as shown in Figure 7.2 to 7.4 below, SPIN did not find any errors,
which is indicated by the "errors: 0" line in each section. However, there are some
states in the system that are marked as "unreached", which means that they cannot
be reached during the execution of the system. These states are listed under the
"unreached in" sections. Overall, the output indicates that the Promela code satisfied
all three LTL formulas and does not have any errors.

64
51.503 - Secure Software Engineering

Figure 7.2: Results for p1

65
51.503 - Secure Software Engineering

Figure 7.3: Results for p2

66
51.503 - Secure Software Engineering

Figure 7.4: Results for p3

67
51.503 - Secure Software Engineering

8. Summary and Key Findings

Security by design is a proactive approach to software development that prioritises


security from the outset of the development process. It involves integrating security
into every aspect of the software development lifecycle, from design to coding to
testing and deployment. Secure coding is an important step in implementing a
security by design approach, as it involves writing code with security in mind.

Secure coding is critical in creating secure software applications because it helps


prevent vulnerabilities and weaknesses that attackers can exploit. By incorporating
security into the coding process, developers can ensure that security is a
fundamental component of their software. It is important to note that secure coding is
more than just writing code; it also involves comprehensive testing to identify and
mitigate security vulnerabilities and weaknesses. Secure coding testing has gone
beyond traditional testing methods and focuses on identifying security flaws and
vulnerabilities that can be exploited by attackers. These types of tests include code
reviews, static code analysis, and dynamic code analysis, black-box testing,
grey-box testing, penetration testing, vulnerability assessments, and to the extent,
formal checking, to identify potential security weaknesses and vulnerabilities

However, secure coding is just one aspect of security by design. It is important to


approach software development with a holistic view of security, considering not just
the code, but also the architecture, deployment environment, and other aspects of
the system. This can include implementing secure design patterns, performing threat
modelling, and using secure development frameworks.

Through the project, we observed the heavy reliance on third-party libraries and
framework i.e. Django in the eCommence application. This may potentially result in
software supply chain issues which are becoming increasingly common. When
developers use third-party code, they are introducing unknown code into their own
applications, which can be a security risk. Dependencies can have vulnerabilities,
backdoors, or other flaws that can be exploited by attackers to gain access to
sensitive information or systems. If a dependency is compromised, it can put the
entire software supply chain at risk.

Therefore, developers should carefully manage their dependencies by keeping them


up to date, monitoring for security issues, and implementing vulnerability scans or
other security checks. Developers should also ensure that they are using trusted
sources for their dependencies and that they have a clear understanding of what the
code does and how it interacts with their own code. It is important to have clear
policies and procedures in place for managing dependencies, including regular
audits and risk assessments.

68
51.503 - Secure Software Engineering

Effective dependency management is a critical part of secure software development,


and organisations should take a proactive approach to identifying and mitigating
software supply chain risks, including those related to third-party dependencies. By
implementing strong security practices and closely monitoring their code, developers
can help ensure that their applications are as secure and reliable as possible.

69
51.503 - Secure Software Engineering

9. References
Django Software Foundation. (n.d.). Django. Django Project. Retrieved April
1, 2023, from https://docs.djangoproject.com/en/4.2/

Ivy, D. (2021, March 22). Divanov11/Django_ecommerce_mod5. GitHub.


Retrieved April 1, 2023, from
https://github.com/divanov11/django_ecommerce_mod5/

Nimble-Code. (n.d.). Nimble-code/SPIN: Explicit state logic model checking


tool -- 2002 winner of the ACM System Software Award. GitHub.
Retrieved April 10, 2023, from https://github.com/nimble-code/Spin

SonarSource. (2023). Python static code analysis: Unique rules to find Bugs,
Vulnerabilities, Security Hotspots, and Code Smells in your PYTHON
code. SonarSource Rules. Retrieved April 1, 2023, from
https://rules.sonarsource.com/python

70

You might also like