
Code PoC pour télécharger des fichiers avec CVE-2024-32830
Code PoC pour télécharger des fichiers avec CVE-2024-32830
getimagesizePour contourner la restriction getimagesize, nous pouvons créer une simple image image/vnd.wap.wbmp pour PHP.
La vérification du type de fichier est très simple :
// https://github.com/php/php-src/blob/0029d2b08bbd3cb3aa293d9c8d55bf31faa9e203/ext/standard/image.c#L917
static int php_get_wbmp(php_stream *stream, struct gfxinfo **result, int check)
{
int i, width = 0, height = 0;
if (php_stream_rewind(stream)) {
return 0;
}
/* get type */
if (php_stream_getc(stream) != 0) {
return 0;
}
/* skip header */
do {
i = php_stream_getc(stream);
if (i < 0) {
return 0;
}
} while (i & 0x80);
/* get width */
do {
i = php_stream_getc(stream);
if (i < 0) {
return 0;
}
width = (width << 7) | (i & 0x7f);
/* maximum valid width for wbmp (although 127 may be a more accurate one) */
if (width > 2048) {
return 0;
}
} while (i & 0x80);
/* get height */
do {
i = php_stream_getc(stream);
if (i < 0) {
return 0;
}
height = (height << 7) | (i & 0x7f);
/* maximum valid height for wbmp (although 127 may be a more accurate one) */
if (height > 2048) {
return 0;
}
} while (i & 0x80);
if (!height || !width) {
return 0;
}
if (!check) {
(*result)->width = width;
(*result)->height = height;
}
return IMAGE_FILETYPE_WBMP;
}
La façon la plus simple de construire une image valide serait d'utiliser deux octets NUL, suivis de deux octets < 0x80 pour la largeur et la hauteur.
Il est possible de faire cela pour n'importe quel fichier, en utilisant php://filter.
La première couche devrait appliquer un encodage base64 pour garantir que toutes les données sont en ASCII, satisfaisant ainsi la contrainte < 0x80.
Le second filtre devrait ajouter les deux premiers octets NUL. Cela est possible en forçant une conversion de UTF-16BE vers UTF-32BE. Cela forcera iconv à interpréter chaque bloc de deux octets comme un caractère UTF-16BE valide, puis à le préfixer de deux octets NUL pour en faire de l'UTF-32BE. Le filtre à utiliser est : convert.iconv.utf-16be.utf-32be.
Notre payload final est php://filter/convert.base64-encode/convert.iconv.utf-16be.utf-32be/resource=<file here>.