文章目录

  • 前言
  • 题目一
  • 题目二
  • 题目三
  • 总结:


前言

上一讲我们已经了解了PHP的基础知识点,这一讲我们来学习一下ctf中PHP具体知识点的运用。


题目一

这是攻防世界中新手区所列举的一道有关PHP知识点的题目,比较基础。

我们首先查看一下代码,发现其实比较简单,只是需要get传参a,b的值,以及有关于a,b的条件判断语句,a参数的要求 a必须等于0且a为真,b参数的要求 b不能为数字且b大于1234。
在此我们可以先尝试传一个a的值(符合条件即可)可出现以下这一情况

但我们可知道这不是完整的flag,所以肯定还有条件我们未用上。这是在考虑b的范围,我们再尝试输入b的值(符合条件),

这题最终就完成了。细看这一题,感觉需要掌握的知识点如下:
1.
松散比较:使用两个等号 == 比较,只比较值,不比较类型。
严格比较:用三个等号 === 比较,除了比较值,也比较类型。
2.
is_numeric() 函数用于检测变量是否为数字或数字字符串。
返回值
如果指定的变量是数字和数字字符串则返回 true,否则返回false,注意浮点型返回 1,即 true。
php中弱类型比较时,会使(‘1234a’ == 1234)为真。

这是因为PHP弱类型的转化规则
1.字符串中开头部分符合整数格式时,字符串将被转换为整数。
2.若开头为浮点数格式,字符串将会被转换为浮点数
3.若开头字符串既不是数字格式,则会被转换为0.

var_dump(123=="123abc")    bool (true);
var_dump("abc"==0)    bool (true);

题目二


我们先查看PHP文件好像没啥效果。再尝试一下phps文件形式。


审计代码得,首先不能 admin 等于 get 传过来的值又要使 admin 等于 get 传值
在 get 传值之前有一个 urldecode 函数。所以这个题需要的就是直接url编码两次就好了。我们直接使用bp可得

然后

题目至此解出。
本题的知识点个人感觉可以去了解一下
1.phps文件就是php的源代码文件,通常用于提供给用户(访问者)直接通过Web浏览器查看php代码的内容。
因为用户无法直接通过Web浏览器“看到”php文件的内容,所以需要用phps文件代替。
2.PHP中get和post的区别
Get是通过Url方式传送数据,可以直接看到,明文传输。而Post并不让用户看到传送的具体信息,POST是通过请求header请求,可以开发者工具或者抓包可以看到,同样也是明文的。

Get在服务器端$_GET;

Post在服务器端$_POST

get限制Form表单的数据集的值必须为ASCII字符,不能通过request.setCharacterEncoding(“utf-8”);设置中文字符,服务器得到的中文字符可能为乱码!
post支持整个字符集ISO10646,可以通过request.setCharacterEncoding(“utf-8”);正确显示中文字符。
3.URL解码
URL 只能使用 ASCII 字符集来通过因特网进行发送。
也就是说URL只能使用英文字母、数字和- _ . ~这一些特殊的符号,可以保留。
Url编码通常也被称为百分号编码。
使用%百分号加上两位的字符——0123456789ABCDEF——代表一个字节的十六进制形式,对于ASCII字符,字母a 在ASCII码中对应的字节是0x61,那么Url编码之后得到的就是%61,字母ab, url编码后得到的就是%61%62。
对于非ASCII字符,使用utf-8对其进行编码得到相应的字节,然后对每个字节执行百分号编码。
如"中文"使用UTF-8字符集得到的字节为0xE4 0xB8 0xAD 0xE6 0x96 0x87,经过Url编码之后得到"%E4%B8%AD%E6%96%87"。
需要注意的是
**encodeURL()**是对于整个URL编码。
不会对于ASCll字母,数字,- !@#$ &()= :;+’ 进行编码。
**encodeURLComponent()**对于URL中的参数进行编码。不会对于数字,ASCll字母,~!
()'等进行编码。

var param = "http://www.b?t=123&s=456"; // 要被编码的参数
URL = "http://www.a?foo="+encodeURIComponent(param);
//"http://www.a?foo=http%3A%2F%2Fwww.b%3Ft%3D123%26s%3D456"

解码参考手册
解码工具

题目三



首先查看代码,发现了几个陌生的东东。
_construct() ,_destruct() ,_wakeup() , unserialize ,preg_match();看来解决这一题的关键可能就是了解这一些语法了。
1.魔术方法

__destruct()  结束时销毁对象
__call()    #在对象中调用一个不可访问方法时调用
__callStatic()    #用静态方式中调用一个不可访问方法时调用
__set()    #设置一个类的成员变量时调用
__isset()    #当对不可访问属性调用isset()empty()时调用
__unset()    #当对不可访问属性调用unset()时被调用。
__invoke()    #调用函数的方式调用一个对象时的回应方法
__set_state()    #调用var_export()导出类时,此静态方法会被调用。
__clone()    #当对象复制完成时调用
__autoload()    #尝试加载未定义的类
__debugInfo()    #打印所需调试信息

_wakeup 反序列化之前调用。(当序列化字符串中表示对象属性个数的值大于真实的属性的个数是会跳过_wakeup的执行)

//构造序列化对象
O:6:" Person" :3:{s : 4: " name";s:7: " Anemore";s:3:"sex";}
//构造 绕过_wakeup
O:6:" Person" :4:{s : 4: " name";s:7: " Anemore";s:3:"sex";}

其它的魔幻函数大家可以了解一下,具体的用法不在此出描述。
2.unserialize
序列化 (serialize)
serialize()函数用于序列化对象或者数组,并返回一个字符串。
string serialize(mixed $value);
返回值:字符串; 输出:混合型。
unserialize(可以从序列化后的结果恢复对象);


图中两条箭头很好的表示了序列化和反序列化。
unserialize漏洞实现需要满足一些条件:
1.unserialize函数的参数可控
2.存在一个构造函数(__construct())、析构函数(__destruct()) wakeup()函数中有向php文件中写数据的操作的类
3.所写的内容需要有对象中的成员变量的值
3.正则表达式
正则表达式描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。
普通字符
普通字符包括没有显式指定为元字符的所有可打印和不可打印字符。这包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号。
举例:
[A-Z] 表示一个区间,匹配所有大写字母,[a-z] 表示所有小写字母。
定位符
定位符使您能够将正则表达式固定到行首或行尾。它们还使您能够创建这样的正则表达式,这些正则表达式出现在一个单词内、在一个单词的开头或者一个单词的结尾。
定位符用来描述字符串或单词的边界,^ 和 $ 分别指字符串的开始与结束,\b 描述单词的前或后边界,\B 表示非单词边界。


具体了解菜鸟教程

总结:

本周写了部分PHP相关一些题目,选取了部分题目并相对详细解释了一些知识点。之后还会对PHP考点有所补充。

更多推荐

CTF中PHP知识点的小运用(二)