Hogyan orvosoljuk az ImageMagick / Imagick konvertáló rendszerek biztonsági házirendjéből származó hibákat

botond küldte be 2020. 09. 02., sze – 12:02 időpontban

Tartalom

 

Bevezető

Az ImageMagick egy ingyenes és nyílt forráskódú, több platformon működő szoftvercsomag, ami elsősorban raszteres képek megjelenítésére, létrehozására, átalakítására, módosítására és szerkesztésére szolgál, de tudja kezelni a különböző vektoros formátumokat is, mint például EPS (Encapsulated PostScript), AI (Adobe Illustrator), PDF (Portable Document Format), stb. Összesen több, mint 200 képfájl-formátumot támogat. Az Imagick pedig egy natív PHP kiterjesztés, amely segítségével webes környezetben kezelhetjük a különböző képformátumokat az ImageMagick API által. Ebben a rövid hibaelhárítóban áttekintjük, hogy egy apró beavatkozás segítségével hogyan háríthatjuk el a szoftver biztonsági házirendjéből származó hibákat.

 

 

A hibajelenség

Linux alatt parancssorban a convert parancsot használva, vagy weboldalunkon a PHP-ben az Imagick objektum létrehozása során hibát kapunk. Az első esetben a parancs kimenetében kapjuk a hibát, az utóbbiban pedig egy try-catch szerkezettel kapjuk el:

try {
	$image = new Imagick($dimsloc);
} catch ( ImagickException $e ) {
	echo "Hiba: ".$e->getMessage();
	die();
}

A hibaüzenetek pedig ilyenek, vagy ezekhez hasonlóak, attól függően, hogy milyen képformátumot szerettünk volna feldolgozni:

attempt to perform an operation not allowed by the security policy `PS' @ error/constitute.c/IsCoderAuthorized/408
attempt to perform an operation not allowed by the security policy `PS2' @ error/constitute.c/IsCoderAuthorized/408
attempt to perform an operation not allowed by the security policy `PS3' @ error/constitute.c/IsCoderAuthorized/408
attempt to perform an operation not allowed by the security policy `EPS' @ error/constitute.c/IsCoderAuthorized/408
attempt to perform an operation not allowed by the security policy `PDF' @ error/constitute.c/IsCoderAuthorized/408
attempt to perform an operation not allowed by the security policy `XPS' @ error/constitute.c/IsCoderAuthorized/408

stb...

 

A megoldás

A megoldást az ImageMagick biztonsági házirendjében kell keresnünk. Erre van egy xml fájl, ami leírja ezeket a szabályokat. ImageMagick verziótól függően nyissuk meg szerkesztésre ezt a fájlt:

ImageMagick 6 esetén (Pl. Debian 10):

sudo nano /etc/ImageMagick-6/policy.xml

ImageMagick 7 esetén (pl. Ubuntu 20.04 LTS):

sudo nano /etc/ImageMagick-7/policy.xml

Majd görgessünk az aljára, ahol ezt találjuk:

<policymap>
  <!-- <policy domain="system" name="shred" value="2"/> -->
  <!-- <policy domain="system" name="precision" value="6"/> -->
  <!-- <policy domain="system" name="memory-map" value="anonymous"/> -->
  <!-- <policy domain="system" name="max-memory-request" value="256MiB"/> -->
  <!-- <policy domain="resource" name="temporary-path" value="/tmp"/> -->
  <policy domain="resource" name="memory" value="256MiB"/>
  <policy domain="resource" name="map" value="512MiB"/>
  <policy domain="resource" name="width" value="16KP"/>
  <policy domain="resource" name="height" value="16KP"/>
  <!-- <policy domain="resource" name="list-length" value="128"/> -->
  <policy domain="resource" name="area" value="128MB"/>
  <policy domain="resource" name="disk" value="1GiB"/>
  <!-- <policy domain="resource" name="file" value="768"/> -->
  <!-- <policy domain="resource" name="thread" value="4"/> -->
  <!-- <policy domain="resource" name="throttle" value="0"/> -->
  <!-- <policy domain="resource" name="time" value="3600"/> -->
  <!-- <policy domain="coder" rights="none" pattern="MVG" /> -->
  <!-- <policy domain="module" rights="none" pattern="{PS,PDF,XPS}" /> -->
  <!-- <policy domain="delegate" rights="none" pattern="HTTPS" /> -->
  <!-- <policy domain="path" rights="none" pattern="@*" /> -->
  <!-- <policy domain="cache" name="memory-map" value="anonymous"/> -->
  <!-- <policy domain="cache" name="synchronize" value="True"/> -->
  <!-- <policy domain="cache" name="shared-secret" value="passphrase" stealth="true"/> -->
  <!-- <policy domain="system" name="pixel-cache-memory" value="anonymous"/> -->
  <!-- <policy domain="system" name="shred" value="2"/> -->
  <!-- <policy domain="system" name="precision" value="6"/> -->
  <!-- not needed due to the need to use explicitly by mvg: -->
  <!-- <policy domain="delegate" rights="none" pattern="MVG" /> -->
  <!-- use curl -->
  <policy domain="delegate" rights="none" pattern="URL" />
  <policy domain="delegate" rights="none" pattern="HTTPS" />
  <policy domain="delegate" rights="none" pattern="HTTP" />
  <!-- in order to avoid to get image with password text -->
  <policy domain="path" rights="none" pattern="@*"/>
  <!-- disable ghostscript format types -->
  <policy domain="coder" rights="none" pattern="PS" />
  <policy domain="coder" rights="none" pattern="PS2" />
  <policy domain="coder" rights="none" pattern="PS3" />
  <policy domain="coder" rights="none" pattern="EPS" />
  <policy domain="coder" rights="none" pattern="PDF" />
  <policy domain="coder" rights="none" pattern="XPS" />
</policymap>

 

 

És az alsó "disable ghostscript format types" részt módosítsuk: töröljük ezt a részt, vagy kommentezzük, majd pótoljuk az alábbiaknak megfelelően:

<policymap>
  <!-- <policy domain="system" name="shred" value="2"/> -->
  <!-- <policy domain="system" name="precision" value="6"/> -->
  <!-- <policy domain="system" name="memory-map" value="anonymous"/> -->
  <!-- <policy domain="system" name="max-memory-request" value="256MiB"/> -->
  <!-- <policy domain="resource" name="temporary-path" value="/tmp"/> -->
  <policy domain="resource" name="memory" value="256MiB"/>
  <policy domain="resource" name="map" value="512MiB"/>
  <policy domain="resource" name="width" value="16KP"/>
  <policy domain="resource" name="height" value="16KP"/>
  <!-- <policy domain="resource" name="list-length" value="128"/> -->
  <policy domain="resource" name="area" value="128MB"/>
  <policy domain="resource" name="disk" value="1GiB"/>
  <!-- <policy domain="resource" name="file" value="768"/> -->
  <!-- <policy domain="resource" name="thread" value="4"/> -->
  <!-- <policy domain="resource" name="throttle" value="0"/> -->
  <!-- <policy domain="resource" name="time" value="3600"/> -->
  <!-- <policy domain="coder" rights="none" pattern="MVG" /> -->
  <!-- <policy domain="module" rights="none" pattern="{PS,PDF,XPS}" /> -->
  <!-- <policy domain="delegate" rights="none" pattern="HTTPS" /> -->
  <!-- <policy domain="path" rights="none" pattern="@*" /> -->
  <!-- <policy domain="cache" name="memory-map" value="anonymous"/> -->
  <!-- <policy domain="cache" name="synchronize" value="True"/> -->
  <!-- <policy domain="cache" name="shared-secret" value="passphrase" stealth="true"/> -->
  <!-- <policy domain="system" name="pixel-cache-memory" value="anonymous"/> -->
  <!-- <policy domain="system" name="shred" value="2"/> -->
  <!-- <policy domain="system" name="precision" value="6"/> -->
  <!-- not needed due to the need to use explicitly by mvg: -->
  <!-- <policy domain="delegate" rights="none" pattern="MVG" /> -->
  <!-- use curl -->
  <policy domain="delegate" rights="none" pattern="URL" />
  <policy domain="delegate" rights="none" pattern="HTTPS" />
  <policy domain="delegate" rights="none" pattern="HTTP" />
  <!-- in order to avoid to get image with password text -->
  <policy domain="path" rights="none" pattern="@*"/>
  <!-- disable ghostscript format types -->
<!--
  <policy domain="coder" rights="none" pattern="PS" />
  <policy domain="coder" rights="none" pattern="PS2" />
  <policy domain="coder" rights="none" pattern="PS3" />
  <policy domain="coder" rights="none" pattern="EPS" />
  <policy domain="coder" rights="none" pattern="PDF" />
  <policy domain="coder" rights="none" pattern="XPS" />
-->
  <policy domain="coder" rights="read | write" pattern="PS" />
  <policy domain="coder" rights="read | write" pattern="PS2" />
  <policy domain="coder" rights="read | write" pattern="PS3" />
  <policy domain="coder" rights="read | write" pattern="EPS" />
  <policy domain="coder" rights="read | write" pattern="PDF" />
  <policy domain="coder" rights="read | write" pattern="XPS" />
</policymap>

Én a kommentezést választottam.

Ezután a parancssori használat esetén egyből a friss szabályokat alkalmazza, amit akár le is kérdezhetünk az identify paranccsal:

identify -list policy
Path: /etc/ImageMagick-6/policy.xml
  Policy: Resource
    name: disk
    value: 1GiB
  Policy: Resource
    name: map
    value: 512MiB
  Policy: Resource
    name: memory
    value: 256MiB
  Policy: Resource
    name: area
    value: 128MB
  Policy: Resource
    name: height
    value: 16KP
  Policy: Resource
    name: width
    value: 16KP
  Policy: Delegate
    rights: None 
    pattern: URL
  Policy: Delegate
    rights: None 
    pattern: HTTPS
  Policy: Delegate
    rights: None 
    pattern: HTTP
  Policy: Path
    rights: None 
    pattern: @*
  Policy: Coder
    rights: Read Write 
    pattern: PS
  Policy: Coder
    rights: Read Write 
    pattern: PS2
  Policy: Coder
    rights: Read Write 
    pattern: PS3
  Policy: Coder
    rights: Read Write 
    pattern: EPS
  Policy: Coder
    rights: Read Write 
    pattern: PDF
  Policy: Coder
    rights: Read Write 
    pattern: XPS

Path: [built-in]
  Policy: Undefined
    rights: None

Ha viszont PHP-ben kaptuk a hibát, akkor a módosítás után indítsuk újra az oldalt futtató PHP-FPM-et, amennyiben ezzel működik az oldal.

 

A probléma oka

Ezt csak érdekességképpen írom le hogy mi okozta ezt, hogy korábban működött az ImageMagick, és egy ideje hibákat dobált. A programban találtak egy biztonsági rést, amit először azzal orvosoltak, hogy a fenti konfig fájlban letiltották a kérdéses fájlformátumokhoz való hozzáférést. Később rendesen is javították a hibát, ki is adták a biztonsági frissítést, azonban a biztonsági szabályokat nem állították vissza. Így ezért volt szükség ennek pótlására.

Az imagemagick debian csomag hibakövetési naplója itt található. A kapcsolódó CVE kódok: CVE-2019-13300, CVE-2019-13304, CVE-2019-13306, CVE-2019-13307, CVE-2019-15140, CVE-2019-19948

 

 

Konklúzió

Nálam egy WordPress alapú weboldalban az egyik plugin hasznája az ImageMagick-et, ami vektorfájlokat kezel. Viszont a pluginban nem volt kiíratva a hiba, ezért csak a furcsa "mellékhatásokat" láttam. Aztán amikor nekiálltam debugolni az egészet, akkor csak hosszas hibakeresés után akadtam rá magára a hibaüzenetre, mivel a pluginban nem volt kiíratva maga a hibaüzenet. Aztán innentől már csak egy kis utánaolvasással, de meglett a megoldás. Ha másoknak ezzel le tudom rövidíteni a keresgélést – akik hasonló helyzetben vannak –, akkor már megérte elkészíteni ezt a leírást.