Library Application Firewall

Protect any service that uses the OpenSSL library.

Spock SLAF is a Shared Library Application Firewall "SLAF". It has the purpose of protecting any service that uses the OpenSSL library. The SLAF inserts hooking to intercept all communication to detect security anomalies and block and log attacks like buffer overflow, path traversal, XSS and SQL injection. So to detect anomalies, Spock uses Deterministic Finite Automaton with rank scores to compute risks and create alerts for each context.

My beginning purpose in this project is to protect any binary that communicates with TLS using OpenSSL resources.

The motivation

The motivation for filtering the inputs of SSL_read() using a Deterministic Finite Automaton (DFA) when hooking a socket communication in C language is to improve the security of the network communication being performed by the sockets. SSL_read() is a function in the Secure Sockets Layer (SSL) library that reads data from a secure connection. By filtering the inputs to SSL_READ using a DFA, you can ensure that the data read by the sockets are safe and free from malicious content, and you can do so in a way that is efficient and does not impact the performance of the sockets.

Blocking input with shellcode content can provide several benefits, including preventing malicious code from being executed on a system. Shellcode can be a form of malicious code often used in attacks to exploit vulnerabilities in software or systems. By blocking input with shellcode content, you can prevent attackers from injecting this type of code into your system, which can help protect against attacks and reduce the risk of data loss or other damage.

Additionally, blocking shellcode input can help to prevent the accidental execution of malicious code. For example, if a user accidentally opens a file or receives an email attachment that contains a shellcode, blocking this input can prevent the code from being executed and potentially cause harm to the system.

Blocking payloads with a format string and path traversal attacks can provide several benefits, including preventing malicious code from being executed on a system and protecting against data loss or other damage.

Format string attacks are a type of vulnerability that occurs when an attacker can insert special formatting characters into a string, which can be used to manipulate the behaviour of a program or system. By blocking payloads with format string content, you can prevent attackers from using this technique to exploit vulnerabilities in your system and potentially cause harm.

Path traversal attacks, also known as directory traversal attacks, are a vulnerability that allows attackers to access files and directories outside the intended directory structure. This can be used to gain unauthorized access to sensitive data or to execute malicious code on a system. By blocking path traversal attacks, you can prevent attackers from using this technique to gain access to unauthorized files or directories, which can help protect against data loss or other damage.

Blocking payloads that try to exploit SQL injection vulnerabilities can provide several benefits, including protecting against data loss or other damage caused by malicious attacks. SQL injection is a type of vulnerability that occurs when an attacker is able to insert malicious SQL code into a database query, which can be used to gain unauthorized access to sensitive data or to execute malicious code on a system.

By blocking payloads that try to exploit SQL injection vulnerabilities, you can prevent attackers from using this technique to gain access to unauthorized data or to execute malicious code on your system. This can help to protect against data loss or other damage caused by malicious attacks.

Additionally, blocking payloads that try to exploit SQL injection vulnerabilities can also help to improve the performance and reliability of your system. Malicious SQL code can often be complex and resource-intensive, which can cause the system to become overloaded and slow down. By blocking this type of payload, you can prevent the system from being overloaded with complex or resource-intensive tasks, which can help to improve overall performance.

Overall, blocking payloads that try to exploit SQL injection vulnerabilities can provide several benefits, including protecting against data loss or other damage caused by malicious attacks and improving system performance and reliability.

Tool features

  • Action to Block, log and detect security anomalies like SQL injection, XSS, and path traversal from SSL_read() function(get input buffers).

  • Capacity to run in any programme that uses the OpenSSL library.

  • Block SQL injection attack

  • Block XSS attack

  • Block path traversal attack

  • Block remote buffer overflow attack(detect arch of binary and use a custom list of shellcodes)

  • Block format string attacks

  • If detect any anomaly in the TLS context, Spock saves the IP address of the attacker, date time and attack "payload" register in the log file.

Etymology

The motivation for this tool was released during a mitigation project in the past seven years. Following my freelancer task, an old client disclosed a problem around deprecated proprietary binary with many vulnerabilities like Heap buffer overflows, remote buffer overflow and path traversal. The big problem of binary context is the application turn abandonware with no patch fixes, but the enterprise needs to run production loads. So my solution was to insert seccomp() to restrict syscalls in the process(you know, block calls like system()/execv()). I replaced libc's malloc() with "DieHard", an error-resistant memory allocator. On the other hand, another initiative was little hooking in OpenSSL's SSL_read() function to restrict some evil payloads, another option.

Another option is to use libreSSL and up a monitor to listen if it has a compatibility bug. The lousy point of LibreSSL is the performance; you can see that if you use a tool like gprof to get a benchmark between OpenSSL and LibreSSL. So OpenSSL is cool but not safest as LibreSSL or lib Sodium. Looking at the performance context, if you get arithmetic functions to big int of OpenSSL, some resources like Big int operations BN_new() do not have a good performance like libGMP. So relax. Performance is not always the best path for security. Security validations and extra buffers, and proper bounds checks have an expected cost. Without this, you can see a lot of problems for example looking to spectre/meltdown in the past.

Following additional facts, external rules of server using BSD's firewall(aka packet filter), using custom rules to allow only by IP and OS fingerprint. So that freelancer task stuck in my mind. Now you can see my new solution following a global approach to protect TLS communication in the server context.

Proof of concept

The first step compile to deploy

Clone the repository:

$ git clone https://github.com/CoolerVoid/spock_slaf

Enter in the folder:

$ cd CoolerVoid/spock_slaf

Compile the content:

$ make clean; make

Now you can see the shared library "spock_slaf.so.1" in "bin" directory.

The second step injects to protect

The second step is to inject a shared library in your binary that uses OpenSSL following the communication context(server).

So now we can use LD_PRELOAD trick:

$ LD_PRELOAD=/home/cooler/spock_slaf/bin/spock_slaf.so.1 bin/rest_server
# note: change /home/cooler/spock_slaf/bin/ to your full path name

Looking at this example, so has been tested in a simple rest server. If anyone attacks the rest_server, you can see the full log in the file "spock_agressors.log".

Extra tips and tricks for customization

  • You can customize the score rank to detect the anomaly if you set macro SPOCK_SCORE to any number between 1 to 10(a low number is more sensitive).

  • You can customize the list of attack payloads to block. Please look at the source code.

  • You can gain performance in the HTTP context if you set macro SPOCK_ONLY_HTTP to "1" in the source code.

  • You can remove debug mode if you set macro SPOCK_BUGVIEW to "0" in the source code.

Understand anti buffer overflow trap

So Spock detects shellcode in payloads and blocks attacks of memory corruption, following common chunks in registers for the context of the binary in execution, for example, detecting x32 or x64 architecture and blocking specific attacks for architecture.

#if UINTPTR_MAX == 0xffffffffffffffff
	const char *custom_shellcode[] = 
	{
		"\\x48\\x31\\xc0",                    // xor    rax,rax  X64 LINUX
		"\\x48\\x31\\xdb",                    // xor    rbx,rbx  X64 LINUX
	    	"\\x48\\x31\\xff",                    // xor    rdi,rdi  X64 LINUX
	    	"\\x48\\x31\\xf6",                    // xor    rsi,rsi  X64 LINUX
	    	"\\x48\\x31\\xd2",                    // xor    rdx,rdx  X64 LINUX
	    	"\\x48\\x89\\xe6",                    // mov    rsp,rsi  x64 LINUX 
	    	"\\x48\\x89\\xe7"                    // mov    rsp,rdi  x64 LINUX
	};
#elif UINTPTR_MAX == 0xffffffff	
	const char *custom_shellcode[] = 
	{
		"\\x31\\xc0",                         // xor    eax,eax  x32 LINUX
	    	"\\x31\\xc9",                         // xor    ecx,ecx  X32 LINUX
	    	"\\x31\\xdb",                         // xor    ebx,ebx  x32 LINUX
	    	"\\x31\\xd2",                         // xor    edx,edx  X32 LINUX
	    	"\\x89\\xe1",                         // mov    esp,ecx  x32 LINUX
	    	"\\x89\\xe3"                         // mov    esp,ebx  X32 LINUX
	};
#endif
	// ARM, MIPS in the future -- TODO


// generic payloads to block

	const char *list[] = 
	{
		"\\x90\\x90", // block NOP
		"\\x00\\x00", // nullbyte
		"\\xcd\\x80", // int $0x80 

So in additional point, Spock uses a custom allocator using OpenBSD practices to prevent integer overflow:

// Fork of OpenBSD's function
/*
 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
 */
#define SPOCK_MUL_NO_OVERFLOW	((size_t)1 << (sizeof(size_t) * 4))

void *
spock_reallocarray(void *optr, size_t nmemb, size_t size)
{
		if ((nmemb >= SPOCK_MUL_NO_OVERFLOW || size >= SPOCK_MUL_NO_OVERFLOW) &&
		    nmemb > 0 && SIZE_MAX / nmemb < size) 
		{
			errno = ENOMEM;
			return NULL;
		}
	return spock_xrealloc(optr, size * nmemb);
}

Thank you

  • Thank you for using my tool. Any problem with the tool or suggestion, please open a GitHub issue in this repository. I will be delighted to help anyone.

  • Curious fact: Spock is my dog's name and a little homage to the Star Trek series.

References

Last updated