[PHP code audit instance tutorial] SQL injection-4. global protection Bypass second injection 0x01 background
Currently, WEB programs basically have global filtering for SQL injection, such as enabling GPC in PHP or common in global files. use the addslashes () function on php to filter the received parameters, especially single quotes. Secondary injection is also a common injection that involves warehouse receiving and warehouse picking. When receiving data because of global escape:
Insert into table (username) values ('hack \'');
In this way, the escape character will disappear into the hack, so that if the hack is imported into the query, the single quotation marks will be successfully introduced, resulting in injection.
The vulnerability comes from Wooyun:
Http://www.wooyun.org/bugs/wooyun-2014-068362
0x02 environment setup
Check the background. We use the 74cms program of a lower version. the version is 3.4 (20140310)
Source code can be found online, I packed a: http://pan.baidu.com/s/1c1mLCru
② Decompress the package to the 74cms (20140310) Directory of www, access http: // localhost/74cms (20140310) in the browser, and install it step by step as prompted, if you have any problems with the installation, go to baidu or google. after successful installation, visit:
0x03 vulnerability analysis Part1: Source code structure
The source code structure is clear, and it should be the clearest structure Audited. It mainly includes the following three parts:
Index. php introduced the common. inc. php file. we followed up with common. inc. php and found the function for processing gpc:
if (!empty($_GET)){$_GET = addslashes_deep($_GET);}if (!empty($_POST)){$_POST = addslashes_deep($_POST);}$_COOKIE = addslashes_deep($_COOKIE);$_REQUEST = addslashes_deep($_REQUEST);
We can see that addslashes will be processed when the server processes the GET and POST requests.
Part2: audit process
1. First, go to your resume:
Elseif ($ act = 'make4 _ save') {$ resume_education = get_resume_education ($ _ SESSION ['uid'], $ _ REQUEST ['pid ']); if (count ($ resume_education)> = 6) showmsg ('educational experience cannot exceed 6! ', 1, $ link); $ setsqlarr ['uid'] = intval ($ _ SESSION ['uid']); $ setsqlarr ['pid '] = intval ($ _ REQUEST ['pid']); if ($ setsqlarr ['uid'] = 0 | $ setsqlarr ['pid'] = 0) showmsg ('Parameter error! ', 1); $ setsqlarr ['start'] = trim ($ _ POST ['start'])? $ _ POST ['start']: showmsg ('Enter the start time! ', 1, $ link); $ setsqlarr ['endtime'] = trim ($ _ POST ['endtime'])? $ _ POST ['endtime']: showmsg ('enter the end time! ', 1, $ link); $ setsqlarr ['school'] = trim ($ _ POST ['school '])? $ _ POST ['school ']: showmsg (' enter the school name! ', 1, $ link); $ setsqlarr ['speciality'] = trim ($ _ POST ['speciality '])? $ _ POST ['speciality ']: showmsg (' enter a professional name! ', 1, $ link); $ setsqlarr ['ucation'] = trim ($ _ POST ['ucation'])? $ _ POST ['education']: showmsg ('select a degree! ', 1, $ link); $ setsqlarr ['Education _ cn'] = trim ($ _ POST ['Education _ cn'])? $ _ POST ['Education _ cn']: showmsg ('select a degree! ', 1, $ link); // you can see the insert table qs_resume_education, import fields related to the education background to the database if (inserttable (table ('resume _ education '), $ setsqlarr) {check_resume ($ _ SESSION ['uid'], intval ($ _ REQUEST ['pid ']);
2. here we can see that the insert statement is written into the database. you can try to add a single quotation mark, and the escape characters will be removed after the statement is written into the database. We will continue to follow up the check_resume function after inserttables.
// Check the resume completion level function check_resume ($ uid, $ pid) {global $ db, $ timestamp, $ _ CFG; $ uid = intval ($ uid ); $ pid = intval ($ pid); $ percent = 0; $ resume_basic = get_resume_basic ($ uid, $ pid); $ resume_intention = $ resume_basic ['intention _ job']; $ resume_specialty = $ resume_basic ['specialty ']; // Obtain the educational experience. $ resume_education = get_resume_education ($ uid, $ pid) is logged out of the database. if (! Empty ($ resume_basic) $ percent = $ percent + 15; if (! Empty ($ resume_intention) $ percent = $ percent + 15; if (! Empty ($ resume_specialty) $ percent = $ percent + 15; if (! Empty ($ resume_education) $ 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) {$ setsqlarr ['complete _ percent '] = $ percent; $ setsqlarr ['complete'] = 2;} else {$ resume_work = get_resume_work ($ uid, $ pid ); $ resume_training = get_resume_training ($ uid, $ pid); $ resume_photo = $ Resume_basic ['photo _ img ']; if (! Empty ($ resume_work) $ percent = $ percent + 13; if (! Empty ($ resume_training) $ percent = $ percent + 13; if (! Empty ($ resume_photo) $ percent = $ percent + 14; $ setsqlarr ['complete'] = 1; $ setsqlarr ['complete _ percent '] = $ percent; require_once (QISHI_ROOT_PATH. 'include/splitword. class. php '); $ sp = new SPWord (); $ setsqlarr ['key'] = $ resume_basic ['intention _ job']. $ resume_basic ['centjobs']. $ resume_basic ['specialty ']; $ setsqlarr ['key'] = "{$ resume_basic ['fullname']}". $ sp-> extracttag ($ setsqlarr ['key']); $ setsqlarr ['key'] = s Tr_replace (",", "", $ resume_basic ['intention _ Jobs']). "{$ setsqlarr ['key']} {$ resume_basic ['Education _ cn']}"; $ setsqlarr ['key'] = $ sp-> pad ($ setsqlarr ['key']); if (! Empty ($ resume_education) {// traverse all fields of educational experience and add them to the array foreach ($ resume_education as $ li) {$ setsqlarr ['key'] = "{$ li ['school ']} {$ setsqlarr ['key']} {$ li ['speciality']}";}} $ setsqlarr ['refreshtime'] = $ timestamp;} // the educational experience is updated here, resulting in second injection! Updatetable (table ('resume'), $ setsqlarr, "uid = '{$ uid}' AND id = '{$ pid }'"); updatetable (table ('resume _ tmp '), $ setsqlarr, "uid =' {$ uid} 'AND id =' {$ pid }'");
3. fill in a resume. in a simple test, fill in the school name field in the education experience section as "aa'
An error message is displayed after saving:
0x04 proof of vulnerability
Construct the POC for getting database user information:
Check the resume and find that the resume name is changed to root @ localhost:
Check the SQL statement and find that the update statement is successfully executed:
Finally, if you are interested, you can continue to obtain information about other administrator accounts and other related fields.
Original article address:
Http://www.cnbraid.com/2016/02/19/sql3/