




已阅读5页,还剩69页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Modsecurity调研报告,郭川2012年2月13日,调研目的,分析Modsecurity模块作为Apache框架下的一个规则引擎的执行流程,以期在Nginx下实现具有类似功能的规则引擎模块,内容,Modsecurity执行流程 Modsecurity移植问题 重要函数流程图,Modsecurity执行流程,读取规则、翻译规则、规则生效简介规则格式、指令哈希表、规则引擎介绍读取规则、翻译规则、规则生效详解,读取规则,时间:Apache启动阶段位置:配置文件,例如 httpd.conf 中存储数据结构:配置树,数据结构选择树是由配置文件中的配置信息结构决定的,翻译规则,时间:Apache启动阶段,读取配置文件后方法:利用规则引擎(规则引擎是 Modsecurity 模块添加的一个钩子函数建立的)存储结构:Modsecurity 模块中定义了存储一条及多条规则的结构体结果:构建了存储多条可使用的规则的结构体,规则生效,时间:Apache 读取、处理以及响应请求过程中的某一点(Modsecurity 模块注册了钩子函数的地方)过程:根据翻译好的规则,进行匹配检查结果:若匹配,则执行规则中的相应动作,规则格式,一条规则实例:SecRule REMOTE_ADDR 05$ redirect:其中SecRule是指令名称,其后所跟是该指令的参数。Modsecurity 定义的指令有60多条,并且各条指令的参数格式不同。指令(Directives)举例:SecAction;SecDefaultAction;SecMarker;SecRuleEngine;SecRule;SecRuleInheritance;SecRequestBodyAccess ,规则格式,SecRule 的参数格式如下:SecRule VARIABLES OPERATOR TRANSFORMATION_FUNCTIONS, ACTIONSVARIABLES举例:QUERY_STRING; REMOTE_ADDR; REQUEST_BODY OPERATOR举例:rx; eq; ge; gt; le; lt TRANSFORMATION_FUNCTIONS举例: lowercase; urlDecode; removeWhitespace ACTIONS举例:allow; msg; id; deny; phase; skip; chain ,指令哈希表,Apache 的每一个模块都有自己定义的指令数组指令数组在模块被添加的时候被 Apache 保存所有的指令被 Apache 保存在指令哈希表中。利用这个哈希表,由指令名字可以快速获取到Apache中保存的关于该条指令的一个结构体,指令哈希表,指令哈希表是在 Apache 启动阶段加载模块的过程中通过读取模块定义的指令数组建立的存储指令的哈希表Modsecurity模块的定义:module AP_MODULE_DECLARE_DATA security2_module = STANDARD20_MODULE_STUFF, create_directory_config, merge_directory_configs, NULL, /* create_server_config */ NULL, /* merge_server_configs */ module_directives, register_hooks;其中,moduel_directives 是 Modsecurity 模块定义的指令数组。,哈希表结构体,哈希表元素结构体,模块链结构体,模块结构体,指令哈希表ap_conf_hash,指令存储结构体,建立规则引擎,时间:读取规则之后,解析规则之前使用Modsecurity的钩子函数hook_pre_configSecRule的语法也即其参数格式如下:SecRule VARIABLES OPERATOR TRANSFORMATION_FUNCTIONS, ACTIONS将VARIABLES OPERATOR TRANSFORMATION_FUNCTIONS ACTIONS 四个域对应的所有可选值存储到一个类型为msc_egine的结构体中,这个结构体就称为规 则引擎。,规则引擎modsecurity,模块引擎结构体,规则引擎结构体,规则变换函数结构体,规则变量结构体,规则操作符结构体,规则动作结构体,读取规则,读取配置文件中的每条配置信息,形成一颗配置树结构。配置树中结点结构如下:,配置树中指令结点结构体,读取规则,配置树:,配置树ap_conftree,配置树中指令结点结构体,遍历配置树并执行每个结点中的指令的过程,读取规则,翻译规则,遍历配置树中的每一条规则根据规则名称查找指令哈希表执行指令结构中的相应函数,指令哈希表中的指令存储结构,SecRule指令的存储结构,相应的函数即cmd_rule(),翻译规则,cmd_rule() 函数利用规则引擎翻译规则,并保存翻译后的规则规则解释好以后,被存储到Modsecurity模块定义的规则结构体(msre_rule)中,所有的规则都存储到规则集结构体中(msre_ruleset)中cmd_rule()函数是Modsecurity模块中最重要的两个函数之一,另一个是modsecurity_process_phase(),翻译规则,规则举例:SecRule REMOTE_ADDR 05$ redirect: 使用REMOTE_ADDR从规则库中取出相应的msre_var_metadata 类型的变量结构体:,规则变量结构体的定义,存储变量REMOTE_ADDR的结构体,翻译规则,使用“05$” 从规则库中取出类型为msre_op_metadata类型的操作符结构体:使用“redirect: ” 从规则库中取出类型为msre_action_metadata类型的动作结构体:,规则操作符结构体,规则操作符结构体实例,规则动作结构体,规则动作结构体实例,翻译规则,规则翻译的步骤:规则库中存储msre_var | op | tfn | action_metadata 类型的结构体根据规则中的具体变量名从规则库中取到对应的结构体将一条规则的相关信息存储到一个规则结构体中将所有规则按照执行阶段的不同存储到一个规则集结构体中,规则集和规则,*规则存储*,规则集,动作,规则,变量,动作集,动作和动作集,规则生效,时间:在Apache处理请求的过程中,添加钩子函数,Modsecurity 的钩子函数中使用规则对请求进行处理过程:变量决定数据操作符决定匹配动作决定去向首先生成具体变量,其次根据操作符进行匹配,若匹配成功,则完成相应动作。,规则生效,规则被解释后得到的规则结构体中存储着各个域对应的结构体,结构体中存储相应的函数指针使用如下规则详细解释SecRule REMOTE_ADDR 05$ redirect: ,SecRule REMOTE_ADDR 05$ redirect: ,变量REMOTE_ADDR对应的结构体,其中函数var_romote_addr_generate的作用是获得访问端ip地址并保存。,函数将modsec_rec类型结构体中remote_addr的值保存到mare_var类型的结构体中。,例子中变量域为”REMOTE_ADDR”,SecRule REMOTE_ADDR 05$ redirect: ,例子中操作符域为05$,默认操作符为“rx”,及正则表达式匹配方式,函数msre_op_rx_execute将操作符的参数(此例中参数为05 )与已获得的变量相匹配,并返回匹配结果标识。,SecRule REMOTE_ADDR 05$ redirect: ,规则动作结构体实例,函数msre_action_redirect_validate检验参数是否合法;msre_action_redirect_execute函数将从定向地址赋给rule-actionset-intercept_uri,例子中动作域为redirect: ,重要结构体总结,规则引擎:msc_engine; msre_engine; msre_var_metadata; msre_op_metadata; msre_tfn_metadata; msre_action_metadata;规则使用:modsec_rec; directory_rec; msre_ruleset; msre_rule; msre_var;msre_actionset; msre_action;,执行流程总结,加载模块,读取指令数组,建立指令哈希表读取配置文件中的规则,建立配置树一个挂钩函数,建立规则库处理配置树,查询指令哈希表,使用规则库翻译规则处理请求,执行钩子函数,匹配规则,移植问题,modsecurity规则集的维护独立作为另外一个项目,网址如下:/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project移植的modsecurity应至少能翻译最小规则集(Rules Language Porting Spec)中的规则。实现nginx下的规则引擎主要参考apache下modsecurity的实现。,移植问题,将modsecurity模块从apache下移植到nginx下需要注意的问题是modsecurity中与apache有联系的部分,modsecurity独立实现部分直接复制就行。,中间相互关联的一部分是移植过程中应该重点考虑的地方,在apache框架下实现的规则引擎,移植问题,模块定义:apache通过加载模块来使用modsecurity实现的规则解释功能,定义模块结构体可以看做是定义apache核心和modsecurity所实现功能的一个接口,加载模块的过程就是apache了解模块实现哪些功能的过程,Apache中定义模块的结构体,Nginx中定义模块的结构体,Apache和nginx中模块结构体比较,移植问题,读取、处理配置信息:需要将apache和nginx读取、处理配置信息的方式作比较规则存储在配置文件中,apache读取配置文件过程中,将每一条规则作为一条独立的配置信息,Apache 配置信息的存储数据结构图解,Structure of the perrequest configuration processor: The walk procedures,移植问题,规则生效:各个域对应的结构体中有相应的函数,在函数的执行过程中会用到apache中的一些数据,此时就需要使用保存的apache数据。,规则操作符结构体实例,规则动作结构体实例,规则变量结构体实例,移植问题,规则生效:modsecurity首先获取将会用到的apache中的数据,存储到类型为modsec_rec类型的结构体中,等到modsecurity中的函数需要时直接从此结构体中取到此结构体是modsecurity中最重要的两个结构体之一;另一个之一类型为directory_config,用于apache处理配置信息的过程中,request_rec,modsec_rec,msre_ruleset,directory_config,server_rec,notes,lookup_default,Apache和Modsecurity交互过程中的主要结构体,Apache结构体,*规则存储*,规则集,动作,规则,变量,动作集,重要函数流程图,规则添加函数(规则翻译函数)及规则生效函数流程图hook_request_early 、hook_request_late 、output_filter 三个函数的流程图,规则添加函数(规则翻译函数)及规则生效函数流程图,Apache2_config.c, Line 615;add_rule;,Line 629; dcfg-ruleset = msre_ruleset_create(modsecurity-msre, cmd-pool);/*Create a ruleset if one does not exist.*/,Line 653; dcfg-tmp_default_actionset = msre_actionset_create_default(modsecurity-msre);/*Create default actionset if one does not already exist.*/,Line 660; if (rule-actionset != NULL) /*Check syntax for chained rules.*/,Line 702; rule-actionset = msre_actionset_merge(modsecurity-msre, dcfg-tmp_default_actionset, rule-actionset, 1);/*Check syntax for chained rules.*/,Line 720; if (dcfg-tmp_chain_starter != NULL);/*如果规则属于某规则链,则设置链头.*/,规则添加流程图,Apache2_config.c, Line 615;add_rule;,Line 725; if (rule-actionset-is_chained != 1); /*检查规则链中的一条规则是否还要继续连接此规则链.*/,Line 748; if (dcfg-tmp_rule_placeholders = NULL); dcfg-tmp_rule_placeholders = apr_table_make(cmd-pool, 10);/*Create skip table if one does not already exist.*/,Line 753; if (rule-actionset-skip_after != NOT_SET_P); apr_table_setn(dcfg-tmp_rule_placeholders, tmp_id, tmp_id);/*Keep track of any rule IDs we need to skip after.*/,Line 776; if (rule-actionset-id != NULL) & apr_table_get(dcfg-tmp_rule_placeholders, rule-actionset-id);/*检查当前添加规则的编号是否存在于数组dcfg-tmp_rule_placeholders中,若存在,则添加此规则后,数组中的编号即失效.*/,规则添加流程图,modsecurity.c, Line 659; modsecurity_process_phase;,Line 661;if (msr-was_intercepted)/*Check if we should run.*/,Line 670;if (msr-phase = phase);/*Do not process the same phase twice.*/,Line 682;if (msr-txcfg-cache_trans = MODSEC_CACHE_ENABLED); /*Clear out the transformation cache at the start of each phase.*/,Line 743; switch(phase); /*这一步是重点。根据当前所处的阶段phase,选择调用哪一个处理函数.*/,规则生效流程图1,modsecurity.c, Line 459; modsecurity_process_phase_request_headers;,Line 463;if (msr-txcfg-debuglog_level = 4);/*检查是否需要记录日志.*/,Line 467;time_before = apr_time_now();/*记录开始时间.*/,Line 469;if (msr-txcfg-ruleset != NULL);/*这一步是重点。 检查规则集是否为空,若不为空,调用规则集处理函数msre_ruleset_process_phase.*/,Line 473; msr-time_phase1 = apr_time_now() - time_before;/*计算此阶段规则集处理所花费时间,结束时间减去开始时间.*/,规则生效流程图2,re.c, Line 1078;msre_ruleset_process_phase;,Line 1089; switch (msr-phase);/*获取当前阶段的规则集.*/,Line 1122; for (i = 0; i nelts; i+);/*循环遍历当前阶段规则集中的所有规则.*/,Line 1134; if (mode = SKIP_RULES);/*是否有skipAfter动作.*/,Line 1189; if (mode = NEXT_CHAIN)/*规则链中有规则不匹配,则跳出此链.*/,Line 1203; if (mode = NEXT_RULE)/*/,Line 1223; if(apr_is_empty_array(msr-removed_rules_tag)=0);/*Check if this rule was removed at runtime.*/,Line 1300; if(msr-txcfg-is_enabled = MODSEC_DISABLED);,Line 1336; rc = msre_rule_process(rule, msr);/*重点。 经过一系列的检查,最终调用规则处理函数.*/,Line 1346; if (rc = RULE_NO_MATCH); /*后续处理.*/,规则生效流程图3,re.c, Line 2849; msre_rule_process;,Line 2851;if (msr-msc_rule_mptmp = NULL);/*处理每条规则时使用新的内存地址空间(新的子内存池),在这里创建新内存 Use a fresh memory sub-pool for processing each rule.*/,Line 2865;msre_rule_process_normal(rule, msr);/*重点。 调用真正的规则处理函数.Executes rule against the given transaction.*/,规则生效流程图4,re.c, Line 2271;msre_rule_process_normal;,Line 2303; for (i = 0; i targets-nelts; i+);/*处理变量域并保存其值。Expand variables to create a list of targets.*/,Line 2371; if (msr-txcfg-cache_trans != MODSEC_CACHE_DISABLED);/*Is this var cacheable?*/,Line 2337; if (msr-txcfg-debuglog_level = 4);/*记录变量处理的日志。Log the target variable expansion.*/,Line 2360; for (i = 0; i nelts; i+);/*遍历前面已经保存的生成的变量,针对每一次遍历:执行变换操作;并调用操作符函数execute_operator。Loop through targets on the final target list, perform transformations as necessary, and invoke the operator.*/,Line 2784;rc = execute_operator(var, rule, msr, acting_actionset, mptmp); /*重点。Execute operator.*/,Line 2469; /*Transform target.*/,规则生效流程图5,re.c, Line 2120;execute_operator;,Line 2136; if (var-param != NULL) /*确定完整变量名称*/,Line 2167; rc = rule-op_metadata-execute(msr, rule, var, /*Detect whether variable and operator matches?*/,Line 2255; msre_perform_nondisruptive_actions(msr, rule, rule-actionset, mptmp);/*根据操作符函数匹配的结果执行非中断性的动作.*/,Line 2261; msre_perform_disruptive_actions(msr, rule, acting_actionset, mptmp, my_error_msg);/*执行中断性动作,但要求该规则不属于规则链*/,规则生效流程图6,hook_request_early 、hook_request_late、output_filter 三个函数的流程图,mod_security2.c, Line 638; hook_request_early; /*初始化请求处理,在apache接收到请求头后马上执行。这个函数会创建新的modsec_rec类型结构体。*/,Line 639; modsec_rec *msr = NULL;/*定义空的类型为modsec_rec的结构体变量。*/,Line 651; msr = create_tx_context(r); /*初始化交易上下文并建立初始配置信息。这里是重点。初始化结构体msr。见下一页。*/,hook_request_early1,mod_security2.c, Line 350; create_tx_context;,Line 367; msr-dcfg1 = (directory_config *)ap_get_module_config(r-per_dir_config, /*获取apache中保存的关于此模块的配置信息*/,Line 388; msr-txcfg = merge_directory_configs(msr-mp, msr-txcfg, msr-dcfg1);/*合并配置信息结构体*/,Line 391; init_directory_config(msr-txcfg); /*设置配置结构体的初始默认值*/,Line 426; if (modsecurity_tx_init(msr) txid = get_env_var(r, “UNIQUE_ID”); /*获取命名的环境变量*/,Line 431; store_tx_context(msr, r);/*保存交易上下文到r-notes字段中: Line 344; apr_table_setn(r-notes, NOTE_MSR, (void *)msr);*/,modsecurity.c, Line 267; modsecurity_tx_init;,hook_request_early3,Line 277-281; /* 设置C-L(Content-Length) */,Line 284-296; /* 检查此请求是否存在请求体*/,Line 299-301; /* 设置C-T (Content-Type) */,Line 337-340; /* 检查是否必须缓冲,若是则只是用内存。*/,Line 304-334; /* 确定针对请求体的操作。挺重要的。*/,Line 380-390; /* 找到cookie headers 并解析*/,Line 343-359; /* 设置参数。在ARGS变量处理函数中会用到。*/Line 348; 函数parse_arguments(); /*解析参数并存储*/,mod_security2.c, Line 676; hook_request_late;,Line 738-746; /* REQUEST_HEADERS处理阶段 */,hook_request_late1,Line 691; msr = retrieve_tx_context(r); /* 取得交易上下文*/,Line 709; msr-dcfg2 = (directory_config *)ap_get_module_config(r-per_dir_config, /* 取得第二个配置信息*/,Line 713; msr-txcfg = create_directory_config(msr-mp, NULL);/* 创建交易上下文*/,Line 721; msr-txcfg = merge_directory_configs(msr-mp, msr-txcfg, msr-usercfg);/* 更新默认的用户设置*/,Line 723; init_directory_config(msr-txcfg); /* 初始化配置结构体 */,Line 765-789; /* 检查请求体是否过长*/,Line 799-843; /* 调用读取请求体的函数read_request_body(),并检查返回结果 */,Line 792-797; /* 确定是否提取多重文件*/,Line 854; msr-request_headers = apr_table_copy(msr-mp, r-headers_in);/* 更新请求头*/,Line 857-867; /* REQUEST_BODY处理阶段 */,Line 872-875; /* 只有当后台需要时才移除客户端设置的压缩标识。*/,Line 749-755; /* 检查在阶段一中是否有禁用规则引擎*/,mod_security2.c, Line 676; hook_request_late;,hook_request_late2,Line 189; bb_in = apr_brigade_create(msr-mp, r-connection-bucket_alloc); /* */,Line 194; rc = ap_get_brigade(r-input_filters, bb_in, AP_MODE_READBYTES, APR_BLOCK_READ, HUGE_STRING_LEN); /*使用注册的input_filter中的处理函数 ,如ap_http_filter。*/,apache2_io.c, Line 157; read_request_body;,hook_request_late3.1,Line 166; if (msr-reqbody_should_exist != 1) ; /*检查是否存在请求体*/,Line 173; if (msr-txcfg-reqbody_access != 1) ; /*检查是否允许访问请求体*/,Line 184; if (modsecurity_request_body_start(msr, error_msg) reqbody_length + buflen (apr_size_t)msr-txcfg-reqbody_limit) ; /* 检查请求体大小限制(should only trigger on chunked requests) */,Line 266; modsecurity_request_body_to_stream(msr, buf, buflen, error_msg); /* */,Line 309; modsecurity_request_body_end(msr, error_msg); /* */,apache2_io.c, Line 157; read_request_body;,hook_request_late3.2,Line 272; int rcbs = modsecurity_request_body_store(msr, buf, buflen, error_msg);/* 重点。将从请求体中取到的数据存储到modsec_rec结构体的相关字段中。 */,Line 305; apr_brigade_cleanup(bb_in); /* */,Line 228; rc = apr_bucket_read(bucket, /* */,Line 97; msre_reqbody_processor_metadata *metadata =; /*获取请求体处理器的元数据结构体*/,Line 100-137; /*确定请求体处理器是否为空及其种类*/,msc_reqbody.c, Line 82; modsecurity_request_body_start;/* Prepare to accept the request body (part 1). */,hook_request_late3.3,Line 91; apr_pool_create( /*另外建立一个新的内存池用以分配新的数据结构(not data, which is allocated via malloc).*/,Line 95-138; if (msr-msc_reqbody_processor != NULL) ; /*初始化请求体处理器*/,Line 140; return modsecurity_request_body_start_init(msr, error_msg); /*调用请求体处理的第二部分*/,Line 56-74; /*为将请求体保存到磁盘中做准备*/,Line 58; msr-msc_reqbody_filename = apr_psprintf(msr-mp, “%s/%s-%s-request_body-XXXXXX”, msr-txcfg-tmp_dir, current_filetime(msr-mp), msr-txid); /*确定磁盘上存储请求体的临时文件名*/,msc_reqbody.c, Line 43; modsecurity_request_body_start_init;/* Prepare to accept the request body (part 2). */,hook_request_late3.4,Line 46-55; if(msr-msc_reqbody_storage = MSC_REQBODY_MEMORY) /* 为将请求体保存到内存中做准备*/,Line 49; msr-msc_reqbody_chunks = apr_array_make(msr-msc_reqbody_mp, 32, sizeof(msc_data_chunk *); /*创建准备存储请求体数据的内存空间*/,Line 65; msr-msc_reqbody_fd = msc_mkstemp(char *)msr-msc_reqbody_filename);/* 在磁盘上创建保存请求体的临时文件*/,Line 653; msr-msc_reqbody_fd = open(msr-msc_reqbody_filename, O_RDONLY | O_BINARY); /*打开磁盘上将要存储请求体数据的文件*/,msc_reqbody.c, Line 621; modsecurity_request_body_retrieve_start;/*Prepares to forward the request body.*/,hook_request_late3.5,Line 628; msr-msc_reqbody_disk_chunk = apr_pcalloc(msr-msc_reqbody_mp, sizeof(msc_data_chunk); /*/,Line 646; msr-msc_reqbody_disk_chunk-data = apr_palloc(msr-msc_reqbody_mp, CHUNK_CAPACITY); /*/,Line 624; if (msr-msc_reqbody_storage = MSC_REQBODY_MEMORY) ; /*判断请求体是否将存储在内存中*/,Line 637; if (msr-msc_reqbody_storage = MSC_REQBODY_DISK) ; /*判断请求体是否将存储在磁盘中*/,Line 638; msr-msc_reqbody_disk_chunk = apr_pcalloc(msr-msc_reqbody_mp, sizeof(msc_data_chunk); /*/,msc_reqbody.c, Line 687; modsecurity_request_body_retrieve;/*Returns one chunk of request body data. It stores a NULL in the chunk pointer when there is no data to return. The return code is 1 if more calls can be made to retrieve more data, 0 if there is no more data to retrieve, or -1 on error. The caller can limit the amount of data returned by providing a non-negative value in nbytes. */,hook_request_late3.6,Line 653; if (msr-msc_reqbody_storage = MSC_REQBODY_DISK) ;,Line 713-743; /*Advance to the current chunk and position on the next byte we need to send.*/,Line 700; if (msr-msc_reqbody_storage = MSC_REQBODY_MEMORY) ;,Line 708; *chunk = msr-msc_reqbody_disk_chunk; /*/,Line 765; i = read(msr-msc_reqbody_fd, msr-msc_reqbody_disk_chunk-data, my_nbytes);,Line 772; *chunk = msr-msc_reqbody_disk_chunk;,Line 373; return modsecurity_request_body_store_disk(msr, data, length, error_msg); /*将请求体数据块存储到磁盘上*/,msc_reqbody.c, Line 293; modsecurity_request_body_store;/* Stores one chunk of request body data. */,hook_request_late3.7,Line 302-360; if (msr-msc_reqbody_processor != NULL) & (msr-msc_reqbody_error = 0) /* If we have a processor for this request body send data to it first.*/,Line 369; return modsecurity_request_body_store_memory(msr, data, length, error_msg); /*将请求体数据块存储在内存中*/,Line 236-257; /*分配新的存储请求体数据的数据结构。*/,msc_reqbody.c, Line 166; modsecurity_request_body_store_memory;/* Stores one chunk of request body data in memory. */,hook_request_late3.9,Line 172-215; /* 检查需要存储的请求体数据块是否超出规定的限制大小.*/,Line 234-282; /*while循环将请求体数据块中的数据转存储在相关的数据结构中*/,Line 259-265; /*当前数据结构的剩余空间足够存储请求体数据*/,Line 266-280; /*当前数据结构空间有限,则填充满以后修改相关指针,并等待下次循环新建一个结构体*/,Line 626-637; /* Put back the Accept-Encoding and TE request headers if they were removed from the request. */,Line 640-729; if (msr-of_status = OF_STATUS_NOT_STARTED) ;/* Initialise on first invocation */,Line 650; rc = modsecurity_process_phase(msr, PHASE_RESPONSE_HEADERS);/* RESPONSE_HEADERS处理阶段*/,Line 610-615; /* 检查上下文内容是否为空*/,apache2_io.c, Line 602; output_filter;,output_filter1,Line 668-689; ap_add_output_filter(“MODSECURITY_OUT”, msr, r, r-connection);/* 确定是否需要检查response body. */,Line 692-711; /* If injecting content unset headers now. */,Line 714-723; /* Content i
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025电影制片人聘用合同电影范本
- 2025年省级公务员招聘的合同样本
- 2025个人物品抵押合同范本
- 2025年北京婚姻登记处自愿离婚合同范本
- 2025年绿色废物回收处理合同
- 2025年航空快递运输合同
- 2025年连锁奶茶店合作经营合同
- 2025建筑工程外架合同
- 2025年医疗护理机构员工劳动合同
- 2025关于科技公司劳动合同模板
- 2025年吉林省中考语文真题(含答案)
- 混凝土结构跳仓施工方案
- 页岩气开发地震监测技术要求DB50-T 1234-2022
- 水稳摊铺作业安全技术交底
- 实验室病原微生物危害 评估报告
- 科技项目申报专员系列培训(技术攻关项目)
- 品质异常处罚细则及奖罚制度
- 小升初英语学习方法指导PPT
- GB∕T 40753-2021 供应链安全管理体系 ISO 28000实施指南
- GA∕T 1577-2019 法庭科学 制式枪弹种类识别规范
- 福州市长乐区农村宅基地及房屋确权登记
评论
0/150
提交评论