Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

A powerful toolkit for enforcing access restrictions in Java

License

NotificationsYou must be signed in to change notification settings

MeGysssTaa/access-warden

Repository files navigation

access-warden-simple-demo.png

Introduction

Access Warden is a simple to use yet powerful toolkit designed to allow Java developers toenforce access restrictions in their applications. It works by generating special runtime stacktrace and environment inspection code and injecting it in your classes after build.

The problem

Simple Example

Let's imagine we're developing a game. Let's say we have a classPlayer with this method:

privatevoidjump() {this.posY +=1.0;// (some hyper-realistic physics simulation here)}

Assuming this method is only called from inside ourPlayer class, we can define itprivate. This means that we are protected from all other classes/sources accessing this method and causing the player to jump infinitely... or,are we?

Standard Java modifiers are not so reliable

Actually thejump method can still be accessed byany other third-party. For example, anattacker can usereflection for that:

voidhack() {Playerplayer = ...Class<?>clazz =Class.forName("our.cool.game.Player");Methodmethod =clazz.getDeclaredMethod("jump");method.setAccessible(true);method.invoke(player);// here, we bypass the "private" access restriction}

Additionally, anattacker could potentially use some native (C/C++) tricks and possibly even something more to ignore theprivate keyword you've just put so much effort in writing. This is definitely not something most applications should worry about. But some certain kinds of applications actuallydo want to avoid the possibility of such"attacks".

Setting up a global SecurityManager

One way of getting around this is to use aSecurityManager, either by defining one before launching your application (which also has to be enforced somehow) with some pre-defined security policies files, or programmatically, by directly inheriting fromjava.lang.SecurityManager and writing code that will filter all the forbidden calls on your own (which may be incompatible with user's current environment, say, due to anotherSecurityManager being already set). Both options involve comparably much work and have severe drawbacks.

The solution

Access Warden provides a toolkit that helps you deal with this kind of issueeasily, quickly, and comparably reliably. Here's some brief overview of allAccess Warden modules:

  • API — Provides low-level access to stacktrace/environment inspection and allows you write somereally specific checks suitable for your particular application case. However, in most cases you'll be only including this module forannotations, on which the other modules are based.
  • Core — Provides very high-level, control-less access toJVM bytecode generation in existing JAR files. Mostly used either as a standalone application or by other modules (such as the Gradle module) for transformation of existing (built) application JAR files. However, you can also use it to run JAR transformations programmatically, at a high level (with barely writing any code).
  • Gradle — Removes the need in running the Core module as a standalone application after each application build. Instead, all the necessary transformations will be automatically applied after you build your application with Gradle.
  • Demo — A basic runnable example that demonstrates the wayAccess Warden can be used, uses Gradle.

WithAccess Warden, our examplePlayer#jump() method can be secured somewhat as follows:

@RestrictedCall (prohibitReflectionTraces    =true,prohibitNativeTraces        =true,prohibitArbitraryInvocation =true,permittedSources            = {"my.cool.game.Player#update*","my.cool.game.Player#keyPressed"        })privatevoidjump() {this.posY +=1.0;// (some hyper-realistic physics simulation here)}

After building this code, the annotation above thejump method will be removed from the code (you can change this behavior to keep the annotation, if you need to, though), and instead some special code will be generated and inserted in the beginning of the method instruction set. This special code will onlyallow methodkeyPressed and all methods whose name starts withupdate (e.g.updateInputs,updatePhysics, etc.) from inside classmy.cool.game.Player to pass. Additionally, it willforbid thejump method to be invoked with reflection and/or native methods.

Any calls that do not match the described criteria will cause aSecurityException to be thrown. This means that you nowtruly define who can, and who cannot access yourPlayer#jump method. Moreoever, it's really easy to do and doesn't require you to have any special knowledge (other than details specific to your application).

Note that with this annotation, you no longer even have to make your methodprivatepublic will act pretty much the same. However, this isnot recommended, since it violates the basics of OOP and makes your code difficult to understand by causing an illusion of apublic method that is actually restricted.

How does Access Warden "suspend" method calls

It does so by simply injecting special bytecode in your already compiled JAR files that throws ajava.lang.SecurityException if the method call is not permitted. The exception will carry a message describing theexact reason why the call was suspended (e.g. whether the caller source was explicitly blacklisted, or the caller used reflection which was disabled for this method via configuration).

Getting Started

For detailed installation instructions and "how to use" see theGetting Started page of the Wiki. For specific details you can also see documentation/javadocs. There's also a lot of other useful information availableon the Access Warden Wiki.

Performance

AllAccess Warden's runtime access context checks, of course, have some CPU overhead. Moreover, your final application JAR (after transformations) will be slightly increasing in size for each piece of code you annotate with@RestrictedAccess or similar. That is, it is only adviced to useAccess Warden's power on the most vulnerable parts of your code — where anattacker bypassing regular Java access modifiers is unacceptable or extremely unwanted.

Internally, though,Access Warden attempts to generate as little amounts of code as possible. See theCode Generation page of the Wiki for details.

Reliability

I can't state that the level of "protection"Access Warden offers is 100% bulletproof. But it is indeed a good starting point against"script-kiddies", and it definitely requires some special knowledge to bypass its checks, if configured and used right.

Contributing

If you'd like to report a bug, ask a question, suggest a new feature, or even provide some code improvements on your own, don't hesitate toopen an issue ormake a pull request!

Building (Gradle)

Assuming you already have Git, Maven, and Gradle installed and set up.

First, clone the project from git andcd into it:

git clone https://github.com/MeGysssTaa/access-wardencd access-warden

Second, use Gradle Wrapper to build the executables (JAR files) from source:

# To build all modules at once:./gradlew build# To build one particular module (for example, access-warden-api):./gradlew access-warden-api:build

Please note that in order to build particular modules you'll first have to build the entire project. This is because modules depend on each other(API <- Core <- Gradle <- Demo).

To learn more aboutAccess Warden modules, seewiki.

License

Apache License 2.0


[8]ページ先頭

©2009-2025 Movatter.jp