尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

PHP变量覆盖漏洞实战解析:从extract到可变变量的安全攻防

PHP变量覆盖漏洞实战解析:从extract到可变变量的安全攻防
📅 发布时间:2026/7/1 11:11:18

1. 项目概述:从一道CTF题看PHP变量覆盖的实战价值

最近在复盘一些经典的CTF题目,特别是[BJDCTF2020]中的一道题,它把PHP变量覆盖漏洞的几种典型利用方式展现得淋漓尽致。对于很多刚接触Web安全或者PHP开发的朋友来说,“变量覆盖”这个词听起来可能有点抽象,甚至觉得它离日常开发很远。但实际情况恰恰相反,这种漏洞隐蔽性强,一旦出现,往往意味着整个应用的安全防线出现了根本性松动,攻击者可以借此绕过各种关键逻辑,比如身份验证、权限检查,甚至直接执行任意代码。

简单来说,PHP变量覆盖漏洞,就是指攻击者能够通过某种方式,将程序中已经定义或即将定义的变量值,替换成自己可控的值。这就像你本来在剧本里给一个角色设定了固定的台词和行动,但有人偷偷溜进后台,把剧本给改了,导致演员完全按照攻击者的意图来表演。在[BJDCTF2020]的这道题里,出题人非常巧妙地设置了三个不同的关卡,分别对应了三种最常见的变量覆盖触发场景:extract()函数、parse_str()函数以及通过$_REQUEST超全局数组的特定传参方式。通过深入拆解这道题,我们不仅能学会如何解题,更能透彻理解这三种手法的原理、区别以及在实际代码审计中该如何快速识别和防范。

这篇文章,我就以这道题为引子,结合我这些年做代码审计和渗透测试遇到的实际案例,带你彻底搞懂PHP变量覆盖。无论你是想深入理解PHP安全特性的开发者,还是正在入门安全研究的学习者,相信这些从实战中提炼出的细节和“坑点”,都能让你有所收获。

2. 核心漏洞原理与三种利用方式深度解析

在深入题目之前,我们必须先夯实理论基础。PHP变量覆盖漏洞的核心,在于程序在初始化或使用变量时,逻辑上存在缺陷,使得外部输入能够意外地改变程序内部变量的值。这通常发生在一些具有“将数组键值对注册为变量”功能的函数或特定场景下。

2.1 利用方式一:extract()函数的“魔法”

extract()函数是导致变量覆盖的“头号嫌疑犯”。它的作用是将一个数组(通常是$_GET,$_POST等)中的键值对,转换成当前符号表中的变量,键名作为变量名,键值作为变量值。

危险用法示例:

// 假设程序先定义了一个关键变量 $is_admin = false; // 然后不慎使用了extract处理用户输入 extract($_GET); // 此时,如果用户传入 ?is_admin=1 // 那么原本的 $is_admin = false 会被覆盖为 $is_admin = ‘1‘ 或 1(取决于类型转换) if ($is_admin) { // 攻击者成功绕过验证,进入管理后台 echo “Welcome, Admin!“; }

关键参数EXTR_OVERWRITE:extract()的第二个参数可以指定冲突解决策略。默认情况下,其值为EXTR_OVERWRITE,这意味着如果新变量名与已有变量冲突,它将覆盖已有的变量。这正是漏洞的根源。安全的做法是使用EXTR_SKIP(跳过已有变量)或EXTR_PREFIX_ALL(为所有变量添加前缀),但开发者往往为了省事而使用默认值或直接忽略第二个参数。

实操心得:在代码审计时,看到extract($_GET)或extract($_POST)且没有设置安全的第二个参数(如EXTR_SKIP),基本就可以标记为一个高危风险点。我曾在一个内容管理系统的后台登录逻辑里发现过这样的代码,直接导致无需密码就能以管理员身份登录。

2.2 利用方式二:parse_str()函数与未初始化的变量

parse_str()函数用于将查询字符串(类似name=John&age=30)解析到变量中。它的行为与extract()类似,但通常用于处理一个字符串。

危险用法示例:

// 用户可控的输入 $input = $_SERVER[‘QUERY_STRING‘]; // 例如:”cmd=whoami&token=abc“ // 错误用法:第二个参数省略,变量直接注册到当前作用域 parse_str($input); // 此时,变量 $cmd 和 $token 被创建并赋值 // 如果后续代码有这样的逻辑: if ($token === ‘secret_key‘) { system($cmd); // 远程代码执行! }

如果parse_str()没有第二个参数(一个数组变量,用于接收解析结果),它会直接将解析出的变量注册到当前作用域。如果这些变量名在之前已经被定义(比如$token在配置文件里被定义为‘secret_key‘),那么它们又会被覆盖。

安全用法:

$params = []; parse_str($input, $params); // 安全,结果存入$params数组 // 后续通过 $params[‘cmd‘] 来访问,不会污染变量空间

注意事项:parse_str()的漏洞常常和“未初始化变量”的警告联系在一起。在旧版本PHP或错误报告等级较低时,即使变量未定义就直接使用,程序也可能继续运行,这给了攻击者定义关键变量的机会。务必确保parse_str()总是使用第二个参数。

2.3 利用方式三:$$可变变量与$_REQUEST的“特性”

这是最隐蔽也最需要理解PHP特性的一种方式。它利用了“可变变量”和PHP全局变量注册机制的历史遗留问题。

可变变量(Variable Variables):$$a的含义是,先取得$a的值,将这个值作为一个变量名,再访问那个变量的值。例如:

$var_name = “user“; $$var_name = “admin“; // 等价于 $user = “admin“;

漏洞场景模拟:

// 假设有一段旧的、不安全的注册全局变量的代码(现已不推荐) foreach ($_REQUEST as $key => $value) { $$key = $value; // 危险操作! } // 程序其他地方定义了关键变量 $allowed = false; // 攻击者构造请求:?allowed=1 // 解析过程:$key=‘allowed‘, $value=‘1‘ => $$key 即 $allowed = ‘1‘ // 变量 $allowed 被覆盖 if ($allowed) { // 再次被绕过 }

这里,$_REQUEST是一个包含了$_GET,$_POST,$_COOKIE数据的超全局数组。通过foreach循环和$$操作,攻击者可以覆盖任何已定义的变量。

排查技巧:这种模式在现代框架中已很少见,但在一些遗留的老旧系统或自定义简易框架中仍有发现。审计时搜索“$$”和“$_REQUEST”、“$_GET”同时出现的代码段,重点关注循环体内的变量赋值逻辑。

三种方式对比总结:

利用方式关键函数/语法触发条件隐蔽性常见场景
extract()覆盖extract($_GET)默认EXTR_OVERWRITE或未安全配置中等控制器参数处理、配置加载
parse_str()覆盖parse_str($input)省略第二个参数较高解析URL参数、处理回调数据
$$可变变量覆盖foreach($_REQUEST as $k=>$v){$$k=$v;}使用了$_REQUEST与$$组合高老旧框架的全局变量注册机制

理解了这三种武器的原理,我们就能像侦探一样,带着明确的目标去审视[BJDCTF2020]的题目了。

3. [BJDCTF2020]题目实战拆解与逐步利用

现在,让我们进入实战环节。假设题目提供了一个简单的PHP页面,核心代码(经过简化提炼)逻辑如下,我们需要通过变量覆盖漏洞获取flag。

// 题目初始代码框架 error_reporting(0); $flag = ‘flag{this_is_a_fake_flag}‘; // 真flag在服务器上 $id = $_GET[‘id‘]; $token = $_GET[‘token‘]; $key = $_GET[‘key‘]; // 第一重检查:extract()漏洞点 if (isset($_GET[‘option1‘])) { extract($_GET); if ($id != 1) { die(‘id check failed!‘); } // 通过第一关后,进入第二段逻辑 } // 第二重检查:parse_str()漏洞点 if (isset($_GET[‘option2‘])) { $data = $_SERVER[‘QUERY_STRING‘]; parse_str($data); if ($token != ‘BJD‘) { die(‘token check failed!‘); } // 通过第二关后,进入第三段逻辑 } // 第三重检查:$$可变变量漏洞点 if (isset($_GET[‘option3‘])) { foreach($_REQUEST as $k => $v){ $$k = $v; } if ($key == ‘ctf‘) { echo “Congratulations! The flag is: “ . $flag; } }

我们的目标是:依次通过三个关卡,最终让程序输出真正的$flag。

3.1 第一关:利用extract()覆盖$id

目标:通过extract($_GET),将程序内可能存在的$id变量覆盖为我们需要的值1。

观察:第一段代码检查$id != 1。如果我们直接传?id=1,在extract($_GET)执行前,$id已经被赋值为$_GET[‘id‘](假设为1)。但extract()执行时,$_GET数组中也有‘id‘=>‘1‘这个键值对,它会尝试再次将$id注册为变量。由于默认是EXTR_OVERWRITE,这不会有问题,$id依然是1,可以通过检查。

但这里有一个陷阱:注意代码顺序。$id = $_GET[‘id‘];这一行在extract()之前。这意味着,在extract()执行时,变量$id已经存在。如果extract()以EXTR_SKIP模式运行,它就不会覆盖已存在的$id。但题目用的是默认的EXTR_OVERWRITE,所以是安全的(对攻击者而言)。不过,更稳妥的利用方式是,我们不去依赖$id = $_GET[‘id‘];这行代码的赋值,而是完全通过extract()来“创造”或“覆盖”出$id=1这个状态。

Payload构造:

http://target.com/vuln.php?option1=1&id=1

原理:传入option1触发第一段逻辑。extract($_GET)将$_GET数组(包含‘id‘=>‘1‘)导入为变量,使得$id的值为字符串‘1‘。在弱类型比较$id != 1中,字符串‘1‘会被转换成整数1,比较1 != 1为false,因此通过检查。

踩坑记录:在实际测试中,我曾遇到过因为代码里对$id进行了严格的类型检查(如$id !== 1)而导致失败的情况。这时就需要确保传入的值在类型和内容上都完全匹配。对于extract(),它导入的都是字符串,如果代码是===全等比较,就需要想办法让变量在extract前不存在,完全由extract创建。有时需要结合其他参数让$id在extract前不被定义。

3.2 第二关:利用parse_str()覆盖$token

目标:通过parse_str($data),将$token变量覆盖为‘BJD‘。

观察:第二段代码从$_SERVER[‘QUERY_STRING‘]获取原始查询字符串,然后直接用parse_str()解析,没有使用第二个参数。这意味着整个查询字符串都会被解析并注册为变量。

关键点:$_SERVER[‘QUERY_STRING‘]是URL中间号?后面的部分,未经解析。而我们要同时触发第一关和第二关,需要传递option1和option2等多个参数。

Payload构造:

http://target.com/vuln.php?option1=1&id=1&option2=1&token=BJD

原理:

  1. option1=1触发第一关逻辑,并通过。
  2. 整个查询字符串“option1=1&id=1&option2=1&token=BJD“被赋值给$data。
  3. parse_str($data)执行,它会解析整个字符串,创建变量$option1,$id,$option2,$token。其中$token被赋值为‘BJD‘。
  4. 代码检查$token != ‘BJD‘,条件不成立,通过第二关。

注意事项:这里parse_str()解析出的$id会覆盖之前extract()创建的$id吗?不会,因为它们是两个独立的代码块,作用域相同。后执行的parse_str()会覆盖先存在的变量。但在本题逻辑中,第一关通过后,第二关的检查并不关心$id的值,所以没有影响。在实际复杂场景中,这种连续的变量覆盖需要仔细梳理变量状态的变化流程。

3.3 第三关:利用$$覆盖$key

目标:通过foreach($_REQUEST as $k=>$v){$$k=$v;},将$key变量覆盖为‘ctf‘。

观察:第三段代码遍历$_REQUEST数组,并用$$k=$v的方式动态创建变量。$_REQUEST包含了$_GET和$_POST等数据。

关键点:我们需要让$key的值等于‘ctf‘。那么,只需要在请求中提供一个名为key,值为ctf的参数即可。foreach循环遇到‘key‘=>‘ctf‘时,会执行$$k = $v即$key = ‘ctf‘。

最终Payload构造: 为了同时满足三个关卡,我们需要传递所有必要的参数。

http://target.com/vuln.php?option1=1&id=1&option2=1&token=BJD&option3=1&key=ctf

原理:

  1. option1和id通过第一关。
  2. option2和token通过第二关。
  3. option3触发第三关逻辑。$_REQUEST数组中包含‘key‘=>‘ctf‘,在循环中执行$key = ‘ctf‘。
  4. 检查$key == ‘ctf‘,条件成立,输出$flag。

一个更隐蔽的利用技巧: 注意第三关使用的是$_REQUEST。这意味着我们也可以通过POST请求传递key=ctf。这在某些只过滤了$_GET而忽略了$_POST或$_COOKIE的场景下非常有用。例如,我们可以用GET传递option1,option2,option3, 用POSTbody传递key=ctf, 增加绕过WAF或简单过滤的可能性。

curl -X POST “http://target.com/vuln.php?option1=1&id=1&option2=1&token=BJD&option3=1“ --data “key=ctf“

通过这三步,我们完整地演示了如何利用三种不同的变量覆盖方式,层层递进,最终达成目标。这道题像是一个精心设计的教学样本,将理论漏洞浓缩在了几十行代码里。

4. 漏洞挖掘、防御与代码审计实战指南

理解了利用方式,我们更重要的任务是学会如何在自己的项目或审计的项目中发现并修复这类问题。

4.1 漏洞挖掘与代码审计切入点

  1. 全局搜索危险函数:这是最直接的方法。在代码仓库或项目目录中,使用grep、ripgrep等工具搜索以下模式:

    # 搜索 extract, 重点关注参数是$_GET、$_POST、$_REQUEST等用户输入的情况 grep -r “extract.*\$_“ . --include=“*.php“ # 搜索 parse_str, 重点关注缺少第二个参数的调用 grep -r “parse_str(“ . --include=“*.php“ | grep -v “parse_str(.*, “ # 搜索可变变量与超全局数组的组合 grep -r “\$\$.*=.*\$_“ . --include=“*.php“ grep -r “foreach.*\$_REQUEST“ . --include=“*.php“
  2. 关注变量初始化流程:检查程序入口文件(如index.php,common.php)或框架的初始化部分,是否有将请求参数批量注册为全局变量的历史遗留代码。许多老旧的CMS或自定义框架会有这样的“快捷方式”。

  3. 跟踪用户输入流向:从$_GET,$_POST,$_COOKIE,$_REQUEST等超全局变量出发,跟踪它们是否被直接传递给了extract(),parse_str(), 或者是否被用于$$动态变量赋值。

  4. 注意包含(include)文件时的变量传递:include或require一个文件时,该文件会继承当前作用域的所有变量。如果攻击者能控制被包含的文件名(本地文件包含漏洞),并结合变量覆盖,可能会产生更严重的后果(如覆盖掉用于包含的变量,实现任意文件包含)。

4.2 安全编码与修复方案

原则:永远不要相信用户输入,对输入进行严格的验证和过滤。

  1. 禁用或安全使用extract():

    • 最佳实践:避免使用extract()函数。现代PHP开发中几乎没有必须使用它的场景。
    • 如果必须使用:永远不要对用户输入的数据(如$_GET,$_POST)使用extract()。如果要对配置数组使用,必须指定第二个参数为EXTR_SKIP或EXTR_PREFIX_ALL。
    // 危险 extract($_POST); // 相对安全(对已知的、受控的配置数组) $config = [‘db_host‘ => ‘localhost‘, ‘db_user‘ => ‘root‘]; extract($config, EXTR_SKIP); // 如果已有同名变量,则跳过 // 更安全(添加前缀,避免冲突) extract($config, EXTR_PREFIX_ALL, ‘cfg‘); // 生成的变量名为 $cfg_db_host, $cfg_db_user
  2. 安全使用parse_str():强制使用第二个参数,将解析结果存入数组。

    // 危险 parse_str($_SERVER[‘QUERY_STRING‘]); // 安全 $params = []; parse_str($_SERVER[‘QUERY_STRING‘], $params); // 然后通过 $params[‘key‘] 访问参数
  3. 杜绝$$与用户输入的直接结合: 绝对不要用用户输入的键名直接作为可变变量名。如果需要动态访问变量,应该使用数组。

    // 危险 foreach ($_REQUEST as $key => $value) { $$key = $value; } // 安全:将用户输入存入一个特定的数组 $userInput = []; foreach ($_REQUEST as $key => $value) { $userInput[$key] = filter_var($value, FILTER_SANITIZE_STRING); // 并进行过滤 } // 后续通过 $userInput[‘key‘] 访问
  4. 使用现代框架并遵循其规范: 主流PHP框架(如Laravel, Symfony, ThinkPHP)都有成熟的请求(Request)对象来处理输入,它们将输入数据封装在对象或特定数组中,从根本上避免了全局变量污染和变量覆盖的问题。例如,在Laravel中,你通过$request->input(‘key‘)或request(‘key‘)来获取输入,非常安全。

  5. 配置php.ini: 在php.ini中,可以将register_globals设置为Off(这已是PHP默认且早已废弃的特性,但检查一下无害)。更重要的是,确保display_errors在生产环境中为Off,防止错误信息泄露路径等敏感信息,虽然这不能防止漏洞,但能增加攻击难度。

4.3 在CTF与实战中的高级利用思路

变量覆盖漏洞很少孤立存在,它常常是串联其他漏洞、扩大攻击面的“桥梁”。

  1. 结合文件包含(LFI/RFI): 假设有一段代码:include($page . ‘.php‘);, 其中$page默认是‘home‘。如果存在变量覆盖漏洞,攻击者可以覆盖$page为‘../../../etc/passwd‘, 就可能造成本地文件包含。如果再允许远程包含(allow_url_include=On),后果更严重。

  2. 覆盖配置或认证变量: 这是最直接的危害。覆盖$isAdmin,$loggedIn,$authKey等变量,直接提升权限或绕过认证。

  3. 覆盖数据库连接参数: 覆盖$db_host,$db_user等,可能用于SQL注入(如将$db_host覆盖为‘localhost;init_command=SET...‘,取决于数据库驱动),或者将连接指向攻击者控制的数据库服务器,窃取数据。

  4. 覆盖序列化对象属性: 如果程序使用了serialize()和unserialize(),并且存在变量覆盖,攻击者可能覆盖反序列化过程中用到的类属性,进而触发魔术方法(如__wakeup,__destruct),实现反序列化漏洞利用。

实战心得:在一次内部渗透测试中,我发现一个后台系统使用了extract($_POST)来处理配置保存。我通过覆盖一个用于记录日志文件路径的变量$log_file,将其指向Web目录下的一个PHP脚本。随后触发一个正常操作产生日志,系统将我的恶意代码写入了这个“日志文件”,从而实现了Webshell的写入。这个案例说明,变量覆盖的影响范围可能远超当前页面逻辑。

5. 常见问题排查与工具使用技巧

在实际开发和审计中,会遇到一些具体的问题。这里记录几个常见的场景和解决方法。

问题1:代码中用了extract(),但似乎覆盖不了变量?

  • 可能原因1:作用域问题。extract()默认只在当前作用域(通常是函数或方法内部)创建变量。如果你在函数外用extract()处理数组,然后在函数内检查变量,那变量是不存在的,除非你使用了global关键字或$GLOBALS数组。
  • 排查:确认extract()调用点和目标变量使用点是否在同一作用域。可以尝试在调用extract()后,立即print_r(get_defined_vars())查看当前所有变量。
  • 可能原因2:冲突解决参数。确认第二个参数不是EXTR_SKIP或EXTR_PREFIX_ALL等安全模式。

问题2:parse_str()用了第二个参数,但还是出现了变量污染?

  • 可能原因:代码中可能存在两处parse_str()调用,一处安全,一处不安全。或者,在调用安全的parse_str($input, $arr)之后,又错误地使用了extract($arr)。
  • 排查:全局搜索所有parse_str调用,逐一确认。同时检查$arr这个结果数组后续是如何被使用的。

问题3:如何自动化检测项目中的变量覆盖漏洞?

  • 静态代码分析工具(SAST):
    • RIPS:一款经典的PHP静态代码分析工具,专门用于安全审计,能很好地识别extract(),parse_str()等漏洞。
    • SonarQube (with PHP Plugin):企业级代码质量平台,其安全规则库可以检测部分不安全的函数使用。
    • Phan / Psalm:这些是PHP的静态分析工具,主要关注类型错误,但通过自定义规则插件,也可以用来检测危险函数。
  • 手动辅助脚本:可以写一个简单的Python或Shell脚本,用正则表达式匹配危险模式,并进行初步筛选。
    # 简单示例:查找危险的extract调用 import re import os pattern = re.compile(r‘extract\s*\(\s*(\$\_(GET|POST|REQUEST|COOKIE))‘) for root, dirs, files in os.walk(‘./project‘): for file in files: if file.endswith(‘.php‘): path = os.path.join(root, file) with open(path, ‘r‘, encoding=‘utf-8‘, errors=‘ignore‘) as f: content = f.read() if pattern.search(content): print(f‘Potential vulnerability in: {path}‘)

问题4:在CTF中,遇到变量覆盖但不知道覆盖哪个变量怎么办?

  • 信息收集:首先尝试通过错误信息泄露(如开启display_errors时)获取线索。如果不行,考虑“盲覆盖”。
  • 盲覆盖尝试:
    1. 覆盖常见变量名:尝试覆盖flag,token,key,auth,admin,is_login,check等常见变量名。
    2. Fuzz变量名:如果题目是黑盒测试,可以使用字典对参数名进行Fuzz,观察响应变化。例如,用Burp Suite的Intruder模块,加载一个常见变量名的字典进行爆破。
    3. 分析代码逻辑:如果是白盒或灰盒,仔细阅读题目给出的有限代码片段,寻找条件判断语句(if)中使用的变量,这些很可能就是需要覆盖的目标。

问题5:修复漏洞后,如何验证修复是否有效?

  • 单元测试:为存在漏洞的代码段编写安全的单元测试用例,模拟攻击者传入恶意参数,断言程序行为符合预期(如返回错误、不覆盖变量等)。
  • 动态测试:使用修复后的代码部署测试环境,用之前的攻击Payload进行测试,确认无法再成功利用。
  • 代码复查:将修复代码提交给其他开发者或安全人员进行复查,确保没有引入新的问题,并且修复方式是彻底的(例如,不仅仅是给extract()加了EXTR_SKIP,而是彻底重构了代码,移除了extract)。

变量覆盖漏洞的原理并不复杂,但其危害性和隐蔽性不容小觑。它提醒我们,在PHP开发中,良好的编码习惯和对语言特性的深刻理解至关重要。从[BJDCTF2020]这道题出发,我们系统地梳理了三种利用方式、审计方法、修复方案以及实战技巧。下次当你看到extract(),parse_str()或者$$与用户输入纠缠在一起时,希望你立刻能绷紧安全这根弦。最好的防御,始于编码时的一念之间。

相关新闻

  • 5分钟掌握Windows任务栏透明化:TranslucentTB终极使用指南
  • 汽车级MCU评估板硬件设计解析:从电源树到调试接口的实战指南
  • 网盘直链下载助手LinkSwift:九大平台技术解析与深度配置指南

最新新闻

  • 高性能收音机系统设计:Si4732与PIC32MX675F256L实战解析
  • ChatGPT写文案到底靠不靠谱?实测172个行业案例后,我删掉了93%的AI初稿——真正能过审的4条黄金法则
  • 如何快速修复损坏视频:untrunc终极完整修复指南
  • 3步实现Markdown笔记完美迁移:Zotero-Better-Notes导入功能终极指南
  • STM32F745ZG驱动WS2812B灯带开发指南
  • 13DOF传感器与PIC18LF47K42实现高精度定位导航方案

日新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

周新闻

  • Windows字体自定义终极方案:No!! MeiryoUI完全指南
  • Deepin Boot Maker:告别命令行,3分钟制作Linux启动盘的智能解决方案
  • Plain Craft Launcher 2:重新定义你的Minecraft游戏体验

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号