Tuesday, March 10, 2009

Friends for Java v2

Here's a new attempt at implementing a secure version of something akin to the friend class concept in java, since the previous attempt was rather flawed in view of being used in a "neat'n'clean API" scenario.

This time I'm using a little introspection to try to catch evil code. Hopefully this check can't be circumvented, at least if a SecurityManager is in place, and also hopefully won't be stopped by any SecurityManager (it doesn't immediately seems so: one can use getClass() at any time, right? Can one also use the 1.5 getEnclosingClass() without being stopped?)

(If you use Eclipse, you can mark the entire code below (all classes in one go), Ctrl+C, then activate the project node of a project and hit Ctrl+V. You will probably have to organize imports afterwards).
package com.example;

import api.WantedCode;

public class NeedingCode {
// Driver
public static void main(String[] args) {
// .. we have an instance of this class
WantedCode code = new WantedCode();

// And access its package private method through a "friend-proxy"
FriendProxy.getProxy().invokeWantedMethodOf(code);
}
}

// ------------

package com.example;

import api.WantedCode;

public abstract class FriendProxy {

// :: Proxy interface method

public abstract void invokeWantedMethodOf(WantedCode instance);

// :: Friend infrastructure

private static FriendProxy _proxy;

public static void setProxy(FriendProxy proxy) {
// Verify that the origin of this proxy matches our expectations.
if (proxy.getClass().getEnclosingClass() != WantedCode.class) {
throw new IllegalAccessError("Only my friend can invoke this method.");
}
_proxy = proxy;
}

// :: Package-private accessor to get to friend's package private method.

static FriendProxy getProxy() {
return _proxy;
}
}

// ------------

package api;

import com.example.FriendProxy;

public class WantedCode {

void wantedMethod() {
System.out.println("Hi from the package-private method in the API!");
}

static {
FriendProxy.setProxy(new GivingAccessToNeedingCode());
}

private static class GivingAccessToNeedingCode extends FriendProxy {
@Override
public void invokeWantedMethodOf(WantedCode instance) {
instance.wantedMethod();
}
}
}

// ------------

package com.example;

import api.WantedCode;

/**
* Test whether the evilness is caught.
*/
public class EvilCode {
// Driver
public static void main(String[] args) {
WantedCode code = new WantedCode();
FriendProxy.setProxy(new FriendProxy() {
@Override
public void invokeWantedMethodOf(WantedCode instance) {
System.err.println("I'm evil!");
}
});
FriendProxy.getProxy().invokeWantedMethodOf(code);
}
}

8 comments:

  1. In a really paranoid scenario, an attacker would replace your WantedCode class, i.e. you wouldn't have a distinct EvilCode class, but instead attacking code would pretend to _be_ WantedCode infact. This could be done by hacking the classpath or similar. In this scenario your check would pass, and you would execute the evil code. The solution is to introduce a security permission, check for it in setProxy() and call setProxy() with privileges enabled (AccessController.doPrivileged() ). However, this requires a security policy to be set up, which makes it a big difficult to run as e.g. applet. I'm working on an example.

    ReplyDelete
  2. I thought that if you can manipulate the classpath, then pretty much all bets are off at any rate - you most probably also have control over the Security policy and -Manager then too?

    ReplyDelete
  3. Well no. When talking about security you should not assume things about the source of the code. For applets, I could think of a scenario where a fishing site uses your JAR (your applet jars can easily be downloaded and embedded in another site) and replaces one class inside (if not signed), OR prepend the classpath with the hacked class. Attackers can probably also play tricks with classloaders, so that the same class gets loaded again into the VM, but from a different source (yeah, this is possible). The only way to be really safe is using the security access control mechanisms of the VM, and sign your JAR. Unfortunately, this requires the _user_ to install an appropriate security policy (because you need to guard calls to setProxy()), which is quite unintuitive ('what? you need a policy to run your own code? wtf?').

    At least, you should also check for identical classloader in your setProxy() method. But this wouldn't help in the first scenario. I don't see an easy and practical solution for the super paranoid. But I guess this is why there is no 'friend' in the Java language, as this opens up a can of worms with respect to security.

    ReplyDelete
  4. BTW, when some evil person is able to sneak in patched classes, something is wrong anyway, even without the friends pattern (you want to sign your JAR then to ensure consistency). So maybe this is all just fluff and checking for the proxy to be set twice and checking the (enclosing) class of the proxy (or some other known unique property) plus checking the classloader is more the enough. And of course, you should check what kind of data/functionality you actually expose and if it is really security relevant.

    ReplyDelete
  5. Well, I still don't quite get it: I presume that if you are paranoid, you're running with a SecurityManager already (as Applets do). You'd also sign these jars. The idea of checking classloaders was interesting. However, what about the check against WantedClass.class: This will fail if we're not talking about the same class that NeedingClass has loaded itself.

    My point boils down to: If you are able to switch out the WantedClass in any way, what's the point of the friend security mechanisms in the first place? Isn't this really a) for making a pretty API (in the "normal case" when running java "command line" without SecurityManager, as in this case, then all bets are off: You can do ANYTHING), and b) when you're in a SecurityManaged mode, in which case you'd make it impossible to instantiate this class from anywhere else.

    If the question is what I can manipulate, I could just recompile the entire thing and use that?! I thought that your initial entry were basically trying to make a "friend" logic for the runtime classes - and I don't quite see how I could manipulate anything there without getting caught, in a security managed scenario.

    An example where you could bypass the suggested solution, in a relevant security-conscious world, would be great.

    ReplyDelete
  6. phần mềm quản lý nhà hàngbạn đang bế tắc trong vấn đề quản lý của mình.? phan mem quan ly nha hang gia rephần mềm mà chúng tôi mang đến cam kết chất lượng và chuyên nghiệp phần mềm quản lý qán cafe tại tphcmbạn không muốn bị thất thoát tài sản chỉ vì phần mềm đã quá cũ và hay bị lỗi.?

    cần làm websitelà các thông tin cơ sở dữ liệu được chủ website thêm vào khi tải dữ liệu lên host Thiết kế website phòng khám nha khoaVới việc thiết kế các thông tin trên website của bạn hướng tới lợi ích của khách hàng điều đó giúp khách hàng sẽ dễ dàng khai thác các thông tin trên website của Bạn Thiết kế website spaVà một khi khách hàng hài lòng thì Bạn đã tạo dựng được một hình ảnh tốt đẹp về mình trong tâm trí và tình cảm của khách hàng, giúp công ty, doanh nghiệp bạn trở lên chuyên nghiệp hơn. Thiết kế website giải tríChi phí để thiết kế website chuyên nghiệp thật là quá nhỏ bé so với những núi chi phí mà bạn bỏ ra để quảng bá các hoạt động của Bạn bằng các phương tiện truyền thống. cong ty thiet ke webHTSolution là một công ty thiết kế website chuyên nghiệp cà chất lượng nhất, chúng tôi luôn đem đến cho các bạn những sản phẩm chất lượng và uy tiến hàng đầu thiết kế website chất lượngtạo ra sự nhận diện thương hiệu và khả năng kinh doanh vượt trội thông qua kênh marketing trực tuyến. thiết kế website giá rẻnhất nhằm giúp website bạn thân thiện hơn với các bộ máy tìm kiếm như (Google, BingYahoo...)

    ReplyDelete
  7. Ngày nay việc tìm mua bàn làm việc văn phòng rất đơn giản vì thị trường nội thất văn phòng ngày càng phát triển nhiều xưởng sản xuất cho ra nhiều mẫu mã sản phẩm đa dạng với giá cả khác nhau nên việc chọn mua bàn văn phòng giá rẻ tphcm như thế nào tại đâu hiệu quả tốt nhất giúp đáp ứng nhu cầu sử dụng. Hiện này khi chọn mua nội thất văn phòng thường với xu hướng chọn ghế chân sắt hoặc inox, bàn làm việc chọn loại bàn gỗ. Sự kết hợp của vật liệu kim loại và tự nhiên giúp căn phòng có sự hài hòa và trong đẹp mắt hơn. Hơn nữa việc chọn ghế chân sắt - inox cũng góp phần giảm thiểu được một khoảng chi phí khi loại ghế này có giá rẻ hơn khá nhiều so với ghế làm bằng gỗ, vì với chi phí thuê hay mua một văn phòng làm việc tại TPHCM là không hề rẻ nên cần phải tính toán chi tiêu hợp lý. Ngoài ra, hầu như tất cả văn phòng đều được đặt ở những tòa nhà cao tầng nên việc vận chuyển ghế gỗ khó khắn hơn rất nhiều do có trọng lượng nặng đáng kể. Cho nên khi chọn mua sản phẩm nội thất văn phòng giá rẻ hcm nhừ bàn ghế hay tủ bạn nên chú ý đến văn phòng của mình vị trí nào đễ dễ cho việc di chuyển sau này. Cho nên khi bạn có nhu cầu chọn mua những mẫu bàn làm việc gỗ nên cân nhắc đến các vấn đề về: Phong thủy, kích thước diện tích văn phòng, phối màu và sự phối hợp liên quan tới các sản phẩm nội thất khác trong văn phòng đặc biệt là sự di chuyển , bảo hành trong quá trình sử dụng.

    ReplyDelete