0 x01 background

Most WEB applications today have global filtering for SQL injection, such as using GPC in PHP or using the addslashes() function on the global file common.php to filter received arguments, especially single quotes. Secondary injection is also a more common type of injection, which involves both in and out of the library. Since there is a global escape, when entering the library:

Insert into table (username) values (‘ hack\ ‘);

This way the escape will disappear and become a hack ‘, so that if the hack ‘goes out of the library and is brought into the query, it will successfully introduce single quotes and cause injection.

The bug comes from dark clouds:www.wooyun.org/bugs/wooyun…



0x02 Environment Setup

In the background we used a lower version of the 74CMS program, version 3.4 (20140310)

① Source code can be found on the web, I packed a copy:pan.baidu.com/s/1c1mLCru

② Decompress to WWW 74CMS (20140310) directory, browser accesshttp://localhost/74cms(20140310)), and then follow the prompts to install step by step. If you have any problems with the installation, please go to Baidu or Google and visit the following picture after success:

0x03 Vulnerability Analysis

Part1: Source code structure

Source code structure is relatively clear, should be audited the most clear structure, there are mainly the following three pieces of content:

Index.php introduces the common.inc. PHP file. We follow common.inc. PHP and find a function that handles GPC:

` ` `
<? php if (! empty(_GET)) { _GET = addslashes_deep(_GET); } if (! empty(_POST)) {
P O S T = a d d s l a s h e s d e e p ( _POST = addslashes_deep(
_POST); }
C O O K I E = a d d s l a s h e s d e e p ( _COOKIE = addslashes_deep(
_COOKIE);
R E Q U E S T = a d d s l a s h e s d e e p ( _REQUEST = addslashes_deep(
_REQUEST);
` ` `

 

As you can see, the server does addslashes for both GET and POST request variables.

Part2: Audit process

1. Post your resume first:

` ` `
elseif (act == ‘make4_save’) { resume_education = get_resume_education(
S E S S I O N [ u i d ] . _SESSION[‘uid’],
_REQUEST[‘pid’]); if (count(
r e s u m e e d u c a t i o n ) > = 6 ) s h o w m s g ( Educational experience cannot be exceeded 6 article ! . 1 . Resume_education) >= 6) showmsg(‘ No more than 6 educational experiences! ‘, 1,
link);
s e t s q l a r r [ u i d ] = i n t v a l ( setsqlarr[‘uid’] = intval(
_SESSION[‘uid’]);
s e t s q l a r r [ p i d ] = i n t v a l ( setsqlarr[‘pid’] = intval(
_REQUEST[‘pid’]); if ($setsqlarr[‘uid’] == 0
` ` `

 

Insert () {insert (); insert (); Let’s start with the check_resume function after inserttables

` ` `
Function check_resume(
u i d . uid,
pid) { global
d b . db,
timestamp,
C F G ; _CFG;
uid = intval(
u i d ) ; uid);
pid = intval(
p i d ) ; pid);
percent = 0;
r e s u m e b a s i c = g e t r e s u m e b a s i c ( resume_basic = get_resume_basic(
uid,
p i d ) ; pid);
resume_intention =
r e s u m e b a s i c [ i n t e n t i o n j o b s ] ; resume_basic[‘intention_jobs’];
resume_specialty =
r e s u m e b a s i c [ s p e c i a l t y ] ; / / Get education experience, out of the database resume_basic[‘specialty’]; // Get education experience from database
resume_education = get_resume_education(
u i d . uid,
pid); if (! empty(
r e s u m e b a s i c ) ) resume_basic))
percent =
p e r c e n t + 15 ; i f ( ! e m p t y ( percent + 15; if (! empty(
resume_intention))
p e r c e n t = percent =
percent + 15; if (! empty(
r e s u m e s p e c i a l t y ) ) resume_specialty))
percent =
p e r c e n t + 15 ; i f ( ! e m p t y ( percent + 15; if (! empty(
resume_education))
p e r c e n t = percent =
percent + 15; if (resume_basic[‘photo_img’] && resume_basic[‘photo_audit’] == “1” && resume_basic[‘photo_display’] == “1”) { setsqlarr[‘photo’] = 1; } else { setsqlarr[‘photo’] = 0; } if (percent < 60) {
s e t s q l a r r [ c o m p l e t e p e r c e n t ] = setsqlarr[‘complete_percent’] =
percent; setsqlarr[‘complete’] = 2; } else { resume_work = get_resume_work(
u i d . uid,
pid);
r e s u m e t r a i n i n g = g e t r e s u m e t r a i n i n g ( resume_training = get_resume_training(
uid,
p i d ) ; pid);
resume_photo =
r e s u m e b a s i c [ p h o t o i m g ] ; i f ( ! e m p t y ( resume_basic[‘photo_img’]; if (! empty(
resume_work))
p e r c e n t = percent =
percent + 13; if (! empty(
r e s u m e t r a i n i n g ) ) resume_training))
percent =
p e r c e n t + 13 ; i f ( ! e m p t y ( percent + 13; if (! empty(
resume_photo))
p e r c e n t = percent =
percent + 14;
s e t s q l a r r [ c o m p l e t e ] = 1 ; setsqlarr[‘complete’] = 1;
setsqlarr[‘complete_percent’] =
p e r c e n t ; r e q u i r e o n c e ( Q I S H I R O O T P A T H . i n c l u d e / s p l i t w o r d . c l a s s . p h p ) ; percent; require_once(QISHI_ROOT_PATH . ‘include/splitword.class.php’);
sp = new SPWord();
s e t s q l a r r [ k e y ] = setsqlarr[‘key’] =
resume_basic[‘intention_jobs’] .
r e s u m e b a s i c [ r e c e n t j o b s ] . resume_basic[‘recentjobs’] .
resume_basic[‘specialty’]; setsqlarr[‘key’] = “{resume_basic[‘fullname’]} ” .
s p > e x t r a c t t a g ( sp->extracttag(
setsqlarr[‘key’]);
s e t s q l a r r [ k e y ] = s t r r e p l a c e ( . . . setsqlarr[‘key’] = str_replace(“,”, ” “,
resume_basic[‘intention_jobs’]) . ” {setsqlarr[‘key’]} {resume_basic[‘education_cn’]}”;
s e t s q l a r r [ k e y ] = setsqlarr[‘key’] =
sp->pad(
s e t s q l a r r [ k e y ] ) ; i f ( ! e m p t y ( setsqlarr[‘key’]); if (! empty(
Resume_education)) {// Go through all the fields of the education experience and add them to the array.
r e s u m e e d u c a t i o n a s resume_education as
li) { setsqlarr[‘key’] = “{li[‘school’]} {setsqlarr[‘key’]} {li[‘speciality’]}”; }}
s e t s q l a r r [ r e f r e s h t i m e ] = setsqlarr[‘refreshtime’] =
timestamp; } // The education experience is updated, and the secondary injection is generated! updatetable(table(‘resume’),setsqlarr, “uid='{uid}’ AND id='{pid}'”); updatetable(table(‘resume_tmp’), setsqlarr, “uid='{uid}’ AND id='{pid}'”);
` ` `

 

3. We fill in a resume for a simple experiment, and fill aa ‘in the school name field of education Experience section.



Error statement found after save:

0x04 Vulnerability proof

Construct a POC to get information about database users:



Resume name changed to root@localhost:



The update statement was executed successfully:



Finally, interested students can continue to obtain other administrator accounts and other related fields of information.

In this paper, by HackBraid summarize, the original link: www.cnbraid.com/2016/02/19/… , please contact the author for reprint.