Nothing is more vulnerable to any kind of attack than the compositions of different components. In fact, better perimeter protection is one of the tactical advantages of the old silo approach, and no one can deny this. You could protect your service compositions made from the same service domain because you can control it in the same way as a silo; however, if there is a single participant (composition member) outside of the domain's premises, all security concerns will multiply drastically.
In this chapter, we will be faced with quite a few challenges, some of which we have already mentioned. Firstly, native-born security architects have completely different mindsets than solution architects. We cannot ask you to forget all that you have already learned from previous chapters, but we will try to introduce you to another way of thinking using our knowledge of patterns and frameworks.
In about 40 pages, we will do our best to systematically cover all the common techniques and approaches used in SOA security patterns, with references to best practices and publications. Most (if not all) books dedicated to SOA security that you find on Amazon will be dated 2008, 2005, or even 2003, and do not cover the latest standards development (OAuth, SAML, and PKI) and recent tools. Probably the best (in our opinion) paperback, Securing Web Services with WS-Security: Demystifying WS-Security, WS-Policy, SAML, XML Signature, and XML Encryption, was published in 2004. Thus, in this chapter, we will not capture the immensity of the SOA security topic and instead focus on layered protection, realized by standard SOA patterns. This layered protection cannot be covered without touching upon SOA-specific attacks aimed at SOA-specific vulnerabilities. Patterns will demonstrate how to mitigate security risks common to SOA implementations.
We would like to start with a quote from a security report based on research of 110 companies from industries including financial services, the government, and IT. The quote is quite long but really interesting:
How old do you think this report is? Twenty years, maybe ten? Not at all. The results of this survey (http://www.oracle.com/us/corporate/press/1972875) were published in mid 2013. Take a look at the Oracle SOA development roadmap table (Chapter 2, An Introduction to Oracle Fusion – a Solid Foundation for Service Inventory). Basic Security Profile Version 1.1 was published in 2009 and this profile de facto has finalized all security standards developed for more than 10 years. You do not have to be a pentester to understand that something is wrong here. The question is, how bad?
No, this is not bad, because the word bad is not capable enough to describe how horrible the actual situation is! It simply means that in at least 66 percent of cases, vital information about your clients, financial transactions, planned merges/acquisitions, employees' private data, and strategic development/products is already in the caring hands of your diligently watchful competitor(s). It also means that this information in two-thirds of cases can be acquired within two days without significant investments into complex sniffing equipment. Yet again, in most cases, it's in the best interest of intruders to keep your data intact and hide all evidence of the security breach.
Without a doubt, the human factor is crucial in any security system; however, discussing this is beyond the scope of this book. Nevertheless, you have to contemplate the fact that about 90 percent of all information leakages are carried out or initiated internally. Yes, sometimes unintentionally, but even good intentions (or the absence of bad ones) provide sufficient basis for anecdotic stories about lost or forgotten notebooks or CDs by agents of one kingdom with allegedly the most proficient secret service in the world. As a result of this contemplation, a clear understanding must be firmly implanted in your mind; in SOA environments, starting from moderate complexity and higher, with more than two service domains and the presence of intermediary, the reliance on TLS/SSL alone is no better than publishing your connection strings with a username/password on your corporate front page.
In this chapter, we will start with an analysis of the situation in order to formalize essential solutions patterns capable of reducing security risks.
We would like to begin our analysis with an old saying: a chain is no stronger than its weakest link. Banal, isn't it? Sorry about that, but indeed with four architectural SOA levels, everything comes down to the resiliency of the single-service implementation, which is in the lowest architectural service layer. As long as any particular service is a composition of services (Task or Task-orchestrated service), the three basic building blocks of SOA infrastructure can be identified. The first two are Utility and Entity service models, usually employed to compose the Task service(s). The third is a Service engine (which is not a small thing, but you will probably rely on an existing one instead of inventing your own for commercial realization). An Entity service's internal architecture is usually more complex than a Utility service, as it commonly involves DB as the entity's persistence storage. Therefore, from the static implementation standpoint, all four enterprise SOA layers will be protected proportionally to the level of security resilience of the Entity service anatomy, and you certainly remember its every single block:
NullPointerException
? Is your code thread-safe? How about memory utilization and stack control, global variables, and so on? If you do not know this, how can you be sure that your main architectural block is safe? A stack/buffer overflow attack is one of the most popular ways of breaking into your system and is commonly focused on components' implementation.Here we mentioned only three internal services elements susceptible to attacks, but these attacks are the most common and truly devastating. Common to these types of vulnerabilities and attacks is that their target is static core service logic, encapsulated in component or groups of components. However, this doesn't make them similar to the classic security issues of the silo approach because we have the second native part of SOA—the service interactions.
Services or components have to communicate with each other in order to carry out their business tasks. What's worse for security personnel is that they have to perform it dynamically, depending on numerous business conditions that involve a considerable amount of external resources in an agnostic manner (see the CTU example, discussed in previous chapters). We do not have strict domain security boundaries anymore because one message can carry information about different (even business-opposing) parties. Different parts of the message can be transformed or enriched separately by independent intermediaries and so on. Information Confidentiality, Integrity, Non-Repudiation, and Origin are constantly at risk when we have something in transit, and we constantly do. Thus, certain measures (in the form of Patterns) shall be applied in order to protect the aforementioned information properties. Luckily, these measures, covered by WS-* specs as Encryption, Digital Signature, and Portable Trust, are quite mature and far older than the SOA concept itself.
Before we go into the risk analysis, vulnerabilities, and SOA-related attacks, we would like to jump ahead to some generic conclusions:
You don't have to build everything from scratch. There are plenty of appropriate tools and libraries and you, as an architect, should just put them (or apply the patterns) in the right place. Again, a good starting point could be to maintain OWASP's terms and terminology within your team—the common understanding of spoofing, surreptitious forwarding, stack smashing, and so on. For the same reason, we will just follow the already proposed classification, avoiding unnecessary reinvention.
To illustrate the risks of having a poor understanding of security design, a highly respectable IT company, and pioneer in event processing and BPMN, participated in CTU's RFI process. Lacking the COTS market-proven security solution, this company proposed a custom package, developed for other customers over several years. The proprietary Security Perimeter was proposed to the completely stunned architects where scans for the threatening content was executed after authentication. Further still, the scanner itself was based on the standard XML parser. Having said that, in this chapter, we will not present you with the custom solution as we did before for ESB and adapters. Instead, we will talk about the API Gateway, a relatively new Oracle strategic product capable of covering five out of eight common SOA security patterns.
From the proven SOA Pattern Catalog, we have eight security patterns: four for service implementation (Group I for static service implementation, starting from Exception Shielding; http://soapatterns.org/design_patterns/exception_shielding) and four to protect service interactions (Group II for service messages in transit). Some of the patterns such as Data Confidentiality and Data Origin Authentication (group II, see http://soapatterns.org/design_patterns/data_confidentiality) are in fact the direct realization of the WS-Security standard, WSS (see https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wss), covering two main W3C specifications: XML Encryption (http://www.w3.org/TR/xmlenc-core/) and XML Signature (http://www.w3.org/TR/xmldsig-core/). Since they are of the utmost importance, they are well covered in all the books we have already mentioned, so we will not focus on them much.
The Trusted Subsytem in its turn (group I) is a security-related extension of the Contract Centralization pattern, designed to prevent access to service resources, bypassing the standard service contract and associated security policies. Thus, there are five patterns left: two related to Authentication and Authorization and three that can be implemented (centralized) by the so-called Security Perimeter. To understand their roles and importance, we will proceed with the most common vulnerabilities first.
Think of military operations in close encounters. Your service domain has a certain edge that is in one way or another exposed to the world outside. (If it's not exposed, you are the lucky one! Why are you reading this?) This edge is actually the skirmish point, where the attacker methodically shoots and observes, trying different weapons. A publicly exposed contract (WSDL/REST) gives enough information for the imposter to devise the initial weapon of choice, for example, service operations or an XSD structure—everything is there, so an attacker has an undisputed tactical advantage. Vaguely defined XSD (types any
or string
for all elements) just makes more room for experiments (in case your attacker is bored) and intercepted valid messages can give the attacker a quite a good understanding of the possible data ranges.
One option is to not expose the WSDL definition (hide the API documentation or at least remove all the comments from WSDL). Well, the secluded contract is not really inline with the Composability principle. However, what about your UDDI? It is similar to the DNS server for IP networks and susceptible to similar attacks. UDDI-crawling attacks can turn your own versioning strategy against you if you keep old, less secure contracts available for backward compatibility.
In any case, the attacker will be looking for a response from your service—the more elaborative the better. Ideally, a complete error stack trace is what the attacker is dreaming of (an entire unhandled SOAP error with faultString
is good enough), but in fact, any piece of information is welcome. Needless to say that the biggest portion of this information will be provided by your Error Handlers (EH) at all levels; therefore, vulnerabilities in EH design shall be discussed first.
It would be a mistake to think that the standard HTTP response or no response at all will considerably improve the overall security. Blind-type injection is one of the most difficult injections for attackers, but it is still quite able to deliver results and standard responses can be mapped to attack types and they are informative enough.
Surely our goal is to make the attacker's life hard, but our developers and operation will be proportionally affected as the Discoverability principle is sacrificed.
Here, we will combine the most common error handling vulnerabilities, allowing attackers to explore your line of defense and collect all the necessary technical information about your services for further steps, aiming at authentication/authorization weaknesses. The methods are quite obvious:
return_acknowledge_till<…>
), try to resend the message (as an active intermediary) within this interval. Interestingly enough, it's not that rare that for an add<something>
operation, the attacker gets a message acknowledging the error, with faultString
containing the primary key violation along with the constraint name, table name, and some additional information about DB itself.evilize
library; for an example by Peter Selinger, see http://www.mathstat.dal.ca/~selinger/md5collision/). Anyway, these attacks will be undertaken after studying the message structure and the response.ds:nodes
containing the following code can be easily stripped by the attacker and a message will still be accepted:<SignatureValue> WkZUJAJ/0QNqzQvwne2vvy8U5Pck8ZZ5UTa6pIwR7GE+OoGi6A1kyw== </SignatureValue>
The important thing is that whatever hacking technique is employed by the attacker, the initial step is always the same: gather as much information from your service response message as possible. Your Error Handler is the major supplier of this information.
Regarding the following vulnerability list, feel free to use your own labels (alphanumerical codes) for all kinds of vulnerabilities. As you go further, you will need them as flags to mark potential weaknesses on the technical infrastructure map.
The vulnerability code for information leakage is
EH01
. Take a look at the common catch
block:
catch (Exception ex){ ex.printStackTrace(); System.out.println(ex); }
What is good for the logfile in a Dev or JIT environment is a disaster in production and definitely should be avoided in a SOAP error response.
The vulnerability code for missing error handling is EH02
.
Standard HTTP response codes 4XX (Unauthorized, Bad Request, Forbidden, Not Found, Method Not Allowed, and so on) are quite often employed in REST-based APIs. Firstly, they are already quite informative for the attacker. Secondly, using standard handlers instead of fine-tuned handlers in your services could not only potentially reveal service technical information (presence of resources, class/resource hierarchy, and methods availability) or service business logic, but can also make the life of your developers difficult if mapping is too generic.
We also have to mention that redirection of everything to a single generic error page or attempts to map 403 to 404 and so on (with the intention of deceiving the attacker) will primarily affect service consumers and ops, not the culprit.
The vulnerability code is EH03
. The following code is another quite common block:
try { provideService(); } catch (SomeUnusualException ex){ // our system is quite resilient and we do not care about low-probability cases }
Note two things here: practical—if this unusual exception ever occurs, you will have no information about it, and philosophical—you better believe it will happen. A developer's laziness is the attacker's best friend. Peer review is an essential part of an architect's tasks. Some tools from the following section can help you.
The vulnerability code for catching NullPointerException
is EH04
.
Catching NullPointerException
doesn't make much sense. Generally, this is not a runtime exception we should handle in a catch
section. In general, it's the lack of coding culture (note, we are not accusing anyone) and if you have filthy code, none of the existing perimeter protection systems or IDS can protect you. Sorry, that is just the way it is. Here are the tools you can use for static and dynamic analysis of your code:
The vulnerability code for the
return
statement inside the finally
block is EH05
.
All errors that might occur or are thrown in the try
block will be ignored by the return
statement in the finally
block:
Object ObjectHandlingMethod() { Object o = null; .... try { o = MethodErrorThrower(); } finally { CleanUpRoutines(); return o; } } Object HandlerErrorThrower(){ ... if (size == 0) { throw new EmptyStackException(); } catch{ logerror() } ... }
An exception is thrown in the other method, called from the core class. An error was caught and even properly logged, but it wasn't propagated back to the caller. The return
statement in the finally
block is choking any exceptions, making the code not only unsafe, but also very hard to maintain.
The vulnerability code for inappropriate cleaning is EH06
.
As you can see from the preceding code, we have CleanUpRoutines()
in the finally
block. This is a mandatory part for any final block—all connections must be closed, file pointer released, threads unlocked, and memory cleaned from the loop-related variables. This is highly important as some attacks are not only aimed at revealing technical implementation details but also at depleting the service resources.
The vulnerability code for handling dissimilar exceptions in the same block is EH07
.
This situation is quite close to the one described for vulnerability with code EH02
and can also be presented by using the same exception handler for differed named exceptions. An indiscriminate handler will not only open the door to the mishandling of complex situations simulated by an attacker, but also will leave an unclear trace record in the system's logs, blinding the response/ops team.
Here we mostly talk about API authentication (System-to-System) and not just about human and web page interactions (although it's also based on SOAP and REST services, serving direct and brokered authentication). In this case, arguably, you can assume the main authentication weakness of all time—the password strength can be finally tamed as the API is not affected by typical human factors, that is, the ability to remember passwords (or leaving yellow sticky notes on the monitor). Indeed, just from a password strength calculator (you will find a lot of them on the Web), we can see that a four-character password, which is common for humans, can be brute forced in a couple of minutes, while a 20-character API key will take ages (with adequate OS (Linux/Unix/Windows) file protection in place, of course).
Well, our optimism should be very cautious about that though. Not too long ago, we were able to use Amazon S3 and EC2 cloud services (actually, AMIs with all our assets) to log in with our regular Amazon shopping account. So naturally, as mentioned earlier, using signature-wrapping (stripping) and cross-site scripting (XSS) attacks, pentesters were able to compromise these Shopping and EC2 credentials and gain total control over the victim's account with virtual machines containing stored code and data. Should we mention the victim's shopping cart? Should we also mention that EC2 is probably the most popular sandbox for developers from several leading companies?
We believe that this vulnerability is already mended by Amazon, but we can add several good recommendations to our list of security design rules from the preceding case:
Generally, gaining direct access by exploiting or resending SOAP/REST messages is a kind of gamble and will require not only inefficiency in security design, but also a little luck as well, and usually attackers do not count on that. After the identification of the backend system's types by studying response messages, the attacker will perform the following tasks:
For some reason (for instance, license policy), you can decide to use an MS SQL database as the backend for certain critical products such as the Oracle Enterprise Repository. That's perfectly fine, but you (your DBA) forgot to disable xp_cmdshell
(or better, delete xpsql70.dll
, drop EXEC sp_dropextendedproc @functname='xp_cmdshell'
, and forget about its existence). What's worse is that the backend resources are shared (which is common) and some services are used as a Trusted Subsystem with SA privileges. This is the perfect recipe for a successful SQL injection attack as well as an invitation to gain full control over all your resources. These types of attacks are well documented and included in OWASP. Countermeasures that have already been mentioned include not giving your service account more privileges than is really necessary. (Frankly, we all know where it comes from—on a Dev server, our developers focus on functionality first and security granularity later. Please do peer review for the component's code and installation scripts including DB.) In addition to the already mentioned vulnerabilities, the most common authentication and authorization (AA) vulnerabilities are gathered in the following sections.
The vulnerability code for a simple authentication protocol is AU01
.
Utilize the Diffie-Hellman scheme to create a session random hash value. This type of authentication is quite susceptible to reflection attacks, that is, when an attacker creates the second handshake session using the challenge obtained during the first (incomplete) one.
The vulnerability code for password system exploits is AU02
:
String plainText = new String(plainTextIn) MessageDigestencer = MessageDigest.getInstance("SHA"); encer.update(plainTextIn); byte[] digest = password.digest(); if (digest==secret_password()){ //log me in }
The failure of a password authentication mechanism will almost always result in attackers being authorized as valid users.
The vulnerability code is AU03
.
The HTTP header element as defined by W3.org is Referer = "Referer" ":" ( absoluteURI | relativeURI)
. The J2EE code for extracting a fields value for further authentication is HttpServletRequest.getHeader("referer")
. In fact, the Referer
field in HTML requests can be simply modified by malicious users.
The vulnerability code for the authentication decision based on the DNS name resolution is AU04
:
import java.net.InetAddress; public class Authenticator { public boolean authByHostname (String clientIP) throws Exception { booleansafe = false; InetAddress address =InetAddress.getByName(clientIP); String hostname=address.getHostName(); String canonicalhostname = address.getCanonicalHostName(); If (canonicalhostname.endsWith("trustedsite.com")) { safe = true; } return safe; } }
You cannot control external DNS servers. All that is in there (IP/name mapping, cache, and registering APIs) one day can be poisoned and compromised. Traffic can be routed to the ghosts controlled by culprits, where IP addresses, names, and host attributes will be mocked as trusted. Simply put, don't trust anything coming from outside, especially from DNS, and do not base your authentication on these attributes.
The vulnerability code for single-factor authentication is AU05
.
Consider a dual-factor authentication as significantly more secure. Increasing the factor will certainly increase authentication resilience, but it could have a negative effect on performance (depending on the number of authentications per second, and it must be evaluated case by case).
The vulnerability code for Least Privilege Violation is
AZ01
.
The elevated privilege level required to perform operations such as chroot()
should be dropped immediately after the operation is performed.
Most commonly, this vulnerability is exploited when your service, acting as a Trusted Subsystem, uses the elevated privilege level, accessing the common resources.
Vulnerabilities represent risks materialized (or maybe not, depending on how good we are) through various attacks. Any project (at least in practice) has a risk assessment. Security risks are the main part, especially for services with external exposure. This section is critical and must stay tuned with the current security trends. OWASP is one of the primary sources of trend information.
We took the OWASP top 10 data for 2013 (https://www.owasp.org/index.php/Top_10_2013) and mapped it to the standard SOA security patterns, capable of mitigating these threats.
Anything that can be inserted, implanted, or simply added to the command line or DB query string could not only break data consistency or add unwanted data portion to the dataset, but also execute some DB or OS command, allowing the attacker at the end to gain complete control of the victim's system.
At the very least, the system will respond with an error message, and it is the architect's responsibility to balance the SOA security, abstraction, and discoverability requirements.
Several factors make this risk number one in the top 10: difficulties in mitigation, number of attack-automation tools, and potential devastation.
The following are the suggested patterns to apply:
The factors that can lead to insufficient authentication are reliance on weak passwords, single-factor authentications, unreliable/compromised protocols, algorithms (such as MD5), the usage of digital signature without encryption (and vice versa), too short or repeatedly reused session keys, a simplified nonce, the possibility to compare protected and unprotected messages, revealing/loss of private keys and certificates, storing passwords as clear text in AIM DB, and misconfiguration of trusted subsystems that allow the bypassing of the service contract and accessing the service resources directly.
The following are the suggested patterns to apply:
The distributed way of handling a service request is quite common. What's more is a single message can be addressed to separate services in parallel or sequentially. Intercepted (the man-in-the-middle attack) and forged in certain parts, impersonating trusted parties (see Trusted Subsystem pattern, http://soapatterns.org/design_patterns/trusted_subsystem), a message can cause session hijacking, malicious redirections, and the exposure of sensitive data. As we mentioned earlier, an attack on Amazon was successful because the application signature verification and XML interpretation were handled separately. Yet again, Amazon is quite protected now against XSS. Are you?
The following are the suggested patterns to apply:
The usage of FSO configuration elements is inevitable (for example, XML, INI, or property files), especially close to the skirmish point. The developer's logic is simple: "I cannot use full-fledged DB in DMZ; it's too heavy and has many weaknesses. The amount of config data I will use in my utility service (or agent) dynamically is insignificant and I can use simple XML instead, staying flexible and configurable at the same time." The logic is flawless, but do we have file consistency checks every time we access it? Do we have adequate file protection from the OS side? What if the attacker, by executing a buffer overflow attack, causes a segmentation fault, halts the program execution (exits abnormally), gains control over the program's resources (not exactly root!), substitutes/modifies the file, and lets the system restart the process? This means that the service agent infrastructure (part of the SOA architecture) is equally vulnerable to attacks as are common entity services because agents are common event-driven programs utilized in all service interactions (imagine the agent checking the elements of the <string>
type for the acceptable length) and, sometimes, their log footprint is so small that you will have a hard time finding the real problem.
The following are the suggested patterns to apply:
This pattern will be applied to every service and agent in the SOA infrastructure. This is a joint task for an architect, OS administrator, and security specialist, and must be performed during a peer review. Every single call to a resource shall be validated and tested. As most common attacks here will be related to buffer overflows, you have to decide on want type of code (that is, language) you want to implement your protection, especially close to DMZ—managed (Java) or unmanaged (C).
Speaking of mandatory configuration routines, please do the basic sanity check by asking yourself the following questions: has LDAP synchronization managed with open protocol (not SSL)? Have you applied security patches or are you afraid of breaking something in production (alternatively, have you applied the wrong patch)? Do you encrypt HD with sensitive data? Have you forgotten to update the Certificate Revocation List? Have you run a service under the root privileges? Do you keep your firewall ports configured by default (it's still not a problem to find which are opened, but we do not want to give the bad guys a chance to slack)? Still believe that WEP is unbreakable (in addition, allowing guest WEP-based Wi-Fi access to corporate data)?
This sanity checklist is not complete, but we have no intention to publish a corporate red book with all security do's and don'ts.
Another noteworthy point is that you can play and have a lot of fun with honeypots and honeynets, but please make sure that they are completely (better still, physically) separated from any of your actual environments.
There is no pattern called diligence or vigilance; that's the state of mind of security ops. You, as an architect, must assist with the proper security configuration of the following elements of the SOA infrastructure:
In fact, every single element of your SOA infrastructure must not go amiss. An obvious thing to say is that highly reusable components, service engines, and most common service agents must be checked first and on a regular basis.
You also have to include into your Ops red book (security response plan) and orange book (backup/recovery plan), a drill schedule, usually performed on your honeynet.
From a perspective of common sense, this is not a vulnerability, but primarily a negligence similar to the security misconfiguration discussed earlier and quite common to web applications (remember, we are not accusing anyone). However, for SOA, it has a broader context. Data is not only exposed on static web via AJAX/REST API. More often than not, it is insufficient crypto-strength or the lack of crypto-protection on sensitive elements of a SOAP message.
Reliance on TLS when intermediaries are on the message path is another example of such exposure, especially if the intermediary is active, that is, involved in message transformation. Even behind the Secure Gateway, in IPC-certified organizations, message data should be encrypted all the way to the ultimate receiver.
The following are the suggested patterns to apply:
Missing function-level access control vulnerability denotes insufficient authorization. It is not enough to just check whether the user is valid; a system must guarantee that this user will be allowed to call only permitted operations.
The Entitlement Server is an essential part of identity management, and for API management, Oracle Enterprise Repository with Registry (UDDI) synchronization is highly important. In terms of authorization, all your policy definition points should be supplied with connectivity to the IAM Rights/Entitlement store. Needless to say, any client-based validations for authorization do not make sense.
The following are the suggested patterns to apply:
This is a kind of manipulation, that is, when a legitimate client is forced to send a request to the service on behalf of a forger. A request can include session-related information including cookies.
Distributing session cookies is a common practice, for instance, in a multiscreen IP TV, when a valid user wants to transmit active session data from the big screen to or her tablet (or vice versa). This situation can be emulated by an attacker in order to catch and analyze the session data.
The following is the suggested pattern to apply:
Actually, perimeter protection is the last resort. Services and especially services-composition controllers must be designed with caution based on all the previously mentioned recommendations for the components design and security configuration.
Similar to XSS, this kind of design flaw is quite harmful for distributed service activities (although, OWASP considers it as a moderate threat). The dynamic nature of service compositions makes SOA architecture quite susceptible to these kinds of attacks.
Going further, the implementation of the absolutely valid Endpoint Redirection SOA pattern (http://soapatterns.org/design_patterns/endpoint_redirection), used for version control and service load balancing, can open the door for such attacks if redirection is done by simple mapping on LB without any perimeter protection with message scanning.
The following are the suggested patterns to apply:
Make sure that all redirects originated and orchestrated by your composition controller (destination endpoints taken from the service repository, the external API URL) are validated separately by SG. Do not accept any redirect parameters from the response message belonging to previous invocations.
If you maintain an invocation list in a message header (message tracking data), make sure that it is assembled from trusted sources.
The following are the different types of identity/authentication manipulation attacks.
The attack code for the reflection attack is AT01
. A typical attack sequence is listed in the following steps:
The attack code for identity spoofing is AT02
.
The identity associated with the message or resource must be removable or modifiable in an undetectable way for the attacker to perform this attack.
For example, after authentication, the valid REST service user will have their token as a part of the URL query string for an extended session. Resource access permission is validated using this token. The user with less privileges from the parallel valid session will obtain this query string (man-in-the-middle, https://www.owasp.org/index.php/Man-in-the-middle_attack and eavesdropping, https://www.owasp.org/index.php/Network_Eavesdropping and modify the session using the obtained token (or user ID if it is open). They will have time until the session expires to illegally access the resources.
In the query string, the entire static section of it must be signed. The signed digest can be in the HTTP header and enforced by a contracts policy (in the security gateway). In the case of SOAP messages, WS-Security elements for the digital signature and encryption must be applied.
The attack code for the replay attack is AT03
.
As we demonstrated earlier, replay attack is the attacker's bread and butter. Having constructed using your XSD or intercepted message, the attacker modifies the time range in the message (if applicable), and the sequence numbers (if necessary), and resends it, sometimes stripping the signatures (if the policy allows).
This attack has many variations and is not always intended to be successful at the very beginning; gathering response info is the initial target, including session data (as almost any SOA message exists in a certain session context). An attacker will explore the predictability and randomness of the session ID in order to repeat this attack with a more accurate IDs. Needless to say that the sequential IDs and reliance on date or time ranges is not a really good idea.
This attack can be combined with buffer overflow attacks in order to crash the service completely. An attacker can assume that after the service restarts, cache will be nullified as well, so the new session ID (possibly starting with zero) will be accepted for the same old message. Oracle's distributed cache and clustered environment with many OFM nodes can prevent this, but an attacker could try to shutdown all nodes at at once, or try to get to the Node Manager (especially if it's in a single-node mode).
If the distribution of cookies is involved, cookies reverse engineering can be employed in order to make the reply attack successful.
The attack code for SQL injection is AT04
.
The true and, therefore, bitter irony here is that due to a lot of DB abstraction layers (including X/O mapping, persistence layers, and even migration to NoSQL DB types) in a service's internal architecture, some experts openly proclaimed a couple of years ago the Death of SQL Injection. As you can see, it's a present-day top risk and all the old techniques we used for old ASP pages are quite powerful for REST and SOAP.
Even if the replay attack fails the information about the backend DB is gathered, such as the version, patches, platform, and possibly constraints, DB name and tables name. It is quite a good start to look for a violation of your Contract Centralization SOA pattern implementation (http://soapatterns.org/design_patterns/contract_centralization), look for open DB connections available at the service location, and carry on with the injections.
Interestingly, SOAP messages can be a good carrier of SQL injection attacks and an overenthusiastic Error Handler can provide perfect assistance in it. A simplified SOAP request will look like the following code:
<soapenv:Body> <pci:getCreditCard soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <id xsi:type="xsd:string">1 or 1=1</id> </pci:getCreditCard> </soapenv:Body>
Yes, the same old 1 or 1=1
, exactly as in old HTML/ASP times. The pci
namespace is pointing to the webgoat.owasp.org
test application, which is open to such a direct approach. You might think that your application is far better protected than OWASP WebGoat application (which is in fact deliberately unsecured). We hope so, but let's not jump to conclusions right away. All we know (from the preceding code) is that the XML SOAP message can be used for the SQL injection directly. There are three classes of SQL injections: Inband, Out-of-band, and Inferential. The difference is how you get the response (if you ever get it). If you see the response immediately, that's Inband, and in the SOA world, it's the most common. What if you shut down the error handler, block all responses and return nothing, and redirect everything back to a 404 page? Can you be safe? Sorry fellow architect, the answer is no. Jumping ahead, we can say that an Inferential or Blind SQL injection technique is the hardest one, but it can still do the trick. The following is a simplified modification of the previous code example:
<id xsi:type="xsd:string">id=1; if not(select system_user)<>'sa' waitfor delay '0:0:10' </id>
So, what we are actually asking is what privileges your service account has on the underlying resources. If it's a MS SQL system admin, please return your "unbreakable" 404 page after 10 seconds. One way or another, we will get the answer, but it will take just a little longer.
All these attacks are so common and effective that they have a lots of tools to support most of the attack types. Firstly, to find the victim (entity service, potentially with DB), public Seekda Web Service search engine or WSindex can be used. For official UDDI crawling of public services, http://www.soapclient.com/uddisearch.html is useful.
To probe and test the targeted service, SoapUI is amazingly good (you can try it together with WebGoat first). However, if someone wants command-line tools to fire constructed SOAP messages with injections, then SOAPClient4XG (Java), CURL, and SOAP::Lite (Perl) prove to be handy. If you need something for all occasions, Burp Suite is an obvious choice and you will learn a lot about injection attack patterns and much more. Talking about injections, specifically with proxy assistance, look at the following list:
We are sure that you will find more, but at the time of writing this, these were active and quite helpful. Still, if you are going to use them as a verification tool, remember that they do not cover all three types of injections and you have to do a lot of manual work to identify service weaknesses (we will not go into the basics of injection as it's not the subject of this chapter).
So an attacker gets the error message (or whatever—system silence is also a message). The injection point is identified. The next step is to identify what type of data is behind. That's simple, because your XSD will clearly say that. If not, it is not that difficult to learn after a series of reply attacks. Why is it important? Because attackers will learn, should they use a single quote for 1=1
, and the type of evasion technique will be necessary to bypass signature scanners at the Security Gateway:
…>id=1 having 1=1... or …>id=X' having 1=1 …
An attacker wants your data. Thus, union-based constructs will be used along the way. If your service stays passive, the last resort is blind injection.
What's important here is that this technique is almost identical for REST, SOAP, or command-line (direct) attacks in terms of construction of the injection syntax. In REST, you (or the attacker) can use the following:
http://[victim_site]/[victim_resource_page]?id=1%20or%20 1=convert(int,(CREDITCARD_NUM))
If error messages are on, the system will respond with an error saying that the conversion to int
failed, but it will give you (or the attacker) the actual column name. So, you can collect all the column names from the REST service DB (guesswork here is exceedingly easy).
If that doesn't work, you can identify the number of columns first using a union-based technique, such as UNION
, SELECT ALL
, 1
, 2
, 3
...N
, where N
is the number of columns and you have to try it N
times (just some guess work). After that, you can start replacing the numbers with possible column names and watch the response. A lot of the previously mentioned hacking tools can do this for you.
Blind injection is the hardest because all that you can simulate usually is how quick the blank error page (404, or whatever) will be returned. So, it's basically just "Yes" or "No"; however, with some persistence, that would be enough. The sqlmap.org site uses blind injection, so it will help you in the hardest cases.
For an attacker (or you, if you pentest your security perimeter), life is a bit more complex than breaking into a WebGoat site and the actual REST injection query string could contain something like the following code (depending on DB and its version) as well as 200 more characters, presenting conditional branching, redirecting, and calls for recreation of the earlier deleted xp_cmdshell
stored procedure. (Yes! It can be restored by SQL injection in the REST service query!):
...OPENROWSET('SQLOLEDB',";'sa';'<password>','select 1; DECLARE@resultint,@OLEResultint, .... EXECUTE @OLEResult=sp_OACreate "WScipt.Shell", ...... "CreateObject%0X",...
An attacker can change the privileges, call standard packages, or stored procedures (Oracle or MS SQL). Even using a blind injection, it is possible to extract a sys password and the current service account into the DBA group.
We will touch upon countermeasures in the following section, but while we are in the attacker's shoes, we will briefly explain how they can be dodged:
1=1
signatures. Where is the enforcement point? Equal sign? So, is this the numeric filtering with "<,>,!="
, yes? How about like
instead? What about 2=2;
or 3>1;
or /**/2/**/=/**2
? We can go for miles with such tricks, but we will save you time and head straight to the sad truth: the signature-based IDS will catch only school kids playing with a freshly downloaded Burp Suite or automated tools configured by default.Does the restrictive list have comments? Replace them with %2D
:http://[victim_site]/[victim_resource_page]/[resource_operation]?id=2/**/or/**2/**/like/**/2%2D%2D
SELECT
, UNION ALL
, LIKE
, and so on? Go to asciitohex.com and read what's written further: %55%4e%49%4f%4e%20%41%4c%4c
. Go on, add it to the REST query string with some of your trimmings.The last thing to mention is that SQL injection is still the most popular, but don't count on it alone. The attacker will unleash a complex multivector attacks the injection's support. One of the possible combinations could be as follows:
By the way, if you think that SQL injections are possible because someone is concatenating the SQL string before executing the query, be aware that the SQL procedure injection is quite possible as well. Prepared statements are more resilient though.
The conclusion is that the attacker has an advantage, not you. Your task is to prepare a multilayered defense.
The attack code for XPATH injection is AT05
.
The underlying idea behind XPath (and XQuery) is to see XML as a kind of systematic storage (similar DB) and have similar ways of accessing data.
So, as in SQL, user supplied information can be used for the construction of the XPath query string. The hacking methods are almost identical to those previously explained.
The standard path to employees' XML data, /employees/employee[@id='EMPLOYEE_ID']
, can be easily supplied with the classic '%20or%20'1'='1
and all the employee data (including CEO) will be dumped to the browser. You can add any XPath-related function you like, such as:
'%20or%20fn:contains(fn:lower-case(@lastname),'your_CEO_lastname')%20or%20'
The counter-countermeasures are similar to an SQL injection. The most hard to break are the prepared statements for XPath expressions.
The attack code for JSON and JavaScript injections is AT06
.
Imagine your service accepts the JSON documents (or constructs them based on user input) and stores them for public use. For big and bulky JSONs, you would dedicate a NoSQL database, hoping that NoSQL means NoSQL injections.
JSON itself is brilliant, as it's simple, and it can be injected (in a positive way) in any software/site capable of handling JavaScript. The flexibility is immense, thanks to AJAX and shared DOM. We can manipulate web page elements almost effortlessly using, for instance, the Chrome extension API (chrome.extension.getURL()
). JSON content will be included directly into the <script>
tag of the targeted page. You will find all the necessary instructions on the jQuery site, including manifest.json
and a sample of the <injected.js>
files.
Fellow architects, the preceding paragraphs are from the Chrome Extension API and jQuery documentation (https://developer.chrome.com/extensions/extension#method-getURL and http://jquery.com/), that's not a joke. You will even find the following examples:
document.head.appendChild(script); document.body.setAttribute("onLoad", "injected_main();");
At first glance, nothing is wrong, except the potential JSON parser/deserializer's strength. Also, we know that the standard eval()
function, used for conversion JSON into a JS object, is full of holes. The eval()
function in many cases (five conditions that can prevent this from happening, some of which are based on filtering) can execute the embedded JavaScript code. Also JSON's array vulnerability has been exploited many times. The most well-known victims are Gmail and Twitter.
JSON is no less secure than XML. It's all about how you use data (encryption, digital signature, screening, validating against standards, use of reliable parsers instead of eval()
). The preceding example with the injecting of potentially insecure JSON (which also could be the subject of injection) is something you must strongly reconsider.
The attack code for schema poisoning is AT07
.
Poisoning, that is, injecting malicious code into a single document, XML or JSON, is bad enough, but the corruption of your entire service data blueprint is a disaster, one that attackers will try to hide from you as long as they can, sneaking in and out unchallenged. It could be the result of a long-planned attack, when an attacker watched your dev repository site, got into it, modified schema or its include elements, and then waited for the opportunity in production.
A bit complex isn't it? Most common for the complex schemas is having different XSDs at different locations, sometimes public for common QDT/namespaces; an attacker can get into the weakest location and change the element type of the XSD instruction. Sometimes, just changing the level of data granularity could be enough—an unlimited string in a key element can open enough room for injections.
Another way of poisoning is having entire schema as <any>
. Yes, we used this type of declaration for the demonstration of the universal message container for the agnostic controller, but we did it behind the perimeter protection. We all know many SOAP-like endpoints that accept <any message>
because there are so many message/schemas, types of data, and vendor's versions, so it seems to be easier to parse messages on the backend without initial validation. So many opportunities for the attacker!
The attack code for forced browsing is AT08
.
As described by OWASP, forced browsing is an attack where the aim is to enumerate and access resources that are not referenced by the application but are still accessible.
This is quite a nasty thing and really dangerous. You have SOAP/WSDL, or more commonly, the REST service infrastructure with plenty of handy services available. It's so easy to build the REST service, as demonstrated earlier. When you start, it's almost impossible to stop. You have them for the internal purposes of accounting/finance, delivery and warehouse, procurement and provisioning, and those OrderRequest
and getInvoice
services that you decided to make public. Or do you just think only two of these are public?
Some of the scanners mentioned earlier are capable of traversing the victims' server in order to find those that are not declared but still exposed resources with a much less secure model. Brute force guessing could work as well.
We didn't set a goal of covering all possible vulnerabilities and attacks. You can study them at OWASP and other resources, but the ones mentioned are sufficient to devise your battle plan and gather all the critical requirements for your SOA protection. Clearly, there is no single tool that can help us a 100 percent, but from from the risk table, you can gather that Service Perimeter Guard is the top pattern to address most of the SOA-related risks. Together with proper service design, an identity management system, security token services, and Policy Studio, this pattern, materialized as Secure Gateway, will be our first line of defense.
Using code for vulnerabilities and attack types from the from the previously discussed classification we will compose our security battle map—a security-related heat map in a form of SOA components and technical infrastructure blueprint, where we link the existing service domains with predefined codes. The goal is to identify critical nodes in our infrastructure and assess the feasibility of the core SOA patterns application. We will use the CTU telecom example from the previous chapters, but its SOA infrastructure is quite common to any enterprise. The level of details on this block diagram will ultimately define the precision of the security protection assessment. So it's in your own interest to make it as complete and comprehensive as possible. What is presented in the next figure is just a starting point and you should expand it for every layer with a clear definition of overlapping sections (areas that an attacker will try to address first).
We already placed Oracle strategic products in appropriate places, including Service Gateway, Entitlement, and Identity Management Suite. Bear in mind that most vulnerabilities are inherited from poor service design and this fact is quite hard to visualize on the heat map; you should refer to peer review reports for this.
Gartner defines Identity Management as follows: "Identity management is the set of business processes, and a supporting infrastructure for the creation, maintenance, and use of digital identities." Direct or Brokered identification services are the most critical resources in our service inventory, not only because they hold clients and corporate sensitive information, but also because of their highest level of reuse.
The most common rules around identity management protection are as follows:
The common tasks around identity management can be described as gathering and storing all credential information in a secure way (passwords as hash, storage media encrypted, and DB row-level security). We have to remember that identity data is quite often scattered around several applications in different business domains, so MDM could be the essential part in Identity Data Maintenance and protection. Once collected and synchronized, credentials will be exposed through a secure API to a Security Token Service, which will provide/renew/revoke tokens, and to the authentication services (usually in scope of Perimeter Guard) and making authentication decisions based on the information in the incoming message. Following the separation of the concerns principle, ID storage (ID management), ID validation (access management), and ID extraction/injection (on SG) are three different components of the AAA security subsystem.
As you can see in the following figure, the starting point is always Perimeter Guard; its main purposes will be to scan the message before AA's operations and isolate IDM systems from the client. The additional level of isolation can provide the reverse proxy pattern, shielding internal Web/REST resources from direct calls.
IDM modularity opens the possibility for the parallel implementation of Direct and Brokered Authentication. The first one is simple and described by the name itself. Brokered Authentication (the synonym is SSO) requires an Authentication Broker, usually to act as a Security Token Provider, which returns the entry validation ticket (token) to the service-requestor for a predefined amount of time with a list of the allowed resources. As this operation requires redirection (see OWASP risks), SG shall be involved in scanning redirects, signing the tokens, and minimizing redirects (the initial client request can be immediately redirected to STS without it reflecting back to the client).
From the following figure, we see that Oracle Identity suite and API Gateway can be combined with other products such as Tivoli Federated Identity Manager (as STS) and WebSEAL reverse proxy.
Authorization data can be stored separately, but controlled by the same Oracle Identity Manager.
The list of Oracle Identity Management and Access Management products at the time of writing this are as follows (some of these could be rebranded, renamed, or merged, so check the Oracle site regularly).
The following are the Identity Governance products:
The following are the Access Management products:
Indisputably, Oracle is one of the leaders in directory product offerings (LDAP directories). The Oracle Internet Directory (OID) was the first product in this group and now, we have a highly efficient Oracle Unified Directory (OUD), which includes both a highly scalable LDAP directory service based on Java and a Oracle Virtual Directory (OVD) product. OUD comes with the following three main components:
The Directory Server essentially is a highly scalable and top-performing LDAP. The Proxy Server contributes to LDAP's high-performance proxy requests and responses and the Replication Server is responsible for the data replication from one OUD to another.
This list of products is just an indication that Oracle has everything necessary for the proper implementation of all eight SOA security patterns. Now it is your responsibility to enforce the security of your services by addressing error handling vulnerabilities (these are what makes your services leak and opens the door for injection-type attacks).
We have put together short responses to problems in Error Handling (EH[nn]) identified during error handling vulnerability analysis.
As an option, javac
will warn you about the return in the finally
block if a compiler's argument is set as -Xlint:finally
. Use of the Ant <compilerarg>
element as follows:
<javacsrcdir="${src.dir}" destdir="${classes.dir}" classpathref="libraries"> <compilerarg value="-Xlint"/> </javac>
Correct cleaning is always important, but you should be extra careful with threads. Please look at the following code samples. They can help you to mitigate at least two types of attacks, bases of buffer overflow and information leakages:
private static final long SLEEP_INTERVAL = 100; private static void removeGarbage() { try { System.gc(); //give a thread chance if you can Thread.sleep(SLEEP_INTERVAL); System.runFinalization(); } catch (InterruptedExceptionie){ //handle threads properly, log exception clearly, //DO NOT JUST print stack trace ! // Try to exit neatly, do not just kill it by .stop() method Thread.interrupt(); } //Other errors catch (Exception ix){ //same as above, DO NOT JUST print stack trace ! // use Runtime.getRuntime().totalMemory(), maxMemory() and freeMemory() // in logging procedure for recording the JVM memory state at the moment of //error. Use simple equation usedJVMMemory = totalMemory() – // freeMemory() for calculating amount of used memory. } }
Do not force garbage cleaning by calling
System.gc()
too often to release the memory. You should trust the intelligence of modern JVM (Oracle JRockit in particular, the true core of OFM) and rest assured that JVM does everything possible to optimize memory utilization. If your code is far from optimal, and contains any vulnerabilities mentioned in vulnerability analysis at the beginning of this chapter, even the best garbage cleaner from JRockit won't be able to turn the tide. Furthermore, even the paramount perimeter protection around your Service Inventory will just die trying to defend service compositions.
Although samples in this paragraph are Java-related (strategic Oracle language), make sure that you have the proper PL/SQL exception handlers as well. All data handling code should be on PL/SQL. (This is for a relational DB, of course; for NoSQL, it depends on realization but is close to data.) Use PL/SQL packages for better modularity and EH centralization. The statement in packages must be prepared. That's it. These are the most effective measures to make injection attacks as hard as possible. Oracle provides complete guidance on how to write injection-proof PL/SQL code. You can find the documentation at http://www.oracle.com/technetwork/database/features/plsql/overview/how-to-write-injection-proof-plsql-1-129572.pdf.
While discussing the attack types, we spent most of the time talking about injections, because this is the best way to get to your precious data. That's what the attackers want, not just to crash your system. Some say that DoS (http://www.cert.org/historical/tech_tips/denial_of_service.cfm) repelling is the hardest security task. No, it isn't. It's just most expensive, but not the hardest. Injections are much more tricky. Why? Because most of the protection techniques are based on scanning input signature and we demonstrated (very briefly though) that IDS methods can be disabled and bypassed. The deceptive complexity of data abstraction levels should not hoodwink you—most serializers/marshallers are designed to transport data from the XML to the SQL column without changes (that's their sole purpose) and security is not their responsibility.
Does this mean that message screening is futile? No, even 50 percent positive catches is a positive thing, and we really could reach higher numbers. Just remember, defense is complex. How? Secure Gateway (Oracle and most of others) is an ESB by design. So, we basically have two ESBs and you can add an additional XSD check on OSB as well. Make sure that the only option your attackers have is a blind injection. Let's make their life harder. What else can help us? The following are the most effective measures for consideration:
Combined together, the preceding measures can give quite a level of protection. Amazingly, there are still a lot of developers who produce tons of JAVA code such as Statement stmt = conn.createStatement("INSERT INTO customer VALUES('" + user + "')"); stmt.execute();
. Thus, Oracle API Gateway must be in your arsenal.
From the diagram in the Risk mitigation design rules section, you can see that OEG is the product with highest concentration of core SOA security patterns. What are the common requirements for such a tool to be trusted?
Some information about the requirements can be found on OWASP (search for OWASP XML Security Gateway Evaluation Criteria Project
), but a list of twenty or forty criteria is too small. Our actual list has almost 200 positions and comprises technical requirements of three different commercial SGs. Oracle is one of them. We encourage you to read some technical whitepapers about its capabilities as it is beyond the scope of this book.
Number 5 in the OWASP top 10 is directly related to the complexity of security tools and mechanisms. In our experience, OEG proved to be amazingly simple in installation, maintenance, and development (see the previous screenshot). Right after unpacking, you will get a resilient and simple environment and an easy to start/stop and monitor. Policy Studio (main development tool) is not exactly Eclipse-style, so it will take time some time to adapt after OSB with its traditional request-response pipelines; however, in an hour, you will be able to build reasonably complex flows for SOAP/REST services with an HTTP or SOAP attribute verification and validation and so on. Development is policy-based, that is, you can define the message flows and different policies for every step separately, maintain nested policies (implementing a Policy Centralization SOA pattern), and apply a common policy to the different flow elements.
Using drag-and-drop development, you can assign a scan for inbound messages, connect to different identity providers, extract or inject SAML tokens, and protect them from spoofing/alteration (see the message processing flow in the next screenshot). The full set of OEG development categories is seen on the right-hand side of the next figure, in the orange box . It is a truly complete set of functions, essential for perimeter protection, inbound/outbound message screening, authentication, authorization, and runtime audit.
One of the critical requirements for a business is obviously concerned with incongruity between security and performance. A simple dummy REST proxy service (not a real case!), assembled as shown in the following screenshot, was even unable to stress dual-core 8GB RAM VM, handling 500 REST transactions per second (response 3K JSON). Actually, LoadUI from a single machine was unable to produce enough stress.
For real OEG performance capabilities, please see figures from our real perftest report.
We have several tests that run the 50 KB message that contain the following aspects:
<EmployeeID>
..</EmployeeID >
element<Salary>
..</Salary >
elementThe main test was executed from a terminal session running on the Linux server:
use HTTPS sessions parallel (threads): 64 test duration: 3600 (somehow the actual test run for a bit more then 2 hours) time taken: 7785.540000 secs. bytes sent: 22362.978370MB (23449282407 octets) bytes received: 24503.956365MB (25694260549 octets) transactions: 445609 connections: 445629 sslConnections: 445629 sslSessionsReused: 0 bytes sent/sec: 2.872373MB (3011901.859987 octets) bytes received/sec: 3.147368MB (3300254.131248 octets) transactions/sec: 57.235465
As a conclusion from these figures, you can deduce that having 10K TPS on a single VM with two cores and an 8 GB RAM for a 50K SOAP message, completely protected by TLS and MLS, is an achievable target.
3.19.75.133