Unveiling the Sudo Heap Overflow Vulnerability (CVE-2021-3156): A Critical Security Flaw Reappears

本文主要是介绍Unveiling the Sudo Heap Overflow Vulnerability (CVE-2021-3156): A Critical Security Flaw Reappears,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

​​​​​​​​

Introduction

In this blog post, we dive into the intricacies of the Sudo Heap Overflow Vulnerability (CVE-2021-3156). On January 26, 2021, Qualys Research Labs discovered a flaw in sudo. When sudo parses the command line parameters, the truncation character is wrongly judged, which leads to the attacker maliciously constructing a payload, causing sudo to overflow the heap. This vulnerability can cause Local privilege escalation.

Environment

environment version

• ubuntu 20.04

• sudo-1.8.31p2

Use the following command to compile and install

cd ./sudo-SUDO_1_8_31p2 mkdir build ./configure --prefix = /home/pwn/sudo CFLAGS = "-O0 -g " make && make install

Vulnerability

#poc./sudoedit -s  '\' 11111111111111111111111111111111111111111111111111111111111111

Executing the above POC and executing sudoedit will display the words malloc(): invalid size, which is a typical exception caused by a heap overflow.

​​​​​​​​

 Source:- https://tutorialboy24.blogspot.com/2023/07/unveiling-sudo-heap-overflow.htmlicon-default.png?t=N6B9https://tutorialboy24.blogspot.com/2023/07/unveiling-sudo-heap-overflow.html

Image description

Vulnerability Analysis

The Source code analysis

set_cmnd function 
File : plugins\sudoers\sudoers . c 
800 : static  int 
801 : set_cmnd ( void ) 
802 : { ... 819 :      if ( sudo_mode & ( MODE_RUN | MODE_EDIT | MODE_CHECK )) { //Need to meet the setting of the flag bit To enter the escape process ... 845 : 846 : /* set user_args */ 847 : if ( NewArgc > 1 ) { 848 :char  * to , * from , ** av ; 
849 : size_t size , n ;         
850 : 
851 : /* Alloc and build up user_args. */        
852 : for ( size = 0 , av = NewArgv + 1 ; * av ; av ++ ) //Traverse each parameter              
853 : size += strlen ( * av ) +          1 ; // Calculate the length of each parameter 
854 : if ( size == 0 || ( user_args = malloc ( size )) == NULL ) { // Dynamically allocate a section of memory through malloc to store parameter content              
855 : sudo_warnx ( U_ ( "%s: %s" ), __func__ , U_ ( "unable to allocate memory" ));        
856 : debug_return_int ( - 1 );        
857 :        } 
858 : if       ( ISSET ( sudo_mode , MODE_SHELL | MODE_LOGIN_SHELL )) { //The setting of the flag bit needs to be satisfied to enter the escape process 
859 : /*        
860: * When running a command via a shell, the sudo front-end        
861: * escapes potential meta chars. We unescape non-spaces        
862: * for sudoers matching and logging purposes.        
863: */        
864 : for ( to = user_args , av = NewArgv + 1 ; ( from = * av ); av ++               ) { //Traverse each environment variable and copy the content to the memory 
865 : while ( * from ) {            /*

The vulnerability point, when scanning the parameter content, encounter \ needs to be escaped, such as '\t' , '\n', etc., so sudo only judges whether \ is followed by a space character, that is, the isspace function is used to judge . characters included in isspace are as follows: ' ' (0x20) space (SPC) space character '\t' (0x09) horizontal tab (TAB) horizontal tab character '\n' (0x0a) newline ( LF) newline character '\v' (0x0b) vertical tab (VT ) vertical tab character '\f' (0x0c) feed (FF) form feed character '\r' (0x0d) carriage return (CR) does not include '' above carriage return . The parameters are separated by '', so when '\' is followed by '', from++ will cause the next parameter to be copied in,and finally cause the heap block to overflow.*/ 866 :

           ==  '\\'  &&  ! isspace (( unsigned  char ) from [ 1 ])) 
867 : from ++ ;                
868 : * to ++ = * from ++ ;              
869 :     }        
870 : * to ++ = ' ' ;              
871 : }        
872 : *-- to = '' ;        

Therefore, the vulnerability lies in the need to escape the escape character when entering the set_cmnd function, but the function does not judge the escape character as the end of the parameter, that is, \ + \x00

parse_args function

The parse_args function is used to reverse escaping, that is, if there are escape characters in the parameter, a \ will be added before each escape character

File : src\parse_args . c 
592 :      if ( ISSET ( mode , MODE_RUN ) &&  ISSET ( flags , MODE_SHELL )) { //The setting of the flag bit needs to be satisfied before entering the reverse escape process 
593 : char ** av , * cmnd = NULL ;       
594 : int ac = 1 ;       
595 : 
596 : if ( argc != 0 ) {      
597: /* shell -c "command" */        
598 : char * src , * dst ;         
599 : size_t cmnd_size = ( size_t ) ( argv [ argc - 1 ] - argv [ 0 ]) +             
600 : strlen ( argv [ argc - 1 ]) + 1 ;           
601 : 
602 : cmnd = dst = reallocarray           ( NULL , cmnd_size , 2 ); 
603 : if ( cmnd == NULL )          
604 : sudo_fatalx ( U_ ( "%s: %s" ), __func__ , U_ ( "unable to allocate memory" ));        
605 : if ( ! gc_add ( GC_PTR , cmnd ))        
606 : exit ( 1 );        
607 : 
608 : for (       av  =  argv ; * av  !=  NULL ; av ++ ) { 
609 : for ( src = * av ; * src != '' ; src ++ ) {            
610 : /* quote potential meta characters */            
611 : if ( ! isalnum (( unsigned char ) * src ) && * src != '_' && * src                  !=  '-'  &&  * src  !=  '$' ) 
612 : * dst ++ = '\\' ;              
613 : * dst ++ = * src ;              
614 : }        
615 : * dst ++ = ' ' ;          
616 :        } 
617 : if ( cmnd != dst )          
618 : dst -- ;   /* replace last space with a NUL */        
619: * dst = '' ;          
620 : 
621 : ac += 2 ; /* -c cmnd */          
622 :    }

This is why the set_cmnd function needs to escape the parameters, so if the parse_args function is first used to reverse the parameters, and then the set_cmnd function is used to escape, then there will be no loopholes in sudo Bypass
inspection

So how to bypass the set_cmnd function and directly enter the parse_args function is the key factor for the vulnerability to be successfully triggered

The first is how to enter the set_cmnd function, sudo will go through double detection

  • sudo_mode needs to have the flag bit of MODE_RUN, MODE_EDIT or MODE_CHECK

  • sudo_mode needs to have the flag bit of MODE_SHELL or MODE_LOGIN_SHELL

File : plugins\sudoers\sudoers . c ... 819 :      if ( sudo_mode & ( MODE_RUN | MODE_EDIT | MODE_CHECK )) { //The setting of the flag bit needs to be satisfied to enter the escape process ... 858 : if ( ISSET ( sudo_mode , MODE_SHELL | MODE_LOGIN_SHELL )) { // Need to meet the setting of the flag bit to enter the escape process If you want to get the flag bit of MODE_SHELL, you need to set the -s parameter, at this time through SET ( flags , MODE_SHELL ), set the flag to MODE_SHELL, and the default mode is NULL, so setting the -s parameter can make the flag set both MODE_SHELL and MODE_RUN. 
File : src\parse_args . c 
479 : case 's' :         
480 : sudo_settings [ ARG_USER_SHELL ]. value = "true" ;              
481 : SET ( flags , MODE_SHELL );            
482 : break ;            ... 534 : if ( ! mode ) 535 : mode = MODE_RUN; /* running a command */         
536 : }

But if you use sudo -s, it will cause the flag to set MODE_SHELL and MODE_RUN, and you will enter the process of the parse_args function, which will add a '\' in front of all non-alphanumeric characters, which will cause us to fail. Construct the vulnerability character of '' + '\x00', so if we want to exploit the vulnerability successfully, we don't need the program to enter the set_cmd function, but we cannot enter the parse_args function

File : src\parse_args . c 
592 :      if ( ISSET ( mode , MODE_RUN ) &&  ISSET ( flags , MODE_SHELL )) { //The setting of the flag bit needs to be satisfied before entering the anti-escaping process ... 608 : for ( av = argv ; * av != NULL ; av ++ ) { 609 : for ( src = * av ; * src !='' ; src ++ ) { 
610 : /* quote potential meta characters */            
611 : if ( ! isalnum (( unsigned char ) * src ) && * src != '_' && * src != '-' && * src != '$' )                        
612 : * dst ++ = '\\' ;              
613 : * dst ++ = * src             ; 
614 : }        ... 622 : }

At the beginning of the parse_args function, it will detect whether it is called by sudo or sudoedit. If it is called by sudoedit, it will directly set MODE_EDIT to the mode, thus bypassing the mode==NULL. When the flag needs to be set to MODE_RUN , so use sudoedit -s, you can set the flag to set MODE_EDIT and set MODE_SHELL

File : src\parse_args . c ... 265 :      proglen = strlen ( progname ); 266 :      if ( proglen > 4 && strcmp ( progname + proglen - 4 , "edit" ) == 0 ) { 267 : progname = "sudoedit " ; 268 : mode = MODE_EDIT ; 269 : sudo_settings [ARG_SUDOEDIT ]. value  =  "true" ; 
270 : }

The second path to enter set_cmnd is to set the flag to MODE_EDIT | MODE_SHELL. Such input can bypass the parse_args function and prohibit entry to the set_cmd function. This is why the heap overflow of sudo needs to be triggered by sudoedit -s instead of sudo - the s

File : plugins\sudoers\sudoers . c ... 819 :      if ( sudo_mode & ( MODE_RUN | MODE_EDIT | MODE_CHECK )) { //The setting of the flag bit needs to be satisfied to enter the escape process ... 858 : if ( ISSET ( sudo_mode , MODE_SHELL | MODE_LOGIN_SHELL )) { // Need to meet the setting of the flag bit to enter the escape process

exploit

Vulnerability Exploitation Analysis

Since the program has an obvious heap overflow vulnerability, it is necessary to sort out how the heap overflow is exploited.

• Find a heap block whose value will affect the flow of program execution, which is called an available heap block.

• Find an operation that can freely control the location of the heap block, and deploy the heap block applied by the vulnerable function above the exploitable heap block. When the heap overflow is triggered, the value of the exploitable heap block can be rewritten to our expected value.

Available Heaps

NSS is used to parse and obtain different types of name information, such as how to obtain user information by name, and NSS needs to be called when sudo needs to obtain user information.

When using NSS to obtain information, it actually performs corresponding behaviors through different dynamic link libraries, and the file names of these libraries exist in the configuration file of /etc/nsswitch.conf

Image description

For example, if you want to query the passwd file, you need to use libnss_files.so and libnss_systemed.so

Image description

So how to load these dynamic link libraries needs to depend on the nss_load_library function, and this related information is stored in the service_user structure, which is stored in the heap memory.

Image description

Then it is necessary to study whether the value of the structure will affect the execution flow of the program. The code is as follows.

File : nsswitch .c 327 : static int 328 : 
nss_load_library  ( service_user * ni ) 329 : { 330 :    if ( ni -> library == NULL ) 331 : { 332 :        / * This service has not yet been used. Fetch the service 333: library for it, creating a new one if need be. If there 334: is no service table from the file, this static variable 335:holds the head of the service_library list made from the 
336:    default configuration. */ 
337 :        static  name_database  default_table ; 
338 :        ni -> library  =  nss_new_service ( service_table  ? : & default_table , 
339 : ni -> name ); //if ni If the value of ->library is NULL, a new ni->library will be created and all members will be initialized                     
340 :        if ( ni -> library  ==  NULL ) 
341 :   return  - 1 ; 
342 : } 
343 : 
344 :    if ( ni -> library -> lib_handle  ==  NULL ) //Since ni->library is newly created, ni->library->lib_handle must be NULL 
345 : { 
346 :        /* Load the shared library. */ 
347 :        size_t  shlen  = ( 7  +  strlen ( ni -> name ) +  3 
348 : + strlen (              __nss_shlib_revision ) +  1 ); 
349 :        int  saved_errno  =  errno ; 
350 :        char  shlib_name [ shlen ]; 
351 : 
352 :        /* Construct shared object name. */ 
353 :        __st***y ( __st***y ( __st* **y ( __st***y ( shlib_name , 
354 : "libnss_" ),                          
355 : ni -> name ),                    
356: ".so" ), //shalib_name is obtained according to splicing              
357 : __nss_shlib_revision );        
358 : 
359 :        ni -> library -> lib_handle  =  __libc_dlopen ( shlib_name ); //load dynamic link library

The key point of the above code is that the program will use __libc_dlopen to open the dynamic link library specified by shalib_name, and shalib_name is obtained by a series of splicing through ni->name, and ni->name is stored in the structure service_user In *ni, the structure is stored in the heap memory. Then we found the key value ni->name, which is a key variable that can modify the execution flow of the program.

Image description

For example, if we change ni->name to X/test, then the final splicing result will get libnss_X/test.so, then if we create a new libnss_X in the current directory and create a test.so in the directory The dynamic link library, then sudo will load and execute the code in our dynamic link library. So far we have found the first key factor of utilization, which is the use of heap blocks.

The operation of arranging blocks

Since we have found the available heap blocks, if we can deploy the heap overflowed heap blocks above the available heap blocks, and use the heap overflow to modify ni->name, the effect of arbitrary code execution can be completed.

In the main function of sudo, the setlocate function will be executed. setlocale is a function used to set the locale of the program, and there are corresponding implementations in many programming languages​​and operating systems.

Regional settings refer to the collection of related information such as the language, region, date format, currency symbol, etc. used by the program at runtime. By setting the locale, the program can adapt to localization needs according to different regions and language environment s.

export LC_ALL=en_US.UTF-8@XXXX

In the setlocal function, a lot of heap block allocation and release operations are involved. When calling setlocal(LC_ALL,""), the program will search for the value of the locale through the value set by the environment variable, and the search for the environment variable depends on _nl_find_locale function.

_nl_find_locale function 
File : locale\findlocale . c 
101 : struct  __locale_data  * 
102 : _nl_find_locale ( const  char  * locale_path , size_t  locale_path_len , 
103 : int category , const char ** name )            
104 : { ... 184 :    /* LOCALE can consist of up to four recognized parts for the XPG syntax: 185: 186: language[_territory[.codeset]][@modifier]187: 
188: Besides the first all of them are allowed to be missing. If the 
189: full specified locale is not found, the less specific one are 
190: looked for. The various part will be stripped off according to 
191: the following order: 
192: (1) codeset        
193: (2) normalized codeset        
194: (3) territory        
195: (4) modifier        
196: */ /* The format of the area is C_en_US.UTF-8@XXXXXX _nl_explode_name is used for judgment (1 )(2)(3)(4)Which part exists and which part is missing */ 197 :    mask = _nl_explode_name ( loc_name , & language , &modifier , & territory , 
198 : & codeset , & normalized_codeset );               
199 :    if ( mask  ==  - 1 ) 
200 :      /* Memory allocate problem. */ 
201 :      return  NULL ; 
202 : //locale_file is dynamic for regional settings Memory allocation 205 :    locale_file = _nl_make_l10nflist ( & _nl_locale_file_list [ category ], 206 :locale_path , locale_path_len , mask , 
207 : language , territory , codeset ,                    
208 : normalized_codeset , modifier ,                    
209 : _nl_category_names_get ( category ), 0 ); // return NULL                    
210 : 
211 :    if ( locale_file  ==  NULL ) 
212 : { 
213 :        /* Find status record for addressed locale file. We have to search
214:    through all directories in the locale path. */ 
215 :        locale_file  =  _nl_make_l10nflist ( & _nl_locale_file_list [ category ], 
216 : locale_path , locale_path_len , mask ,                    
217 : language , territory , code set ,                    
218 : normalized_codeset , modifier ,                    
219 : _nl_category_names_get ( category ), 1 );                    
220:        if ( locale_file  ==  NULL ) 
221 : /* This means we are out of core. */    
222 : return NULL ;     
223 : } 
}
_nl_make_l10nflist* *function**

_nl_make_l10nflist will allocate heap blocks according to the value we pass in.

File : intl\l10nflist . c 
150 : struct  loaded_l10nfile  * 
151 : _nl_make_l10nflist ( struct  loaded_l10nfile  ** l10nfile_list , 
152 : const char * dirlist , size_t dirlist_len ,               
153 : int mask , const char * language , const char * territory ,                 
154 : const char *             codeset , const  char  * normalized_codeset , 
155 : const char * modifier ,              
156 : const char * filename , int do_allocate )               
157 : { ... 165 :    //Dynamic allocation according to the length of the area value we pass in 166 :    abs_filename = ( char * ) malloc ( dirlist_len 167 : + strlen ( language ) 168: + (( mask & XPG_TERRITORY ) != 0                     
169 : ? strlen ( territory ) + 1 : 0 )                       
170 : + (( mask & XPG_CODESET ) != 0                     
171 : ? strlen ( codeset ) + 1 : 0 )                       
172 : + (( mask & XPG_NORM_CODESET ) != 0                    
173 : ? strlen ( normalized_codeset ) + 1 : 0 )                       
174 : + (( mask & XPG_MODIFIER ) != 0                     
175 : ? strlen ( modifier ) + 1 : 0 )                       
176 : + 1 + strlen ( filename ) + 1 );                      
177 : ... 292 : }setlocale* *function**

The overall operation of the setlocale function is to read the value of the environment variable to obtain the value of the regional setting, and allocate the heap block size according to the value of the regional setting. If there is any specification that does not meet the regional value, all previously applied heap blocks will be released. .

File : locale\setlocale . c 
334 :        while ( category --  >  0 ) 
335 : if ( category != LC_ALL )      
336 :      { //Use the _nl_find_locale function to obtain the value of the environment variable and store it in newdata[category] 337 : newdata [ category ] = _nl_find_locale ( locale_path , locale_path_len , 338 : category , 339 : & newnames[ category ]); 
340 : ... 364 : else 365 :   { //Use the __strdup function to allocate space in the heap memory and copy newdata[category] into it 366 : newnames [ category ] = __strdup ( newnames [ category ] ); 367 : if ( newnames [ category ] == NULL ) 368 : break ; 369 :   } ... 393 : if (category  !=  LC_ALL  &&  newnames [ category ] !=  _nl_C_name 
394 : && newnames [ category ] != _nl_global_locale .__ names [ category ])            
395 : free (( char * ) newnames [ category ]) ; The primitive, as long as there is a regional setting value that does not conform to the specification, all previously applied heap blocks will be released     

Therefore, the size of the heap can be controlled by the area value, and then a wrong area value is set at the end to control the position of the heap. So far we have found an operation that can control the heap.

​​​​​​​​

 Source:- https://tutorialboy24.blogspot.com/2023/07/unveiling-sudo-heap-overflow.htmlicon-default.png?t=N6B9https://tutorialboy24.blogspot.com/2023/07/unveiling-sudo-heap-overflow.html

LC_IDENTIFICATION =  C.UTF-8@XX..XX  #If the length is 0x10, then malloc(0x10) LC_MEASUREMENT =  C.UTF-8@XX..XXX , #If the length is 0X20, then malloc(0x20) LC_TELEPHONE = XXXX #If it does not conform to the specification of the area value, free() will be called analysis of exp

Since we need to control the heap block of server_user, we need to know the size of the heap block. Through debugging, we can see that it is a heap block of 0x40, so use setlocate to release a few more heap blocks of 0x40, then server_user will use what we released pile of blocks.

Image description

Immediately after that, allocate the vulnerability heap block above the server_user heap block. Since the server_user heap block is constructed by ourselves, we only need to release the vulnerability heap block while releasing the heap block, and the application for the vulnerability heap ap ap block can be set according to the length of the parameter

Image description

Set the function of setting the area value as the primitive of heap block allocation and release, and use the character after @ to control the size of the heap block

Image description

Freeing heap blocks with wrong region values

Image description

Finally, how to fill in the exploitable heap block. Here, heap overflow is used, and the filling string is constructed in the environment variable, so that the exploitable heap block can overwrite the content value of the exploitable heap block. However, it should be noted here that we need to Ni->library is filled with \x00, and \x00 cannot be directly input into the environment variable, so it is necessary to observe how the vulnerable function copies characters again. According to the code analysis, as long as '' is followed by '\x0 0', then we can directly copy the value of \x00 to the heap memory. Then modify ni->name to the dynamic link library we think is constructed.

File : plugins\sudoers\sudoers . c 
866 : if ( from [ 0 ] == '\\' && ! isspace (( unsigned char ) from [ 1 ])) //if '\' is followed by '\x00'                
867 : from ++ ; //At this point from will point to \x00                
868 : * to ++ = * from ++ ; //Use \x00 to copy the value              
869 :     }       

Set multiple environment variables so that there are multiple '' + '\x00' in the memory, so use '\x00' to cover the memory value of the heap.

Image description

The demonstration effect is as follows

Image description

Bug Fixes

The repair of the vulnerability is to make an additional judgment on the flag bit of MODE_EDIT, and add a check of '' after ''

---  a / plugins / sudoers / sudoers . c Sat Jan 23 08 : 43 : 59 2021 - 0700       
+++  b / plugins / sudoers / sudoers . c Sat Jan 23 08 : 43 : 59 2021 - 0700       
@@  - 547 , 7  + 547 , 7  @@/* If run as root with SUDO_USER set, set sudo_user.pw to that user. */ / * XXX - causes confusion when root is not listed in sudoers */ - if ( sudo_mode & ( MODE_RUN | MODE_EDIT ) && prev_user != NULL ) { + if ( ISSET ( sudo_mode , MODE_RUN | MODE_EDIT ) && prev_user != NULL ) { if ( user_uid == 0 && strcmp ( prev_user ,"root" ) !=  0 ) { struct passwd * pw ; @@ - 932 , 8 + 932 , 8 @@ if ( user_cmnd == NULL ) user_cmnd = NewArgv [ 0 ]; - if ( sudo_mode & ( MODE_RUN | MODE_EDIT | MODE_CHECK )) { - if ( ISSET ( sudo_mode , MODE_RUN |MODE_CHECK )) { 
+     if ( ISSET ( sudo_mode , MODE_RUN | MODE_EDIT | MODE_CHECK )) { 
+ if ( ! ISSET ( sudo_mode , MODE_EDIT )) { // extra judgment on MODE_EDIT    const char * runchroot = user_runchroot ; if ( runchroot == NULL && def_runchroot != NULL && strcmp ( def_runchroot , "*") !=  0 ) 
@@  - 961 , 7  + 961 , 8  @@ sudo_warnx ( U_ ( "%s: %s" ), __func__ , U_ ( "unable to allocate memory" )); debug_return_int ( NOT_FOUND_ERROR );     } - if ( ISSET ( sudo_mode , MODE_SHELL | MODE_LOGIN_SHELL )) { + if ( ISSET ( sudo_mode ,MODE_SHELL | MODE_LOGIN_SHELL ) && 
+ ISSET ( sudo_mode , MODE_RUN )) { // sudo -s is required to escape            /* * When running a command via a shell, the sudo front-end * escapes potential meta chars. We unescape non- spaces @@ -969,10 +970,22 @@ */ for ( to = user_args , av = NewArgv + 1 ; ( from = * av ); av ++ ) { while ( * from ) { -if ( from [ 0 ] ==  '\\'  &&  ! isspace (( unsigned  char ) from [ 1 ])) 
+ if ( from [ 0 ] == '\\' && from [ 1 ] != '' && / / Added the judgment of ''                   
+ ! isspace (( unsigned char ) from [ 1 ])) {                 from ++ ; + } + if( size  - ( to  -  user_args ) <  1 ) { 
+ sudo_warnx ( U_ ( "internal error, %s overflow" ),                
+ __func__ );                
+ debug_return_int ( NOT_FOUND_ERROR );                
+ }            * to ++ = * from ++ ;     } + if ( size - ( to - user_args ) < 1 ) { + sudo_warnx( U_ ( "internal error, %s overflow" ), 
+ __func__ );                
+ debug_return_int ( NOT_FOUND_ERROR );            
+     }        * to ++ = ' ' ; } *-- to = '' ;

Summarize

sudo heap overflow attack process

First, use setlocate as the primitive for heap block allocation and release, and construct a suitable heap layout to ensure that the server_user heap block is as close as possible to the heap block created by the vulnerable code.

Secondly, the heap overflow is used to overwrite the ni->name value of the server_user heap block, and the overwritten value is a maliciously constructed dynamic link library name.

Finally, wait for the dynamic link library to be loaded and executed.

Limitations of Sudo Heap Overflow Exploitation

Since the sudo heap overflow depends on the layout of the heap, different versions of sudo or the operating system will affect the exploitation of the vulnerability.

​​​​​​​​Source :- https://tutorialboy24.blogspot.com/2023/07/unveiling-sudo-heap-overflow.htmlicon-default.png?t=N6B9https://tutorialboy24.blogspot.com/2023/07/unveiling-sudo-heap-overflow.html

这篇关于Unveiling the Sudo Heap Overflow Vulnerability (CVE-2021-3156): A Critical Security Flaw Reappears的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/236356

相关文章

idea maven编译报错Java heap space的解决方法

《ideamaven编译报错Javaheapspace的解决方法》这篇文章主要为大家详细介绍了ideamaven编译报错Javaheapspace的相关解决方法,文中的示例代码讲解详细,感兴趣的... 目录1.增加 Maven 编译的堆内存2. 增加 IntelliJ IDEA 的堆内存3. 优化 Mave

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

Spring Security方法级安全控制@PreAuthorize注解的灵活运用小结

《SpringSecurity方法级安全控制@PreAuthorize注解的灵活运用小结》本文将带着大家讲解@PreAuthorize注解的核心原理、SpEL表达式机制,并通过的示例代码演示如... 目录1. 前言2. @PreAuthorize 注解简介3. @PreAuthorize 核心原理解析拦截与

springboot security使用jwt认证方式

《springbootsecurity使用jwt认证方式》:本文主要介绍springbootsecurity使用jwt认证方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录前言代码示例依赖定义mapper定义用户信息的实体beansecurity相关的类提供登录接口测试提供一

springboot security验证码的登录实例

《springbootsecurity验证码的登录实例》:本文主要介绍springbootsecurity验证码的登录实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录前言代码示例引入依赖定义验证码生成器定义获取验证码及认证接口测试获取验证码登录总结前言在spring

springboot security快速使用示例详解

《springbootsecurity快速使用示例详解》:本文主要介绍springbootsecurity快速使用示例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝... 目录创www.chinasem.cn建spring boot项目生成脚手架配置依赖接口示例代码项目结构启用s

springboot security之前后端分离配置方式

《springbootsecurity之前后端分离配置方式》:本文主要介绍springbootsecurity之前后端分离配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的... 目录前言自定义配置认证失败自定义处理登录相关接口匿名访问前置文章总结前言spring boot secu

springboot简单集成Security配置的教程

《springboot简单集成Security配置的教程》:本文主要介绍springboot简单集成Security配置的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录集成Security安全框架引入依赖编写配置类WebSecurityConfig(自定义资源权限规则

最新Spring Security实战教程之Spring Security安全框架指南

《最新SpringSecurity实战教程之SpringSecurity安全框架指南》SpringSecurity是Spring生态系统中的核心组件,提供认证、授权和防护机制,以保护应用免受各种安... 目录前言什么是Spring Security?同类框架对比Spring Security典型应用场景传统

最新Spring Security实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)

《最新SpringSecurity实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)》本章节介绍了如何通过SpringSecurity实现从配置自定义登录页面、表单登录处理逻辑的配置,并简单模拟... 目录前言改造准备开始登录页改造自定义用户名密码登陆成功失败跳转问题自定义登出前后端分离适配方案结语前言